201 lines
5.6 KiB
Python
201 lines
5.6 KiB
Python
"""Probe the GeoLite2 database to find IPs that resolve to real countries.
|
|
|
|
Run inside the api container:
|
|
docker compose exec api python /app/probe_geo.py
|
|
|
|
Or locally if the DB is present:
|
|
python probe_geo.py /path/to/GeoLite2-City.mmdb
|
|
|
|
Tests a curated list of well-known public IPs and prints the ones that resolve.
|
|
"""
|
|
|
|
import sys
|
|
import json
|
|
import os
|
|
import maxminddb
|
|
|
|
# Well-known public IPs from various countries
|
|
CANDIDATE_IPS = [
|
|
# United States
|
|
("23.21.30.100", "US"),
|
|
("72.14.198.234", "US"),
|
|
("68.49.71.1", "US"),
|
|
("208.67.222.222", "US"), # OpenDNS
|
|
("74.125.200.100", "US"), # Google
|
|
("151.101.1.69", "US"), # Fastly
|
|
("142.250.80.46", "US"), # Google
|
|
("216.58.214.206", "US"), # Google
|
|
("172.217.164.110", "US"), # Google
|
|
("13.107.42.14", "US"), # Microsoft
|
|
("20.190.128.1", "US"), # Microsoft
|
|
("52.84.74.1", "US"), # AWS CloudFront
|
|
("99.86.0.1", "US"), # AWS
|
|
# United Kingdom
|
|
("81.2.69.142", "GB"),
|
|
("212.58.224.10", "GB"),
|
|
("51.140.137.15", "GB"),
|
|
("178.173.57.1", "GB"),
|
|
# France
|
|
("51.140.137.15", "FR"),
|
|
("193.70.150.1", "FR"),
|
|
# Japan
|
|
("210.170.232.46", "JP"),
|
|
("133.244.200.1", "JP"),
|
|
("202.214.69.1", "JP"), # NTT
|
|
("210.188.206.1", "JP"), # Softbank
|
|
# Germany
|
|
("217.160.0.1", "DE"),
|
|
("212.227.156.1", "DE"),
|
|
("2a02:2e0::1", "DE"), # IPv6 - may not resolve
|
|
("217.69.70.1", "DE"),
|
|
# Australia
|
|
("101.168.100.1", "AU"),
|
|
("203.50.224.1", "AU"),
|
|
("1.35.128.1", "AU"), # Telstra
|
|
# Brazil
|
|
("177.72.120.1", "BR"),
|
|
("200.149.130.1", "BR"),
|
|
("189.75.1.1", "BR"),
|
|
# Canada
|
|
("76.69.248.1", "CA"),
|
|
("24.199.12.1", "CA"),
|
|
("99.248.1.1", "CA"), # Bell
|
|
# India
|
|
("117.239.1.1", "IN"),
|
|
("180.151.1.1", "IN"),
|
|
("106.192.1.1", "IN"),
|
|
# South Korea
|
|
("1.235.198.1", "KR"),
|
|
("211.36.1.1", "KR"),
|
|
# Netherlands
|
|
("185.30.1.1", "NL"),
|
|
("94.23.1.1", "NL"),
|
|
# Mexico
|
|
("189.203.1.1", "MX"),
|
|
("200.44.1.1", "MX"),
|
|
# Italy
|
|
("217.20.1.1", "IT"),
|
|
("93.45.1.1", "IT"),
|
|
# Spain
|
|
("213.99.1.1", "ES"),
|
|
("88.0.1.1", "ES"),
|
|
# Sweden
|
|
("213.248.1.1", "SE"),
|
|
# Poland
|
|
("79.133.1.1", "PL"),
|
|
# Argentina
|
|
("190.15.1.1", "AR"),
|
|
# South Africa
|
|
("196.201.1.1", "ZA"),
|
|
# Egypt
|
|
("213.53.1.1", "EG"),
|
|
# Turkey
|
|
("37.146.1.1", "TR"),
|
|
# Russia
|
|
("77.88.55.1", "RU"), # Yandex DNS
|
|
("5.255.255.1", "RU"),
|
|
]
|
|
|
|
|
|
def probe(db_path: str):
|
|
"""Test each candidate IP against the GeoLite2 database."""
|
|
reader = maxminddb.open_database(db_path)
|
|
results = []
|
|
|
|
# Deduplicate IPs but keep all expected countries
|
|
seen_ips = set()
|
|
for ip, expected_country in CANDIDATE_IPS:
|
|
if ip in seen_ips:
|
|
continue
|
|
seen_ips.add(ip)
|
|
|
|
try:
|
|
result = reader.lookup(ip)
|
|
if result is None:
|
|
continue
|
|
|
|
country = result.get("country", {})
|
|
city = result.get("city", {})
|
|
location = result.get("location", {})
|
|
|
|
country_code = country.get("iso_code", "")
|
|
country_name = country.get("names", {}).get("en", country_code)
|
|
city_name = city.get("names", {}).get("en", "")
|
|
lat = location.get("latitude")
|
|
lon = location.get("longitude")
|
|
|
|
results.append({
|
|
"ip": ip,
|
|
"country": country_name,
|
|
"country_code": country_code,
|
|
"city": city_name,
|
|
"latitude": lat,
|
|
"longitude": lon,
|
|
})
|
|
except Exception as e:
|
|
print(f" ERROR looking up {ip}: {e}")
|
|
|
|
reader.close()
|
|
return results
|
|
|
|
|
|
def main():
|
|
# Determine DB path
|
|
db_path = None
|
|
|
|
if len(sys.argv) > 1:
|
|
# Explicit path provided
|
|
db_path = sys.argv[1]
|
|
else:
|
|
# Try common locations
|
|
candidates = [
|
|
"/app/geo/GeoLite2-City.mmdb", # container path
|
|
os.path.join(os.path.dirname(__file__), "geo", "GeoLite2-City.mmdb"), # local
|
|
]
|
|
for p in candidates:
|
|
if os.path.exists(p):
|
|
db_path = p
|
|
break
|
|
|
|
if db_path is None:
|
|
print("GeoLite2-City.mmdb not found.")
|
|
print("Usage:")
|
|
print(" docker compose exec api python /app/probe_geo.py")
|
|
print(" python probe_geo.py /path/to/GeoLite2-City.mmdb")
|
|
sys.exit(1)
|
|
|
|
print(f"Probing GeoLite2 at: {db_path}")
|
|
results = probe(db_path)
|
|
|
|
if not results:
|
|
print("No IPs resolved! The database might be empty or outdated.")
|
|
sys.exit(1)
|
|
|
|
print(f"\nResolved {len(results)} IPs:\n")
|
|
|
|
# Group by country
|
|
by_country = {}
|
|
for r in results:
|
|
by_country.setdefault(r["country_code"], []).append(r)
|
|
|
|
for cc in sorted(by_country.keys()):
|
|
entries = by_country[cc]
|
|
print(f" {cc} ({entries[0]['country']}):")
|
|
for e in entries:
|
|
print(f" {e['ip']:20s} -> {e['city'] or 'N/A':20s} ({e['latitude']}, {e['longitude']})")
|
|
|
|
# Output as Python tuples for inject_test_logs.py
|
|
print(f"\n\nTuples for inject_test_logs.py TEST_IPS:")
|
|
print("TEST_IPS = [")
|
|
for r in results:
|
|
print(f' ("{r["ip"]}", "{r["country"]}", "{r["city"]}"),')
|
|
print("]")
|
|
|
|
# Also output JSON for convenience
|
|
print(f"\nJSON output:")
|
|
print(json.dumps(results, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|