1010from six .moves import urllib
1111import cgi
1212import json
13+ import requests
1314import socket
15+ import geoip2 .database
1416
1517SITE = '//tools.wmflabs.org/whois-referral'
1618
3133 'Geolocation' : lambda x : 'https://whatismyipaddress.com/ip/%s' % x ,
3234}
3335
36+ geolite_file = '/data/project/whois-referral/GeoLite2-City_20200421/GeoLite2-City.mmdb'
37+ geoip_reader = None
38+ if os .path .exists (geolite_file ):
39+ geoip_reader = geoip2 .database .Reader (geolite_file )
40+
41+ ipinfo_file = '/data/project/whois-referral/ipinfo_token'
42+ ipinfo_token = None
43+ if os .path .exists (ipinfo_file ):
44+ try :
45+ f = open (ipinfo_file )
46+ ipinfo_token = f .read ().strip ()
47+ except :
48+ pass
49+
3450
3551def order_keys (x ):
3652 keys = dict ((y , x ) for (x , y ) in enumerate ([
53+ 'geolite2' , 'geo_ipinfo' ,
3754 'asn_registry' , 'asn_country_code' , 'asn_cidr' , 'query' ,
3855 'referral' , 'nets' , 'asn' , 'asn_date' ,
3956 'name' , 'description' , 'address' ,
@@ -50,10 +67,12 @@ def order_keys(x):
5067def lookup (ip , rdap = False ):
5168 obj = IPWhois (ip )
5269 if rdap :
53- # TODO: RDAP output includes less relevant info, needs a dedicated formatter
5470 return obj .lookup_rdap (asn_methods = ['dns' , 'whois' , 'http' ])
5571 else :
56- ret = obj .lookup_whois (get_referral = True , asn_methods = ['dns' , 'whois' , 'http' ])
72+ try :
73+ ret = obj .lookup_whois (get_referral = True , asn_methods = ['dns' , 'whois' , 'http' ])
74+ except WhoisLookupError :
75+ ret = obj .lookup_whois (asn_methods = ['dns' , 'whois' , 'http' ])
5776 # remove some fields that clutter
5877 for x in ['raw' , 'raw_referral' ]:
5978 ret .pop (x , None )
@@ -148,6 +167,28 @@ def format_page(form):
148167 result = {'error' : repr (e )}
149168 error = True
150169
170+ geoip_res = geoip_reader .city (ip )
171+ if geoip_res :
172+ try :
173+ result ['geolite2' ] = geoip_res .country .name
174+ if geoip_res .subdivisions .most_specific .name :
175+ result ['geolite2' ] = geoip_res .subdivisions .most_specific .name + ", " + result ['geolite2' ]
176+ if geoip_res .city .name :
177+ result ['geolite2' ] = geoip_res .city .name + ", " + result ['geolite2' ]
178+ except Exception as e :
179+ result ['geolite2' ] = "Unavailable: " + repr (e )
180+
181+ if ipinfo_token :
182+ ipinfo = requests .get ('https://ipinfo.io/' + ip + '/json?token=' + ipinfo_token )
183+ ipinfo_json = ipinfo .json ()
184+ if ipinfo_json and 'error' not in ipinfo_json :
185+ result ['geo_ipinfo' ] = ipinfo_json ['country' ]
186+ if 'region' in ipinfo_json :
187+ result ['geo_ipinfo' ] = ipinfo_json ['region' ] + ", " + result ['geo_ipinfo' ]
188+ if 'city' in ipinfo_json :
189+ result ['geo_ipinfo' ] = ipinfo_json ['city' ] + ", " + result ['geo_ipinfo' ]
190+
191+
151192 if fmt == 'json' and do_lookup :
152193 return 'Content-type: text/plain\n \n {}\n ' .format (json .dumps (result ))
153194
0 commit comments