diff -urN xtables-addons-2.14.old/extensions/xt_geoip.h xtables-addons-2.14/extensions/xt_geoip.h --- xtables-addons-2.14.old/extensions/xt_geoip.h 2017-11-22 21:29:25.000000000 +0400 +++ xtables-addons-2.14/extensions/xt_geoip.h 2020-06-07 22:15:24.187564284 +0400 @@ -18,7 +18,7 @@ XT_GEOIP_DST = 1 << 1, /* Perform check on Destination IP */ XT_GEOIP_INV = 1 << 2, /* Negate the condition */ - XT_GEOIP_MAX = 15, /* Maximum of countries */ + XT_GEOIP_MAX = 50, /* Maximum of countries */ }; /* Yup, an address range will be passed in with host-order */ diff -urN xtables-addons-2.14.old/geoip/xt_geoip_build xtables-addons-2.14/geoip/xt_geoip_build --- xtables-addons-2.14.old/geoip/xt_geoip_build 2017-11-22 21:29:25.000000000 +0400 +++ xtables-addons-2.14/geoip/xt_geoip_build 2020-06-07 22:21:36.000000000 +0400 @@ -1,10 +1,14 @@ #!/usr/bin/perl # # Converter for MaxMind CSV database to binary, for xt_geoip -# Copyright © Jan Engelhardt, 2008-2011 +# Copyright Jan Engelhardt, 2008-2011 +# Copyright Philip Prindeville, 2018 +# Added Twice output (BE, LE) for v1.x for SME9 - Mab974, 2018 # use Getopt::Long; -use IO::Handle; +use Net::CIDR::Lite; +use Socket qw(AF_INET AF_INET6 inet_pton); +use warnings; use Text::CSV_XS; # or trade for Text::CSV use strict; @@ -32,33 +36,208 @@ } } +my %countryId; +my %countryName; + +my $dir = findVersion(); + +&loadCountries(); + &dump(&collect()); -sub collect +sub findVersion { - my %country; - - while (my $row = $csv->getline(*ARGV)) { - if (!defined($country{$row->[4]})) { - $country{$row->[4]} = { - name => $row->[5], - pool_v4 => [], - pool_v6 => [], - }; + my @dirs = (); + my $filename; + + opendir(my $dh, '.') || die "Can't open .: $!\n"; + + while (($filename = readdir($dh))) { + if ($filename =~ m/^GeoLite2-Country-CSV_\d{8}$/) { + push(@dirs, $filename); } - my $c = $country{$row->[4]}; - if ($row->[0] =~ /:/) { - push(@{$c->{pool_v6}}, - [&ip6_pack($row->[0]), &ip6_pack($row->[1])]); + } + closedir $dh; + + @dirs = sort @dirs; + return pop(@dirs); +} + +sub loadCountries +{ + my $file = "$dir/GeoLite2-Country-Locations-en.csv"; + + sub id; sub cc; sub long; sub ct; sub cn; + + %countryId = (); + %countryName = (); + + open(my $fh, '<', $file) || die "Couldn't open list country names\n"; + + # first line is headers + my $row = $csv->getline($fh); + + my %header = map { ($row->[$_], $_); } (0..$#{$row}); + + my %pairs = ( + country_iso_code => 'ISO Country Code', + geoname_id => 'ID', + country_name => 'Country Name', + continent_code => 'Continent Code', + continent_name => 'Continent Name', + ); + + # verify that the columns we need are present + map { die "Table has no $pairs{$_} column\n" unless (exists $header{$_}); } keys %pairs; + + my %remapping = ( + id => 'geoname_id', + cc => 'country_iso_code', + long => 'country_name', + ct => 'continent_code', + cn => 'continent_name', + ); + + # now create a function which returns the value of that column # + map { eval "sub $_ () { \$header{\$remapping{$_}}; }" ; } keys %remapping; + + while (my $row = $csv->getline($fh)) { + if ($row->[cc] eq '' && $row->[long] eq '') { + $countryId{$row->[id]} = $row->[ct]; + $countryName{$row->[ct]} = $row->[cn]; } else { - push(@{$c->{pool_v4}}, [$row->[2], $row->[3]]); - } - if ($. % 4096 == 0) { - print STDERR "\r\e[2K$. entries"; + $countryId{$row->[id]} = $row->[cc]; + $countryName{$row->[cc]} = $row->[long]; } } - print STDERR "\r\e[2K$. entries total\n"; + $countryName{A1} = 'Anonymous Proxy'; + $countryName{A2} = 'Satellite Provider'; + $countryName{O1} = 'Other Country'; + + close($fh); + + # clean up the namespace + undef &id; undef &cc; undef &long; undef &ct; undef &cn; +} + +sub lookupCountry +{ + my ($id, $rid, $proxy, $sat) = @_; + + if ($proxy) { + return 'A1'; + } elsif ($sat) { + return 'A2'; + } + $id ||= $rid; + if ($id eq '') { + return 'O1'; + } + die "Unknown id: $id line $.\n" unless (exists $countryId{$id}); + return $countryId{$id}; +} + +sub collect +{ + my ($file, $fh, $row); + my (%country, %header); + + sub net; sub id; sub rid; sub proxy; sub sat; + + my %pairs = ( + network => 'Network', + registered_country_geoname_id => 'Registered Country ID', + geoname_id => 'Country ID', + is_anonymous_proxy => 'Anonymous Proxy', + is_satellite_provider => 'Satellite', + ); + + foreach (sort keys %countryName) { + $country{$_} = { + name => $countryName{$_}, + pool_v4 => Net::CIDR::Lite->new(), + pool_v6 => Net::CIDR::Lite->new(), + }; + } + + $file = "$dir/GeoLite2-Country-Blocks-IPv4.csv"; + + open($fh, '<', $file) || die "Can't open IPv4 database\n"; + + # first line is headers + $row = $csv->getline($fh); + + %header = map { ($row->[$_], $_); } (0..$#{$row}); + + # verify that the columns we need are present + map { die "Table has no %pairs{$_} column\n" unless (exists $header{$_}); } keys %pairs; + + my %remapping = ( + net => 'network', + id => 'geoname_id', + rid => 'registered_country_geoname_id', + proxy => 'is_anonymous_proxy', + sat => 'is_satellite_provider', + ); + + # now create a function which returns the value of that column # + map { eval "sub $_ () { \$header{\$remapping{$_}}; }" ; } keys %remapping; + + while ($row = $csv->getline($fh)) { + my ($cc, $cidr); + + $cc = lookupCountry($row->[id], $row->[rid], $row->[proxy], $row->[sat]); + $cidr = $row->[net]; + $country{$cc}->{pool_v4}->add($cidr); + + #if ($. % 4096 == 0) { + # print STDERR "\r\e[2K$. entries"; + #} + } + + #print STDERR "\r\e[2K$. entries total\n"; + + close($fh); + + # clean up the namespace + undef &net; undef &id; undef &rid; undef &proxy; undef &sat; + + $file = "$dir/GeoLite2-Country-Blocks-IPv6.csv"; + + open($fh, '<', $file) || die "Can't open IPv6 database\n"; + + # first line is headers + $row = $csv->getline($fh); + + %header = map { ($row->[$_], $_); } (0..$#{$row}); + + # verify that the columns we need are present + map { die "Table has no %pairs{$_} column\n" unless (exists $header{$_}); } keys %pairs; + + # unlikely the IPv6 table has different columns, but just to be sure + # create a function which returns the value of that column # + map { eval "sub $_ () { \$header{\$remapping{$_}}; }" ; } keys %remapping; + + while ($row = $csv->getline($fh)) { + my ($cc, $cidr); + + $cc = lookupCountry($row->[id], $row->[rid], $row->[proxy], $row->[sat]); + $cidr = $row->[net]; + $country{$cc}->{pool_v6}->add($cidr); + + #if ($. % 4096 == 0) { + # print STDERR "\r\e[2K$. entries"; + #} + } + + #print STDERR "\r\e[2K$. entries total\n"; + + close($fh); + + # clean up the namespace + undef &net; undef &id; undef &rid; undef &proxy; undef &sat; + return \%country; } @@ -66,18 +245,23 @@ { my $country = shift @_; - foreach my $iso_code (sort keys %$country) { + foreach my $iso_code (sort keys %{$country}) { &dump_one($iso_code, $country->{$iso_code}); } } sub dump_one { +# 2 sub-directories added pour big-endian and little-endian + my($iso_code, $country) = @_; my($file, $fh_le, $fh_be); - + my ($start, $end); + my @ranges; + + @ranges = $country->{pool_v6}->list_range(); printf "%5u IPv6 ranges for %s %s\n", - scalar(@{$country->{pool_v6}}), + scalar(@ranges), $iso_code, $country->{name}; $file = "$target_dir/LE/".uc($iso_code).".iv6"; @@ -90,15 +274,23 @@ print STDERR "Error opening $file: $!\n"; exit 1; } - foreach my $range (@{$country->{pool_v6}}) { - print $fh_be $range->[0], $range->[1]; - print $fh_le &ip6_swap($range->[0]), &ip6_swap($range->[1]); + binmode($fh_be); + binmode($fh_le); + + foreach my $range (@ranges) { + ($start, $end) = split('-', $range); + $start = inet_pton(AF_INET6, $start); + $end = inet_pton(AF_INET6, $end); + print $fh_be $start, $end; + + print $fh_le &ip6_swap($start), &ip6_swap($end); } close $fh_le; close $fh_be; + @ranges = $country->{pool_v4}->list_range(); printf "%5u IPv4 ranges for %s %s\n", - scalar(@{$country->{pool_v4}}), + scalar(@ranges), $iso_code, $country->{name}; $file = "$target_dir/LE/".uc($iso_code).".iv4"; @@ -111,31 +303,29 @@ print STDERR "Error opening $file: $!\n"; exit 1; } - foreach my $range (@{$country->{pool_v4}}) { - print $fh_le pack("VV", $range->[0], $range->[1]); - print $fh_be pack("NN", $range->[0], $range->[1]); + binmode($fh_be); + binmode($fh_le); + + foreach my $range (@ranges) { + ($start, $end) = split('-', $range); + my $start = inet_pton(AF_INET, $start); + my $end = inet_pton(AF_INET, $end); + print $fh_be $start, $end; + print $fh_le ip4_swap($start), ip4_swap($end); } close $fh_le; close $fh_be; } -sub ip6_pack +sub ip6_swap { - my $addr = shift @_; - $addr =~ s{::}{:!:}; - my @addr = split(/:/, $addr); - my @e = (0) x 8; - foreach (@addr) { - if ($_ eq "!") { - $_ = join(':', @e[0..(8-scalar(@addr))]); - } - } - @addr = split(/:/, join(':', @addr)); - $_ = hex($_) foreach @addr; - return pack("n*", @addr); + my ($p1, $p2, $p3, $p4) = unpack 'a4 a4 a4 a4', shift @_; + return pack "a4 a4 a4 a4", ip4_swap($p1), ip4_swap($p2), + ip4_swap($p3), ip4_swap($p4); } -sub ip6_swap +sub ip4_swap { - return pack("V*", unpack("N*", shift @_)); + my ($b1, $b2, $b3, $b4) = unpack 'a a a a', shift @_; + return pack "a a a a", $b4, $b3, $b2, $b1; } diff -urN xtables-addons-2.14.old/geoip/xt_geoip_build.1 xtables-addons-2.14/geoip/xt_geoip_build.1 --- xtables-addons-2.14.old/geoip/xt_geoip_build.1 2017-11-22 21:29:25.000000000 +0400 +++ xtables-addons-2.14/geoip/xt_geoip_build.1 2020-06-07 22:21:36.000000000 +0400 @@ -5,7 +5,7 @@ .SH Syntax .PP \fI/usr/libexec/xt_geoip/\fP\fBxt_geoip_build\fP [\fB\-D\fP -\fItarget_dir\fP] [\fIfile\fP...] +\fItarget_dir\fP] .SH Description .PP xt_geoip_build is used to build packed raw representations of the range @@ -16,7 +16,12 @@ also ordered, as xt_geoip relies on this property for its bisection approach to work. .PP -Input is processed from the listed files, or if none is given, from stdin. +It expects to find a directory named +.IR GeoLite2-Country-CSV_YYYYMMDD +in the current directory, and will select the most recent if multiple +instances are found. The +.IR xt_geoip_dl +script can be used to populate this directory. .PP Since the script is usually installed to the libexec directory of the xtables-addons package and this is outside $PATH (on purpose), invoking the diff -urN xtables-addons-2.14.old/geoip/xt_geoip_dl xtables-addons-2.14/geoip/xt_geoip_dl --- xtables-addons-2.14.old/geoip/xt_geoip_dl 2017-11-22 21:29:25.000000000 +0400 +++ xtables-addons-2.14/geoip/xt_geoip_dl 2020-06-07 22:25:47.711229516 +0400 @@ -1,8 +1,26 @@ #!/bin/sh -rm -f GeoIPv6.csv GeoIPv6.csv.gz GeoIPCountryCSV.zip GeoIPCountryWhois.csv; -wget \ - http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz \ - http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip; -gzip -d GeoIPv6.csv.gz; -unzip GeoIPCountryCSV.zip; +status=$(/sbin/e-smith/config getprop geoip status) +if [[ "$status" != "enabled" ]] +then + echo "Geoip is not enabled. No download." + exit 1 +fi + +LicenseKey=$(/sbin/e-smith/config getprop geoip LicenseKey) +if [ -z $LicenseKey ] +then + echo "No License Key available. Downloading cannot be performed" + exit 1 +fi + +rm -rf GeoLite2-Country-CSV_* + +if ( ! wget -O GeoLite2-Country-CSV.zip -q "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country-CSV&license_key=${LicenseKey}&suffix=zip" ) +then + echo "Error while downloading" + exit 2 +fi + +unzip -q GeoLite2-Country-CSV.zip +rm -f GeoLite2-Country-CSV.zip diff -urN xtables-addons-2.14.old/mconfig xtables-addons-2.14/mconfig --- xtables-addons-2.14.old/mconfig 2017-11-22 21:29:25.000000000 +0400 +++ xtables-addons-2.14/mconfig 2020-06-18 11:15:58.417767490 +0400 @@ -9,7 +9,7 @@ build_IPMARK=m build_LOGMARK=m build_SYSRQ=m -build_TARPIT=m +##build_TARPIT=m centos 7 compatibility build_condition=m build_fuzzy=m build_geoip=m