diff --git a/CHANGELOG.md b/CHANGELOG.md index f22fbb4..75e8cdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +6.8.0 +----- + +- Display warning when `GeoLite2-Country.mmdb` is missing, instead of trying to download it +- Add documentation for MaxMind `geoipupdate` changes on January 30th, 2019 (closes issues #137 and #139) + 6.7.4 ----- diff --git a/docs/index.rst b/docs/index.rst index 40e4dbc..0ba2faf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -493,6 +493,8 @@ On CentOS or RHEL systems, run: sudo yum install -y geoipupdate +Windows releases can be downloaded from the `releases page on GitHub`_. + On December 30th, 2019, MaxMind started requiring free accounts to access the free Geolite2 databases, in order `to comply with various privacy regulations`_. @@ -502,7 +504,8 @@ Then, navigate the to the `License Keys`_ page under your account, and create a You can use `parsedmarc` as the description for they key. Once you have generated a key, download the config pre-filled configuration file. -This file should be saved at ``/etc/GeoIP.conf``. +This file should be saved at ``/etc/GeoIP.conf`` on Linux or macOS systems, or at +`%SystemDrive%\ProgramData\MaxMind\GeoIPUpdate\GeoIP.conf` on Windows systems. Then run diff --git a/parsedmarc/__init__.py b/parsedmarc/__init__.py index 18e2fca..d5ccb9a 100644 --- a/parsedmarc/__init__.py +++ b/parsedmarc/__init__.py @@ -33,7 +33,7 @@ from parsedmarc.utils import is_outlook_msg, convert_outlook_msg from parsedmarc.utils import timestamp_to_human, human_timestamp_to_datetime from parsedmarc.utils import parse_email -__version__ = "6.7.4" +__version__ = "6.8.0" logging.basicConfig( format='%(levelname)8s:%(filename)s:%(lineno)d:' diff --git a/parsedmarc/utils.py b/parsedmarc/utils.py index dca076a..9147abe 100644 --- a/parsedmarc/utils.py +++ b/parsedmarc/utils.py @@ -263,55 +263,24 @@ def human_timestamp_to_timestamp(human_timestamp): return human_timestamp_to_datetime(human_timestamp).timestamp() -def get_ip_address_country(ip_address, parallel=False, offline=False): +def get_ip_address_country(ip_address): """ Uses the MaxMind Geolite2 Country database to return the ISO code for the country associated with the given IPv4 or IPv6 address Args: ip_address (str): The IP address to query for - parallel (bool): Parallel processing - offline (bool): Do not make online queries for geolocation and DNS Returns: str: And ISO country code associated with the given IP address """ - def download_country_database(location="GeoLite2-Country.mmdb"): - """Downloads the MaxMind Geolite2 Country database - - Args: - location (str): Local location for the database file - """ - if parallel or offline: - logging.warning("GeoLite2-Country.mmdb is missing." - "please install and run geoipupdate as root to " - "get the latest version.") - return - url = "https://geolite.maxmind.com/download/geoip/database/" \ - "GeoLite2-Country.tar.gz" - # Use a browser-like user agent string to bypass some proxy blocks - headers = {"User-Agent": USER_AGENT} - original_filename = "GeoLite2-Country.mmdb" - try: - response = requests.get(url, headers=headers) - response.raise_for_status() - tar_bytes = response.content - tar_file = tarfile.open(fileobj=BytesIO(tar_bytes), mode="r:gz") - tar_dir = tar_file.getnames()[0] - tar_path = "{0}/{1}".format(tar_dir, original_filename) - tar_file.extract(tar_path) - shutil.move(tar_path, location) - shutil.rmtree(tar_dir) - except Exception as e: - raise DownloadError("Error downloading {0}: {1}".format( - url, - e.__str__())) system_paths = [ "GeoLite2-Country.mmdb", "/usr/local/share/GeoIP/GeoLite2-Country.mmdb", "/usr/share/GeoIP/GeoLite2-Country.mmdb", "/var/lib/GeoIP/GeoLite2-Country.mmdb", "/var/local/lib/GeoIP/GeoLite2-Country.mmdb", + "%SystemDrive%\\ProgramData\\MaxMind\\GeoIPUpdate\\GeoIP\\GeoLite2-Country.mmdb" "C:\\GeoIP\\GeoLite2-Country.mmdb" ] @@ -325,22 +294,16 @@ def get_ip_address_country(ip_address, parallel=False, offline=False): if db_path is None: db_path = os.path.join(tempdir, "GeoLite2-Country.mmdb") if not os.path.exists(db_path): - try: - download_country_database() - except Exception as e: - logger.error(e.__str__()) - return None - if not os.path.exists(db_path): - return None + logging.warning("GeoLite2-Country.mmdb is missing. " + "Please follow the instructions at " + "https://dev.maxmind.com/geoip/geoipupdate/ " + "to get the latest version.") + return None else: db_age = datetime.now() - datetime.fromtimestamp( os.stat(db_path).st_mtime) if db_age > timedelta(days=7): - try: - download_country_database() - except Exception as e: - logger.error(e.__str__()) - return None + logger.warning("GeoLite2-Country.mmdb is more than a week old") db_path = db_path db_reader = geoip2.database.Reader(db_path) @@ -386,7 +349,7 @@ def get_ip_address_info(ip_address, cache=None, offline=False, reverse_dns = get_reverse_dns(ip_address, nameservers=nameservers, timeout=timeout) - country = get_ip_address_country(ip_address, parallel=parallel) + country = get_ip_address_country(ip_address) info["country"] = country info["reverse_dns"] = reverse_dns info["base_domain"] = None diff --git a/setup.py b/setup.py index 80cc6c7..0202a1f 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ from setuptools import setup from codecs import open from os import path -__version__ = "6.7.4" +__version__ = "6.8.0" description = "A Python package and CLI for parsing aggregate and " \ "forensic DMARC reports"