[PATCH nft v1]files: add script to generate geoip.nft file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds a python script to download MaxMind's GeoLite2
database and generate a file named geoip.nft, which users can 'include'.

The nft_geoip.py file has three options:
 --download            : to download and unzip the database folder from MaxMind.
 --file-location       : to specify the .csv file containing the country names and geoname ids.
 --file-ipv4           : to specify the .csv file containing information about IPv4 blocks.

Signed-off-by: Shekhar Sharma <shekhar250198@xxxxxxxxx>
---
The version history of the patch is:
v1: add the script nft_geoip.py 
---
 files/nft_geoip.py | 181 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 181 insertions(+)
 create mode 100644 files/nft_geoip.py

diff --git a/files/nft_geoip.py b/files/nft_geoip.py
new file mode 100644
index 00000000..52b65ff9
--- /dev/null
+++ b/files/nft_geoip.py
@@ -0,0 +1,181 @@
+#!/usr/bin/env python3
+#
+# (C) 2019 by Shekhar Sharma <shekhar250198@xxxxxxxxx>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+"""Download and unzip GeoLite2 database from MaxMind database and Generate geoip.nft file by parsing CSVs."""
+import argparse
+from collections import namedtuple
+import csv
+import unicodedata
+from zipfile import ZipFile
+import urllib.request
+import os
+import sys
+
+
+GeoEntry = namedtuple('GeoEntry', 'geoname_id, '
+                      'continent_code, '
+                      'locale_code, '
+                      'continent_name, '
+                      'country_iso_code, '
+                      'country_name, '
+                      'is_in_european_union')
+
+# then mapping for network address to geoname_id
+NetworkEntry = namedtuple('NetworkEntry',
+                          'network, '
+                          'geoname_id, '
+                          'registered_country_geoname_id,'
+                          'represented_country_geoname_id,'
+                          'is_anonymous_proxy,'
+                          'is_satellite_provider')
+
+
+def strip_accent(text):
+    """Remove accented characters. Convert to ASCII."""
+    return ''.join(char for char in unicodedata.normalize('NFKD', text) \
+                   if unicodedata.category(char) != 'Mn')
+
+
+def make_country_and_continent_dict():
+    """Read the locations file and make dicts."""
+    country_dict = {}
+    continent_dict = {}
+    flag = 0
+    for geo_entry in map(GeoEntry._make, csv.reader(ARGS.LOCATIONS)):
+        if flag == 0:
+            flag = 1
+        else:
+            country_dict[geo_entry.geoname_id] = geo_entry.country_name
+            continent_dict[geo_entry.country_name] = geo_entry.continent_name
+    return correct_dictionary(country_dict), correct_dictionary(continent_dict)
+
+
+def correct_dictionary(dictionary):
+    """Given a dict, strip accents from it, and replace special characters."""
+    new_dict = {}
+    for key, value in dictionary.items():
+        if key != '' and value != '':
+            new_key = strip_accent(key).lower()
+            new_key = new_key.replace(" ", "_").replace("[", "").replace("]", "").replace(",","")
+            new_value = strip_accent(value).lower()
+            new_value = new_value.replace(" ", "_").replace("[", "").replace("]", "").replace(",","")
+            new_dict[new_key] = new_value
+    return new_dict
+
+
+def write_geoids(country_dict):
+    """Write geoids to output file."""
+    with open('geoip.nft', 'w') as output_file:
+        for row, country in country_dict.items():
+            output_file.write('define {} = {}\n'.format(country,row))
+        output_file.write('\n' * 3)
+
+
+def make_geoip_dict(country_dict):
+    """Use country_dict to make geoip_dict."""
+    geoip_dict = {}
+    for net_entry in map(NetworkEntry._make, csv.reader(ARGS.BLOCKS)):
+        try:
+            geoip_dict[net_entry.network] = country_dict[net_entry.geoname_id]
+        except KeyError:
+            pass
+    return correct_dictionary(geoip_dict)
+
+
+def make_lines1(dictionary):
+    """Given dict, make lines to write into output file."""
+    return ['{} : ${}'.format(row,value) for row, value in dictionary.items()]
+
+
+def make_lines2(dictionary):
+    """Given dict, make lines to write into output file."""
+    return ['${} : ${}'.format(row,value) for row, value in dictionary.items()]
+
+
+def write_continent_info(geoip_dict, continent_dict):
+    """Write to output file."""
+    with open("geoip.nft", "a+") as output_file:
+        output_file.write('map geoname_id {\n'
+                          '\ttype ipv4_addr : mark\n'
+                          '\tflags interval\n'
+                          '\telements = {\n\t\t')
+
+        output_file.write(',\n\t\t'.join(make_lines1(geoip_dict)))
+        output_file.write('\n')
+        output_file.write('\t}\n')
+        output_file.write('\t}')
+        output_file.write('\n'*3)
+        output_file.write('define africa = 1\n'
+                          'define asia = 2\n'
+                          'define europe = 3\n'
+                          'define north_america = 4\n'
+                          'define south_america = 5\n'
+                          'define oceania = 6\n'
+                          'define antarctic = 7\n')
+        output_file.write('\n' * 3)
+
+        output_file.write('map continent_code {\n'
+                          '\ttype mark : mark\n'
+                          '\tflags interval\n'
+                          '\telements = {\n\t\t')
+
+        output_file.write(',\n\t\t'.join(make_lines2(continent_dict)))
+        output_file.write('\n')
+        output_file.write('\t}\n')
+        output_file.write('\t}')
+        output_file.write('\n' * 3)
+
+if __name__ == '__main__':
+    # Parse input file names
+    PARSER = argparse.ArgumentParser(description='Create geoip.nft file by parsing CSVs.')
+    PARSER.add_argument('--file-location',
+                        type=argparse.FileType('r'),
+                        help='a csv file containing the locations of countries with geoname ids.',
+                        required=False,
+                        dest='LOCATIONS')
+    PARSER.add_argument('--file-ipv4',
+                        type=argparse.FileType('r'),
+                        help='a csv file containing the ipv4 blocks for countries.',
+                        required=False,
+                        dest='BLOCKS')
+
+    PARSER.add_argument('--download',action='store_true',
+                        help='download the folder containing data in CSV format.',
+                        dest='DOWNLOAD')
+
+
+    ARGS = PARSER.parse_args()
+
+    if ARGS.DOWNLOAD:
+        print('Downloading GeoIP CSV files,\nPlease wait, this may take a moment.\n')
+        url ='http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip'
+        urllib.request.urlretrieve(url,'csvdata.zip')
+        file='csvdata.zip'
+        with ZipFile(file,'r') as zip:
+            zip.extractall()
+        os.remove(file)
+        sys.exit("Done")
+
+    if not ARGS.DOWNLOAD:
+        if not (ARGS.BLOCKS or ARGS.LOCATIONS):
+            PARSER.print_help()
+            sys.exit("You must specify the files where data is located or download the data folder using --download option")
+        if not ARGS.BLOCKS:
+            PARSER.print_help()
+            sys.exit("You must specify the file where IPv4 data is located")
+        if not ARGS.LOCATIONS:
+            PARSER.print_help()
+            sys.exit("You must specify the file where country location data is located")		
+
+    print('Creating geoip.nft\n')
+    COUNTRY_DICT, CONTINENT_DICT = make_country_and_continent_dict()
+    write_geoids(COUNTRY_DICT)
+    GEOIP_DICT = make_geoip_dict(COUNTRY_DICT)
+    write_continent_info(GEOIP_DICT, CONTINENT_DICT)
+    print('Done')
-- 
2.17.1




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux