def whois_info(self): """ Return WhoisInfo of the IP (AS Name/Number/CIDR/etc...,Subnet, CIDR, City,State,Country,Address, etc...) for an IP Address >>> from ipinformation import IPInformation >>> from pprint import pprint >>> pprint( IPInformation(ip_address='8.8.8.8').whois_info() ) {'whois': {'as': {'cidr': '8.8.8.0/24', 'country_code': 'US', 'creation_date': None, 'name': u'Google Inc.', 'number': 15169, 'registry': 'arin'}, 'error': 'no', 'raw': '\n#\n# ARIN WHOIS data and services are subject to the Terms of Use\n# available at: https://www.arin.net/whois_tou.html\n#\n# If you see inaccuracies in the results, please report at\n# http://www.arin.net/public/whoisinaccuracy/index.xhtml\n#\n\n\n#\n# The following results may also be obtained via:\n# http://whois.arin.net/rest/nets;q=8.8.4.4?showDetails=true&showARIN=false&showNonArinTopLevelNet=false&ext=netref2\n#\n\n\n# start\n\nNetRange: 8.0.0.0 - 8.255.255.255\nCIDR: 8.0.0.0/8\nNetName: LVLT-ORG-8-8\nNetHandle: NET-8-0-0-0-1\nParent: ()\nNetType: Direct Allocation\nOriginAS: \nOrganization: Level 3 Communications, Inc. (LVLT)\nRegDate: 1992-12-01\nUpdated: 2012-02-24\nRef: http://whois.arin.net/rest/net/NET-8-0-0-0-1\n\n\n\nOrgName: Level 3 Communications, Inc.\nOrgId: LVLT\nAddress: 1025 Eldorado Blvd.\nCity: Broomfield\nStateProv: CO\nPostalCode: 80021\nCountry: US\nRegDate: 1998-05-22\nUpdated: 2012-01-30\nComment: ADDRESSES WITHIN THIS BLOCK ARE NON-PORTABLE\nRef: http://whois.arin.net/rest/org/LVLT\n\n\nOrgTechHandle: IPADD5-ARIN\nOrgTechName: ipaddressing\nOrgTechPhone: +1-877-453-8353 \nOrgTechEmail: [email protected]\nOrgTechRef: http://whois.arin.net/rest/poc/IPADD5-ARIN\n\nOrgNOCHandle: NOCSU27-ARIN\nOrgNOCName: NOC Support\nOrgNOCPhone: +1-877-453-8353 \nOrgNOCEmail: [email protected]\nOrgNOCRef: http://whois.arin.net/rest/poc/NOCSU27-ARIN\n\nOrgAbuseHandle: APL8-ARIN\nOrgAbuseName: Abuse POC LVLT\nOrgAbusePhone: +1-877-453-8353 \nOrgAbuseEmail: [email protected]\nOrgAbuseRef: http://whois.arin.net/rest/poc/APL8-ARIN\n\n# end\n\n\n# start\n\nNetRange: 8.8.4.0 - 8.8.4.255\nCIDR: 8.8.4.0/24\nNetName: LVLT-GOGL-8-8-4\nNetHandle: NET-8-8-4-0-1\nParent: LVLT-ORG-8-8 (NET-8-0-0-0-1)\nNetType: Reallocated\nOriginAS: \nOrganization: Google Inc. (GOGL)\nRegDate: 2014-03-14\nUpdated: 2014-03-14\nRef: http://whois.arin.net/rest/net/NET-8-8-4-0-1\n\n\n\nOrgName: Google Inc.\nOrgId: GOGL\nAddress: 1600 Amphitheatre Parkway\nCity: Mountain View\nStateProv: CA\nPostalCode: 94043\nCountry: US\nRegDate: 2000-03-30\nUpdated: 2015-11-06\nRef: http://whois.arin.net/rest/org/GOGL\n\n\nOrgAbuseHandle: ABUSE5250-ARIN\nOrgAbuseName: Abuse\nOrgAbusePhone: +1-650-253-0000 \nOrgAbuseEmail: [email protected]\nOrgAbuseRef: http://whois.arin.net/rest/poc/ABUSE5250-ARIN\n\nOrgTechHandle: ZG39-ARIN\nOrgTechName: Google Inc\nOrgTechPhone: +1-650-253-0000 \nOrgTechEmail: [email protected]\nOrgTechRef: http://whois.arin.net/rest/poc/ZG39-ARIN\n\n# end\n\n\n\n#\n# ARIN WHOIS data and services are subject to the Terms of Use\n# available at: https://www.arin.net/whois_tou.html\n#\n# If you see inaccuracies in the results, please report at\n# http://www.arin.net/public/whoisinaccuracy/index.xhtml\n#\n\n', 'registration': [{'abuse_emails': None, 'address': '1025 Eldorado Blvd.', 'cidr': '8.0.0.0/8', 'city': 'Broomfield', 'country_code': 'US', 'creation_date': datetime.datetime(1992, 12, 1, 0, 0, tzinfo=<UTC>), 'description': 'Level 3 Communications, Inc.', 'handle': 'NET-8-0-0-0-1', 'misc_emails': None, 'name': 'LVLT-ORG-8-8', 'postal_code': '80021', 'range': '8.0.0.0-8.255.255.255', 'state': 'CO', 'tech_emails': None, 'updated': datetime.datetime(2012, 2, 24, 0, 0, tzinfo=<UTC>)}, {'abuse_emails': None, 'address': '1600 Amphitheatre Parkway', 'cidr': '8.8.8.0/24', 'city': 'Mountain View', 'country_code': 'US', 'creation_date': datetime.datetime(2014, 3, 14, 0, 0, tzinfo=<UTC>), 'description': 'Google Inc.', 'handle': 'NET-8-8-8-0-1', 'misc_emails': None, 'name': 'LVLT-GOGL-8-8-8', 'postal_code': '94043', 'range': '8.8.8.0-8.8.8.255', 'state': 'CA', 'tech_emails': None, 'updated': datetime.datetime(2014, 3, 14, 0, 0, tzinfo=<UTC>)}], }} >>> pprint( IPInformation(ip_address='127.0.0.1').whois_info() ) No Whois information for '127.0.0.1' because it is not a public ip {'whois': {'as': {'cidr': None, 'country_code': None, 'creation_date': None, 'name': None, 'number': None, 'registry': None}, 'raw': None, 'registration': [{'abuse_emails': None, 'address': None, 'cidr': None, 'city': None, 'country_code': None, 'creation_date': None, 'description': None, 'handle': None, 'misc_emails': None, 'postal_code': None, 'state': None, 'tech_emails': None, 'updated': None}], }} """ def null_whois_info(): data = { "whois": { "as": { "cidr": None, "country_code": None, "creation_date": None, "name": None, "number": None, "registry": None, }, "raw": None, "registration": [ { "abuse_emails": None, "address": None, "cidr": None, "city": None, "country_code": None, "creation_date": None, "description": None, "handle": None, "misc_emails": None, "postal_code": None, "state": None, "tech_emails": None, "updated": None, } ], } } return data if ( self.is_public() ): # TODO:Other stats with \n... for k,v in dict.items(): value=v.replace('\n','') dict[k]=value # TODO:What about noc, tech, and abuse information data = {"whois": {"as": {}}} # Perform whois lookup for IP and DNS query for AS information and disable whois for AS information. try: d = ipwhois.IPWhois(self.ip_address, allow_permutations=False).lookup_whois(inc_raw=True) except ipwhois.HTTPLookupError: print "No Whois information for '%s' because HTTPLookupError." % (self.ip_address) logging_file.error("No Whois information for '{0}' because HTTPLookupError.".format(self.ip_address)) data = null_whois_info() data["whois"].update({"error": "yes"}) data["whois"].update( {"error_message": "No Whois information for '%s' because HTTPLookupError." % (self.ip_address)} ) return data except ipwhois.WhoisLookupError: print "No Whois information for '%s' because WhoisLookupError" % (self.ip_address) logging_file.error("No Whois information for '{0}' because WhoisLookupError.".format(self.ip_address)) data = null_whois_info() data["whois"].update({"error": "yes"}) data["whois"].update( {"error_message": "No Whois information for '%s' because WhoisLookupError." % (self.ip_address)} ) return data except (ipwhois.ASNLookupError, ipwhois.ASNRegistryError): print "No ASN information for '{0}' because ASNLookupError.".format(self.ip_address) logging_file.error( "No ASN & Whois information for '{0}' because ASNLookupError.".format(self.ip_address) ) data = null_whois_info() data["whois"].update({"error": "yes"}) data["whois"].update( {"error_message": "No ASN & Whois information for '%s' because ASNLookupError." % (self.ip_address)} ) return data # AS Number try: # asnum = [ int(a) for a in d.get('asn').split(' ')[0] ] #TODO:Remove eventually asnum = [int(a) for a in d.get("asn").split(" ")][ 0 ] # Only grab the first one, do not want to make this a list anymore data["whois"]["as"].update({"number": asnum}) as_num_failure = False except (ValueError, TypeError, UnboundLocalError) as error: logging_file.error( 'No ASNumber from whois information for "{0}". Due to:\n{1}'.format(self.ip_address, error) ) as_num_failure = True # Get ASN Information from Maxmind DB in case of AS Number error and to get AS Name because that is not populated from whois anyways as_maxmind = geoipv4_as.asn_by_addr(self.ip_address) if as_maxmind: as_maxmind = as_maxmind.decode("utf-8", "replace") # Assign it as a regex group as_info = re.search(asn_info_regex, as_maxmind.encode("utf-8")) try: # Get ASNumber asnum_maxmind = int(as_info.group(1)) if as_num_failure: # Assign ASNumber from maxmind if whois ASNumber grab failed data["whois"]["as"].update({"number": asnum_maxmind}) # Get ASName asname_maxmind = as_info.group(2) data["whois"]["as"].update({"name": asname_maxmind}) except (ValueError, TypeError, AttributeError) as error: logging_file.error( 'No Maxmind AS information for "{0}". Due to:\n{1}'.format(self.ip_address, error) ) if as_num_failure: # Only assign none for ASNumber if not already grabbed data["whois"]["as"].update({"number": None}) data["whois"]["as"].update({"name": None}) else: logging_file.info( 'No Maxmind AS information for "{0}" could be found in the database.'.format(self.ip_address) ) if as_num_failure: # Only assign none for ASNumber if not already grabbed data["whois"]["as"].update({"number": None}) data["whois"]["as"].update({"name": None}) # AS Country Code data["whois"]["as"].update({"country_code": d.get("asn_country_code")}) # AS Registry data["whois"]["as"].update({"registry": d.get("asn_registry")}) # AS CIDR as_cidr = d.get("asn_cidr") if as_cidr != "NA": data["whois"]["as"].update({"cidr": as_cidr}) else: data["whois"]["as"].update({"cidr": None}) # AS Creation Date data["whois"]["as"].update({"creation_date": time_info.convert_time(d.get("asn_date")).convert_to_utc()}) # Registration Information by Subnet for registration in d.get("nets"): reg = dict() # Country Code reg.update({"country_code": registration.get("country")}) # City reg.update({"city": registration.get("city")}) # State reg.update({"state": registration.get("state")}) # CIDR cidr = registration.get("cidr") reg.update({"cidr": cidr}) # Range try: range = "%s-%s" % (netaddr.IPNetwork(cidr).network, netaddr.IPNetwork(cidr).broadcast) reg.update({"range": range}) except ValueError: reg.update({"range": None}) # Description reg.update({"description": registration.get("description")}) # Name reg.update({"name": registration.get("name")}) # Handle reg.update({"handle": registration.get("handle")}) # Updated reg.update({"updated": time_info.convert_time(registration.get("updated")).convert_to_utc()}) # Created reg.update({"creation_date": time_info.convert_time(registration.get("created")).convert_to_utc()}) # Postal Code reg.update({"postal_code": registration.get("postal_code")}) # Address reg.update({"address": registration.get("address")}) # Abuse Emails abuse_emails = registration.get("abuse_emails") if abuse_emails: abuse_emails = abuse_emails.split("\n") reg.update({"abuse_emails": abuse_emails}) # Miscellaneous Emails misc_emails = registration.get("misc_emails") if misc_emails: misc_emails = misc_emails.split("\n") reg.update({"misc_emails": misc_emails}) # Tech Emails tech_emails = registration.get("tech_emails") if tech_emails: tech_emails = tech_emails.split("\n") reg.update({"tech_emails": tech_emails}) # TODO:Sub referrals # Update reg information data["whois"].setdefault("registration", []).append(reg) # Add Raw WhoIs data["whois"].update({"raw": d.get("raw")}) # Reverse IP / PTR Record # try: # reverse_ip = ipwhois.Net(self.ip_address).get_host()[0] # data['whois'].update( { 'reverse_ip': reverse_ip } ) # # except (ipwhois.HostLookupError, IndexError): # data['whois'].update( { 'reverse_ip': None } ) # Assign error status data["whois"].update({"error": "no"}) # Assign all null values if not public IP else: # print 'No Whois information for "%s" because it is not a public IP Address.' %self.ip_address logging_file.info( "No Whois information for '{0}' because it is not a public IP Address.".format(self.ip_address) ) data = null_whois_info() return data
def maxmind_AS(self): """ Use Maxmind DB to gather ASName and ASNumber instead of doing a network lookup for it. >>> from ipinformation import IPInformation >>> from pprint import pprint >>> pprint( IPInformation(ip_address='8.8.8.8').maxmind_AS() ) {'as': {'name': 'Google Inc.', 'number': 15169, 'error': False }} """ # Create dictionary for data to return data = {"as": {}} # Verify is IP if self.ISIP: # Verify is public IP if self.is_public(): # Query Maxmind DB for info as_maxmind = geoipv4_as.asn_by_addr(self.ip_address) if as_maxmind: as_maxmind = as_maxmind.decode("utf-8", "replace") # Assign it as a regex group as_info = re.search(asn_info_regex, as_maxmind.encode("utf-8")) # Assign no error in beginning data["as"].update({"error": False}) try: # Get ASNumber asnum_maxmind = int(as_info.group(1)) data["as"].update({"number": asnum_maxmind}) except (ValueError, TypeError, AttributeError, None): data["as"].update({"number": None}) data["as"].update({"error": True}) try: # Get ASName asname_maxmind = as_info.group(2) data["as"].update({"name": asname_maxmind}) except (ValueError, TypeError, AttributeError, None): data["as"].update({"name": None}) data["as"].update({"error": True}) else: logging_file.info( 'No Maxmind AS information for "{0}" could be found in the database.'.format(self.ip_address) ) data["as"].update({"number": None}) data["as"].update({"name": None}) data["as"].update({"error": True}) else: data["as"].update({"number": None}) data["as"].update({"name": None}) data["as"].update({"error": False}) # Not an IP else: data["as"].update({"number": None}) data["as"].update({"name": None}) data["as"].update({"error": True}) return data
def geo_info(self): """ Return Geo location information (City,State,Country,etc...) for an IP Address >>> from ipinformation import IPInformation >>> from pprint import pprint >>> pprint( IPInformation(ip_address='8.8.8.8').geo_info() ) {'geo': {'area_code': 650, 'city': u'Mountain View', 'continent': 'NA', 'coordinates': [37.3845, -122.0881], 'country_code': 'US', 'country_code3': 'USA', 'country_name': 'United States', 'error': 'no', 'dma_code': 807, 'latitude': 37.3845, 'longitude': -122.0881, 'metro_code': 'San Francisco, CA', 'postal_code': u'94040', 'region_code': u'CA', 'time_zone': 'America/Los_Angeles'}} >>> pprint( IPInformation(ip_address='127.0.0.1').geo_info() ) {'geo': {'general': {'area_code': None, 'asname': None, 'asnum': None, 'city': None, 'continent': None, 'coordinates': None, 'country_code': None, 'country_code3': None, 'country_name': None, 'dma_code': None, 'error': 'no', 'latitude': None, 'longitude': None, 'metro_code': None, 'postal_code': None, 'region_code': None, 'time_zone': None}}} """ def null_geo_ip(): d = { "city": None, "region_code": None, "asnum": None, "area_code": None, "time_zone": None, "dma_code": None, "metro_code": None, "country_code3": None, "country_name": None, "postal_code": None, "longitude": None, "country_code": None, "asname": None, "latitude": None, "coordinates": None, "continent": None, } return d data = {"geo": {}} if not self.ISIP: # print '"%s" is not a valid IP Address.' %self.ip_address logging_file.error('"{0}" is not a valid IP Address.'.format(self.ip_address)) data["geo"].update(null_geo_ip()) data["geo"].update({"error": "yes"}) return data else: if self.is_public(): city_information = geoipv4_city.record_by_addr(self.ip_address) if city_information: data["geo"].update(city_information) longitude = city_information.get("longitude") latitude = city_information.get("latitude") coordinates = [longitude, latitude] data["geo"].update({"coordinates": coordinates}) data["geo"].update({"error": "no"}) # Assign all null values if IP not found in Maxmind DB else: data["geo"].update(null_geo_ip()) data["geo"].update({"error": "yes"}) print 'No Maxmind GeoIP information for "{0}".'.format(self.ip_address) logging_file.info('No Maxmind GeoIP information for "{0}".'.format(self.ip_address)) # Assign all null values if not public IP else: data["geo"].update(null_geo_ip()) data["geo"].update({"error": "no"}) # TODO:Finish IPv6 return data