From ce0d66d37fb5f5676168be4f30ade6a68777d5fd Mon Sep 17 00:00:00 2001 From: Rick Elrod Date: Fri, 11 Jan 2019 21:22:19 +0000 Subject: [PATCH] Try adding a script for generating the GeoIP ACLs Signed-off-by: Rick Elrod --- roles/dns/files/GeoIP.sh | 39 ++++++-------------- roles/dns/files/geoip.py | 80 ++++++++++++++++++++++++++++++++++++++++ roles/dns/tasks/main.yml | 8 ++++ 3 files changed, 99 insertions(+), 28 deletions(-) mode change 100755 => 100644 roles/dns/files/GeoIP.sh create mode 100644 roles/dns/files/geoip.py diff --git a/roles/dns/files/GeoIP.sh b/roles/dns/files/GeoIP.sh old mode 100755 new mode 100644 index fb2780e5b5..3fd137cc05 --- a/roles/dns/files/GeoIP.sh +++ b/roles/dns/files/GeoIP.sh @@ -1,31 +1,14 @@ -#!/bin/bash +#!/usr/bin/env bash +# Rick Elrod +# (c) 2019 Red Hat, Inc. +# etc. -# This copyrighted material is made available to anyone wishing to use, modify, -# copy, or redistribute it subject to the terms and conditions of the GNU -# General Public License v.2. This program is distributed in the hope that it -# will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the -# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the GNU General Public License for more details. You should have -# received a copy of the GNU General Public License along with this program; -# if not, write to the Free Software Foundation, Inc., 51 Franklin Street, -# Fifth Floor, Boston, MA 02110-1301, USA. +# Fail early +set -e -rm -f /root/GeoIPCountryCSV.zip - -wget -q -T 5 -t 1 http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip -unzip -q GeoIPCountryCSV.zip || exit 1 - -awk -F \" '{print $10","$6","$8}' GeoIPCountryWhois.csv > cbe.csv -rm -f GeoIPCountryWhois.csv - -(for c in $(awk -F , '{print $1}' cbe.csv | sort -u) -do - echo "acl \"$c\" {" - grep "^$c," cbe.csv | awk -F , 'function s(b,e,l,m,n) {l = int(log(e-b+1)/log(2)); m = 2^32-2^l; n = and(m,e); if (n == and(m,b)) printf "\t%u.%u.%u.%u/%u;\n",b/2^24%256,b/2^16%256,b/2^8%256,b%256,32-l; else {s(b,n-1); s(n,e)}} s($2,$3)' - echo -e "};\n" -done) > /var/named/GeoIP.acl - -rm -f cbe.csv - -exit 0 +rm -f GeoLite2-Country-CSV.zip csvs/* +rmdir csvs +wget -q -T 5 -t 1 https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country-CSV.zip +unzip -j GeoLite2-Country-CSV.zip -d csvs/ +python geoip.py csvs/GeoLite2-Country-Blocks-IPv4.csv csvs/GeoLite2-Country-Blocks-IPv6.csv csvs/GeoLite2-Country-Locations-en.csv > /var/named/GeoIP.acl diff --git a/roles/dns/files/geoip.py b/roles/dns/files/geoip.py new file mode 100644 index 0000000000..8bc135c582 --- /dev/null +++ b/roles/dns/files/geoip.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# (c) 2019 Red Hat, Inc. +# Rick Elrod +# etc. + +import csv +import sys + +if len(sys.argv) != 4: + print "Usage: geoip-to-acl.py "\ + " "\ + "" + sys.exit(1) + +v4blocks = sys.argv[1] +v6blocks = sys.argv[2] +locations = sys.argv[3] + +location_map = {} +subnet_map = {} + +with open(locations) as loc_in: + reader = csv.reader(loc_in) + # Skip the header line + reader.next() + for row in reader: + # If we have a narrowed down country, use it. + # Otherwise, use the continent. + if row[4] == '': + location_map[int(row[0])] = row[2] + else: + location_map[int(row[0])] = row[4] + +# Handle v4 +with open(v4blocks) as v4_in: + reader = csv.reader(v4_in) + # Skip the header line + reader.next() + for row in reader: + # Figure out if we need to use row[1] or row[2] + if row[1] == '' and row[2] == '': + # If the subnet has no country attached to it at all (??), skip it. + continue + elif row[2] == '': + geo_code = location_map[int(row[1])] + else: + geo_code = location_map[int(row[2])] + + if subnet_map.get(geo_code): + subnet_map[geo_code].append(row[0]) + else: + subnet_map[geo_code] = [row[0]] + +# Handle v6 +with open(v6blocks) as v6_in: + reader = csv.reader(v6_in) + # Skip the header line + reader.next() + for row in reader: + # Figure out if we need to use row[1] or row[2] + if row[1] == '' and row[2] == '': + # If the subnet has no country attached to it at all (??), skip it. + continue + elif row[2] == '': + geo_code = location_map[int(row[1])] + else: + geo_code = location_map[int(row[2])] + + if subnet_map.get(geo_code): + subnet_map[geo_code].append(row[0]) + else: + subnet_map[geo_code] = [row[0]] + +# And generate the ACLs +for k,v in sorted(subnet_map.iteritems()): + print 'acl "%s" {' % k + for subnet in v: + print '\t%s;' % subnet + print '};' + print '' diff --git a/roles/dns/tasks/main.yml b/roles/dns/tasks/main.yml index 28e009ec25..ee526cb748 100644 --- a/roles/dns/tasks/main.yml +++ b/roles/dns/tasks/main.yml @@ -35,6 +35,14 @@ - config - dns +- name: copy geoip.py + copy: src=geoip.py dest=/var/named/geoip.py mode=0755 + notify: + - restart named + tags: + - config + - dns + - name: copy GeoIP.sh copy: src=GeoIP.sh dest=/var/named/GeoIP.sh mode=0755 notify: