This script was developed to address a specific scenario where vendors provide a range of IP subnets to be whitelisted. In environments where geolocation-based blocking is implemented, verifying the geographic origins of these IP addresses is crucial.
The aim is to ensure that none of the IP addresses within the provided subnets originate from countries that are intended to be blocked as per our security policies. It is important to note that an IP block provided by a vendor may not necessarily correspond to a single geographic location. Even though it might appear as a single network block, it could contain subnets assigned to various countries.
Therefore, by simply testing the first available IP address in the vendor-provided block, we might not get an accurate representation of the entire range. Other subnets within that block could be assigned to different countries. This is why we’ve built this script, to verify each relevant subnet within the provided IP block, ensuring that none originate from our list of blocked countries. This helps maintain the integrity of our geolocation-based security measures.
# Author: Kerry Cordero
# Version: 1.0.0
# Description: This script prompt for the IP Address and then the SubnetMask/CIDR. It will output the IP, Country, Country Code, Region, City, Latitude, Longitude.
import requests
from prettytable import PrettyTable
import ipaddress
api_key = "da4fd73c8e152f70bdf56547a008785edd27f34e6862bde308e215ac"
def get_ip_location(ip):
url = f"https://api.ipdata.co/{ip}?api-key={api_key}"
response = requests.get(url)
data = response.json()
if "message" in data:
print("Error:", data["message"])
return None
else:
return {
"IP": data["ip"],
"Country": data["country_name"],
"Country Code": data["country_code"],
"Region": data["region"],
"City": data["city"],
"Latitude": data["latitude"],
"Longitude": data["longitude"]
}
def subnet_calculation(ip_address, subnet):
# Convert the IP address to IPv4Network object
network = ipaddress.IPv4Network(f"{ip_address}/{subnet}", strict=False)
# Create a PrettyTable instance
table = PrettyTable()
# Set the field names
table.field_names = ["IP", "Country", "Country Code", "Region", "City", "Latitude", "Longitude"]
# Create a list to hold /24 subnets
subnet_list = [ip for ip in network.subnets(new_prefix=24)]
# Iterate over each subnet and get location info for the first IP
for subnet in subnet_list:
first_ip = next(subnet.hosts())
location = get_ip_location(first_ip)
if location is not None:
# Add row
table.add_row([
location["IP"],
location["Country"],
location["Country Code"],
location["Region"],
location["City"],
location["Latitude"],
location["Longitude"]
])
# Print the table
print(table)
# Prompt the user for the IP address
ip_address = input("Enter the IP address: ")
# Prompt the user for the subnet
subnet_input = input("Enter the subnet (in CIDR notation or full write out): ")
# Extract the subnet prefix length from the input
if "/" in subnet_input:
subnet = int(subnet_input.split("/")[1])
else:
# Use the subnet mask to generate a dummy IPv4Interface object, then get its network's prefix length
dummy_interface = ipaddress.IPv4Interface(f"0.0.0.0/{subnet_input}")
subnet = dummy_interface.network.prefixlen
# Call the subnet_calculation function
subnet_calculation(ip_address, subnet)