diff --git a/geoip-lookup.py b/geoip-lookup.py new file mode 100755 index 0000000..134dea4 --- /dev/null +++ b/geoip-lookup.py @@ -0,0 +1,96 @@ +#!/usr/bin/python3.8 + +import getopt +import sys + +try: + import geoip2.database +except ImportError: + print( + "Required module geoip2.database not found. On Gentoo Linux, please install dev-python/geoip2 from the 'fritteli' overlay.", + file=sys.stderr) + exit(1) + + +class LookupException(Exception): + """ + General Exception class that is raised if anything goes wrong. + """ + pass + + +def get_county_code(ipaddress, dbfile): + """ + Determine the country code that the given ipaddress comes from. + :param ipaddress: The IP address to look up + :param dbfile: The path to the GeoIP2/GeoLite2 database file (Country or City database) + :return: The ISO country code (2 letters) + """ + if not ipaddress: + raise LookupException("No address given") + if not dbfile: + raise LookupException("No db file given") + + reader = None + try: + reader = geoip2.database.Reader(dbfile) + dbtype = reader.metadata().database_type + country = None + if dbtype == 'GeoLite2-City' or dbtype == 'GeoIP2-City': + country = reader.city(ipaddress).country + elif dbfile == 'GeoLite2-Country' or dbtype == 'GeoIP2-Country': + country = reader.country(ipaddress).country + # ASN is not supported + # elif dbfile == 'GeoLite2-ASN' or dbtype == 'GeoIP2-ASN': + + if not country: + raise LookupException("Unsupported DB type: " + dbtype) + + return country.iso_code + finally: + if reader: + reader.close() + + +def parse_command_line(argv): + """ + Parse the command line. First, the database file must be specified ("-f /path/to/db/file.mmdb"), then the IP address + to look up + :param argv: + :return: + """ + dbfile = None + try: + opts, args = getopt.getopt(argv, "f:") + except getopt.GetoptError as e: + raise LookupException("Error parsing command line") from e + + for opt, arg in opts: + if opt == "-f": + dbfile = arg + else: + raise LookupException("Unknown command line argument") + + if len(args) == 0: + raise LookupException("No address given on command line") + return dbfile, args[0] + + +def main(argv): + """ + Read the database file and the IP address from the command line and print the corresponding ISO country code on + stdout. + :param argv: Format: "-f /path/to/database.mmdb ip.v4.add.ress" + :return: + """ + (dbfile, ipaddress) = parse_command_line(argv) + code = get_county_code(ipaddress, dbfile) + print(code) + + +if __name__ == '__main__': + try: + main(sys.argv[1:]) + except BaseException as e: + print("Usage: geoip-lookup.py -f /path/to/geoip2-database.mmdb 192.168.1.1", file=sys.stderr) + raise e