"""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()