From: Stefan Schantl Date: Sat, 14 Feb 2015 11:34:31 +0000 (+0100) Subject: Merge branch 'master' of ssh://git.ipfire.org/pub/git/ipfire-2.x into seventeen-geoip X-Git-Tag: v2.17-core91~128^2~6^2~12^2~3 X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=commitdiff_plain;h=bc9446c65ff048ebce8c0665cc0efe2231fb37de;hp=309b7de86ec42c1ed395125d7dc022acfd56e500 Merge branch 'master' of ssh://git.ipfire.org/pub/git/ipfire-2.x into seventeen-geoip Conflicts: make.sh --- diff --git a/config/cfgroot/general-functions.pl b/config/cfgroot/general-functions.pl index 35ae7c0930..29f7e8c6b8 100644 --- a/config/cfgroot/general-functions.pl +++ b/config/cfgroot/general-functions.pl @@ -17,6 +17,7 @@ package General; use strict; use Socket; use IO::Socket; +use Locale::Country; use Net::SSLeay; use Net::IPv4Addr qw(:all); $|=1; # line buffering diff --git a/config/cfgroot/geoip-functions.pl b/config/cfgroot/geoip-functions.pl new file mode 100644 index 0000000000..68b6f503d7 --- /dev/null +++ b/config/cfgroot/geoip-functions.pl @@ -0,0 +1,90 @@ +#!/usr/bin/perl -w +############################################################################ +# # +# This file is part of the IPFire Firewall. # +# # +# IPFire 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. # +# # +# IPFire is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty 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 IPFire; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +# Copyright (C) 2015 IPFire Team . # +# # +############################################################################ + +package GeoIP; + +use Locale::Country; + +# Function to get the flag icon for a specified country code. +sub get_flag_icon($) { + my ($input) = @_; + + # Webserver's root dir. (Required for generating full path) + my $webroot = "/srv/web/ipfire/html"; + + # Directory which contains the flag icons. + my $flagdir = "/images/flags"; + + # File extension of the country flags. + my $ext = "png"; + + # Remove whitespaces. + chomp($input); + + # Convert given country code to lower case. + my $ccode = lc($input); + + # Generate filename, based on the contry code in lower case + # and the defined file extension. + my $file = join('.', $ccode,$ext); + + # Generate path inside webroot to the previously generated file. + my $flag_icon = join('/', $flagdir,$file); + + # Generate absolute path to the icon file. + my $absolute_path = join('', $webroot,$flag_icon); + + # Check if the a icon file exists. + if (-e "$absolute_path") { + # Return content of flag_icon. + return $flag_icon; + } +} + +# Function to get the county name by a given country code. +sub get_full_country_name($) { + my ($input) = @_; + my $name; + + # Remove whitespaces. + chomp($input); + + # Convert input into lower case format. + my $code = lc($input); + + # Handle country codes which are not in the list. + if ($code eq "a1") { $name = "Anonymous Proxy" } + elsif ($code eq "a2") { $name = "Satellite Provider" } + elsif ($code eq "o1") { $name = "Other Country" } + elsif ($code eq "ap") { $name = "Asia/Pacific Region" } + elsif ($code eq "eu") { $name = "Europe" } + elsif ($code eq "yu") { $name = "Yugoslavia" } + else { + # Use perl built-in module to get the country code. + $name = &Locale::Country::code2country($code); + } + + return $name; +} + +1; diff --git a/config/cfgroot/header.pl b/config/cfgroot/header.pl index cf895bf246..974c4d8b22 100644 --- a/config/cfgroot/header.pl +++ b/config/cfgroot/header.pl @@ -263,7 +263,7 @@ sub getcgihash { return if ($ENV{'REQUEST_METHOD'} ne 'POST'); if (!$params->{'wantfile'}) { $CGI::DISABLE_UPLOADS = 1; - $CGI::POST_MAX = 512 * 1024; + $CGI::POST_MAX = 1024 * 1024; } else { $CGI::POST_MAX = 10 * 1024 * 1024; } diff --git a/config/cron/crontab b/config/cron/crontab index d78d08f593..54e9b5fee2 100644 --- a/config/cron/crontab +++ b/config/cron/crontab @@ -57,3 +57,6 @@ HOME=/ # Re-read firewall rules every Sunday in March, October and November to take care of daylight saving time 00 3 * 3 0 /usr/local/bin/timezone-transition /usr/local/bin/firewallctrl 00 2 * 10-11 0 /usr/local/bin/timezone-transition /usr/local/bin/firewallctrl + +# Update GeoIP database once a month. +3 2 1 * * * [ -f "/var/ipfire/red/active" ] && /usr/local/bin/xt_geoip_update >/dev/null 2>&1 diff --git a/config/firewall/firewall-lib.pl b/config/firewall/firewall-lib.pl index f3cd67fb09..f73d84f296 100755 --- a/config/firewall/firewall-lib.pl +++ b/config/firewall/firewall-lib.pl @@ -552,4 +552,37 @@ sub get_internal_firewall_ip_address return 0; } +sub get_geoip_locations() { + # Path to the directory which contains the binary geoip + # databases. + my $directory="/usr/share/xt_geoip/LE"; + + # Array to store the final country list. + my @country_codes = (); + + # Open location and do a directory listing. + opendir(DIR, "$directory"); + my @locations = readdir(DIR); + closedir(DIR); + + # Loop through the directory listing, and cut of the file extensions. + foreach my $location (sort @locations) { + # skip . and .. + next if($location =~ /^\.$/); + next if($location =~ /^\.\.$/); + + # Remove whitespaces. + chomp($location); + + # Cut-off file extension. + my ($country_code, $extension) = split(/\./, $location); + + # Add country code to array. + push(@country_codes, $country_code); + } + + # Return final array. + return @country_codes; +} + return 1; diff --git a/config/firewall/geoipblock b/config/firewall/geoipblock new file mode 100644 index 0000000000..4d483d3b89 --- /dev/null +++ b/config/firewall/geoipblock @@ -0,0 +1 @@ +GEOIPBLOCK_ENABLED=off diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl old mode 100755 new mode 100644 index 97b8897af8..cd2f3a6359 --- a/config/firewall/rules.pl +++ b/config/firewall/rules.pl @@ -60,6 +60,7 @@ my $configfwdfw = "${General::swroot}/firewall/config"; my $configinput = "${General::swroot}/firewall/input"; my $configoutgoing = "${General::swroot}/firewall/outgoing"; my $p2pfile = "${General::swroot}/firewall/p2protocols"; +my $geoipfile = "${General::swroot}/firewall/geoipblock"; my $configgrp = "${General::swroot}/fwhosts/customgroups"; my $netsettings = "${General::swroot}/ethernet/settings"; @@ -94,6 +95,9 @@ sub main { # Load P2P block rules. &p2pblock(); + # Load GeoIP block rules. + &geoipblock(); + # Reload firewall policy. run("/usr/sbin/firewall-policy"); } @@ -573,6 +577,40 @@ sub p2pblock { } } +sub geoipblock { + my %geoipsettings = (); + + # Check if the geoip settings file exists + if (-e "$geoipfile") { + # Read settings file + &General::readhash("$geoipfile", \%geoipsettings); + } else { + # Exit submodule, go on processing the remaining script + return; + } + + # If geoip blocking is not enabled, we are finished here. + if ($geoipsettings{'GEOIPBLOCK_ENABLED'} ne "on") { + # Exit submodule. Process remaining script. + return; + } + + # Get supported locations. + my @locations = &fwlib::get_geoip_locations(); + + # Create iptables chain. + run("$IPTABLES -F GEOIPBLOCK"); + + # Loop through all supported geoip locations and + # create iptables rules, if blocking this country + # is enabled. + foreach my $location (@locations) { + if($geoipsettings{$location} eq "on") { + run("$IPTABLES -A GEOIPBLOCK -m geoip --src-cc $location -j DROP"); + } + } +} + sub get_protocols { my $hash = shift; my $key = shift; diff --git a/config/menu/50-firewall.menu b/config/menu/50-firewall.menu index e872e6428c..7271b32121 100644 --- a/config/menu/50-firewall.menu +++ b/config/menu/50-firewall.menu @@ -22,6 +22,12 @@ 'title' => "P2P-Block", 'enabled' => 1, }; + $subfirewall->{'50.geoipblock'} = { + 'caption' => $Lang::tr{'geoipblock'}, + 'uri' => '/cgi-bin/geoip-block.cgi', + 'title' => $Lang::tr{'geoipblock'}, + 'enabled' => 1, + }; $subfirewall->{'60.wireless'} = { 'caption' => $Lang::tr{'blue access'}, 'uri' => '/cgi-bin/wireless.cgi', diff --git a/config/rootfiles/common/Locale-Country b/config/rootfiles/common/Locale-Country index bbe51eee77..0ed312f434 100644 --- a/config/rootfiles/common/Locale-Country +++ b/config/rootfiles/common/Locale-Country @@ -1,13 +1,50 @@ -#usr/lib/perl5/site_perl/5.12.3/Locale -usr/lib/perl5/site_perl/5.12.3/Locale/Constants.pm -usr/lib/perl5/site_perl/5.12.3/Locale/Constants.pod -usr/lib/perl5/site_perl/5.12.3/Locale/Country.pm -usr/lib/perl5/site_perl/5.12.3/Locale/Country.pod -usr/lib/perl5/site_perl/5.12.3/Locale/Currency.pm -usr/lib/perl5/site_perl/5.12.3/Locale/Currency.pod -usr/lib/perl5/site_perl/5.12.3/Locale/Language.pm -usr/lib/perl5/site_perl/5.12.3/Locale/Language.pod -usr/lib/perl5/site_perl/5.12.3/Locale/Script.pm -usr/lib/perl5/site_perl/5.12.3/Locale/Script.pod -#usr/lib/perl5/site_perl/5.12.3/MACHINE-linux-thread-multi/auto/Locale-Codes -#usr/lib/perl5/site_perl/5.12.3/MACHINE-linux-thread-multi/auto/Locale-Codes/.packlist +#usr/lib/perl5/5.12.3/Locale/Codes +usr/lib/perl5/5.12.3/Locale/Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes.pod +usr/lib/perl5/5.12.3/Locale/Codes/API.pod +usr/lib/perl5/5.12.3/Locale/Codes/Changes.pod +usr/lib/perl5/5.12.3/Locale/Codes/Constants.pm +usr/lib/perl5/5.12.3/Locale/Codes/Constants.pod +usr/lib/perl5/5.12.3/Locale/Codes/Country.pm +usr/lib/perl5/5.12.3/Locale/Codes/Country.pod +usr/lib/perl5/5.12.3/Locale/Codes/Country_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/Country_Retired.pm +usr/lib/perl5/5.12.3/Locale/Codes/Currency.pm +usr/lib/perl5/5.12.3/Locale/Codes/Currency.pod +usr/lib/perl5/5.12.3/Locale/Codes/Currency_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/Currency_Retired.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangExt.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangExt.pod +usr/lib/perl5/5.12.3/Locale/Codes/LangExt_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangExt_Retired.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangFam.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangFam.pod +usr/lib/perl5/5.12.3/Locale/Codes/LangFam_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangFam_Retired.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangVar.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangVar.pod +usr/lib/perl5/5.12.3/Locale/Codes/LangVar_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/LangVar_Retired.pm +usr/lib/perl5/5.12.3/Locale/Codes/Language.pm +usr/lib/perl5/5.12.3/Locale/Codes/Language.pod +usr/lib/perl5/5.12.3/Locale/Codes/Language_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/Language_Retired.pm +usr/lib/perl5/5.12.3/Locale/Codes/Script.pm +usr/lib/perl5/5.12.3/Locale/Codes/Script.pod +usr/lib/perl5/5.12.3/Locale/Codes/Script_Codes.pm +usr/lib/perl5/5.12.3/Locale/Codes/Script_Retired.pm +#usr/lib/perl5/5.12.3/i586-linux-thread-multi/auto/Locale +#usr/lib/perl5/5.12.3/i586-linux-thread-multi/auto/Locale/Codes +#usr/lib/perl5/5.12.3/i586-linux-thread-multi/auto/Locale/Codes/.packlist +#usr/share/man/man3/Locale::Codes.3 +#usr/share/man/man3/Locale::Codes::API.3 +#usr/share/man/man3/Locale::Codes::Changes.3 +#usr/share/man/man3/Locale::Codes::Constants.3 +#usr/share/man/man3/Locale::Codes::Country.3 +#usr/share/man/man3/Locale::Codes::Currency.3 +#usr/share/man/man3/Locale::Codes::LangExt.3 +#usr/share/man/man3/Locale::Codes::LangFam.3 +#usr/share/man/man3/Locale::Codes::LangFam_Retired.3 +#usr/share/man/man3/Locale::Codes::LangVar.3 +#usr/share/man/man3/Locale::Codes::Language.3 +#usr/share/man/man3/Locale::Codes::Script.3 diff --git a/config/rootfiles/common/perl-Text-CSV_XS b/config/rootfiles/common/perl-Text-CSV_XS new file mode 100644 index 0000000000..ca2f642287 --- /dev/null +++ b/config/rootfiles/common/perl-Text-CSV_XS @@ -0,0 +1,8 @@ +#usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/Text +usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/Text/CSV_XS.pm +#usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/auto/Text +#usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/auto/Text/CSV_XS +#usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/auto/Text/CSV_XS/.packlist +#usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/auto/Text/CSV_XS/CSV_XS.bs +usr/lib/perl5/site_perl/5.12.3/i586-linux-thread-multi/auto/Text/CSV_XS/CSV_XS.so +#usr/share/man/man3/Text::CSV_XS.3 diff --git a/config/rootfiles/common/stage2 b/config/rootfiles/common/stage2 index 663aef57ae..4e8b750c8b 100644 --- a/config/rootfiles/common/stage2 +++ b/config/rootfiles/common/stage2 @@ -143,6 +143,7 @@ usr/share/doc/licenses/GPLv3 #usr/share/man/man8 #usr/share/misc #usr/share/terminfo +#usr/share/xt_geoip #usr/share/zoneinfo #var #var/cache diff --git a/config/rootfiles/common/xtables-addons b/config/rootfiles/common/xtables-addons new file mode 100644 index 0000000000..9053c280ca --- /dev/null +++ b/config/rootfiles/common/xtables-addons @@ -0,0 +1,7 @@ +lib/xtables/libxt_geoip.so +#usr/libexec/xtables-addons +usr/libexec/xtables-addons/xt_geoip_build +usr/libexec/xtables-addons/xt_geoip_dl +#usr/share/man/man1/xt_geoip_build.1 +#usr/share/man/man1/xt_geoip_dl.1 +#usr/share/man/man8/xtables-addons.8 diff --git a/config/xtables-addons/mconfig b/config/xtables-addons/mconfig new file mode 100644 index 0000000000..92e47f0ad9 --- /dev/null +++ b/config/xtables-addons/mconfig @@ -0,0 +1,24 @@ +# -*- Makefile -*- +# +build_ACCOUNT=n +build_CHAOS=n +build_DELUDE=n +build_DHCPMAC=n +build_DNETMAP=n +build_ECHO=n +build_IPMARK=n +build_LOGMARK=n +build_SYSRQ=n +build_TARPIT=n +build_condition=n +build_fuzzy=n +build_geoip=m +build_gradm=n +build_iface=n +build_ipp2p=n +build_ipv4options=n +build_length2=n +build_lscan=n +build_pknock=n +build_psd=n +build_quota2=n diff --git a/html/cgi-bin/firewall.cgi b/html/cgi-bin/firewall.cgi index badee6b3c0..12152700fb 100644 --- a/html/cgi-bin/firewall.cgi +++ b/html/cgi-bin/firewall.cgi @@ -33,6 +33,7 @@ no warnings 'uninitialized'; require '/var/ipfire/general-functions.pl'; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; +require "${General::swroot}/geoip-functions.pl"; require "/usr/lib/firewall/firewall-lib.pl"; unless (-d "${General::swroot}/firewall") { system("mkdir ${General::swroot}/firewall"); } @@ -47,6 +48,7 @@ my %defaultNetworks=(); my %netsettings=(); my %customhost=(); my %customgrp=(); +my %customgeoipgrp=(); my %customnetworks=(); my %customservice=(); my %customservicegrp=(); @@ -73,6 +75,7 @@ my $color; my $confignet = "${General::swroot}/fwhosts/customnetworks"; my $confighost = "${General::swroot}/fwhosts/customhosts"; my $configgrp = "${General::swroot}/fwhosts/customgroups"; +my $configgeoipgrp = "${General::swroot}/fwhosts/customgeoipgrp"; my $configsrv = "${General::swroot}/fwhosts/customservices"; my $configsrvgrp = "${General::swroot}/fwhosts/customservicegrp"; my $configccdnet = "${General::swroot}/ovpn/ccd.conf"; @@ -1135,6 +1138,54 @@ END } print""; } + # geoip locations / groups. + my @geoip_locations = &fwlib::get_geoip_locations(); + + print "\n"; + print "\n"; + print "$Lang::tr{'geoip'}\n"; + print "\n"; + #End left table. start right table (vpn) print""; # CCD networks @@ -1472,6 +1523,7 @@ sub newrule &General::readhasharray("$confighost", \%customhost); &General::readhasharray("$configccdhost", \%ccdhost); &General::readhasharray("$configgrp", \%customgrp); + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); &General::readhasharray("$configipsec", \%ipsecconf); &General::get_aliases(\%aliases); my %checked=(); @@ -2600,6 +2652,13 @@ END }else{ print $$hash{$key}[4]; } + }elsif ($$hash{$key}[3] eq 'cust_geoip_src') { + my ($split1,$split2) = split(":", $$hash{$key}[4]); + if ($split2) { + print "$split2\n"; + }else{ + print "$Lang::tr{'geoip'}: $$hash{$key}[4]\n"; + } }elsif ($$hash{$key}[4] eq 'RED1'){ print "$ipfireiface $Lang::tr{'fwdfw red'}"; }elsif ($$hash{$key}[4] eq 'ALL'){ @@ -2676,6 +2735,13 @@ END }else{ print $$hash{$key}[6]; } + }elsif ($$hash{$key}[5] eq 'cust_geoip_tgt') { + my ($split1,$split2) = split(":", $$hash{$key}[6]); + if ($split2) { + print "$split2\n"; + }else{ + print "$Lang::tr{'geoip'}: $$hash{$key}[6]\n"; + } }elsif ($$hash{$key}[5] eq 'tgt_addr'){ my ($split1,$split2) = split("/",$$hash{$key}[6]); if ($split2 eq '32'){ @@ -2693,7 +2759,6 @@ END #RULE ACTIVE if($$hash{$key}[2] eq 'ON'){ $gif="/images/on.gif" - }else{ $gif="/images/off.gif" } diff --git a/html/cgi-bin/fwhosts.cgi b/html/cgi-bin/fwhosts.cgi index c3642f0f0e..395dca83c6 100644 --- a/html/cgi-bin/fwhosts.cgi +++ b/html/cgi-bin/fwhosts.cgi @@ -27,6 +27,8 @@ use Sort::Naturally; use CGI::Carp 'fatalsToBrowser'; no warnings 'uninitialized'; require '/var/ipfire/general-functions.pl'; +require "/var/ipfire/geoip-functions.pl"; +require "/usr/lib/firewall/firewall-lib.pl"; require "${General::swroot}/lang.pl"; require "${General::swroot}/header.pl"; @@ -36,6 +38,7 @@ my %customhost=(); my %customgrp=(); my %customservice=(); my %customservicegrp=(); +my %customgeoipgrp=(); my %ccdnet=(); my %ccdhost=(); my %ipsecconf=(); @@ -62,6 +65,7 @@ my $configccdhost = "${General::swroot}/ovpn/ovpnconfig"; my $configipsec = "${General::swroot}/vpn/config"; my $configsrv = "${General::swroot}/fwhosts/customservices"; my $configsrvgrp = "${General::swroot}/fwhosts/customservicegrp"; +my $configgeoipgrp = "${General::swroot}/fwhosts/customgeoipgrp"; my $fwconfigfwd = "${General::swroot}/firewall/config"; my $fwconfiginp = "${General::swroot}/firewall/input"; my $fwconfigout = "${General::swroot}/firewall/outgoing"; @@ -73,6 +77,7 @@ unless (-e $confighost) { system("touch $confighost"); } unless (-e $configgrp) { system("touch $configgrp"); } unless (-e $configsrv) { system("touch $configsrv"); } unless (-e $configsrvgrp) { system("touch $configsrvgrp"); } +unless (-e $configgeoipgrp) { system("touch $configgeoipgrp"); } &General::readhash("${General::swroot}/main/settings", \%mainsettings); &General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); @@ -671,6 +676,84 @@ if ($fwhostsettings{'ACTION'} eq 'savegrp') &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq 'savegeoipgrp') +{ + my $grp=$fwhostsettings{'grp_name'}; + my $rem=$fwhostsettings{'remark'}; + my $count; + my $type; + my @target; + my @newgrp; + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); + + # Check for existing group name. + if (!&checkgroup($grp) && $fwhostsettings{'update'} ne 'on'){ + $errormessage = $Lang::tr{'fwhost err grpexist'}; + } + + # Check remark. + if ($rem ne '' && !&validremark($rem) && $fwhostsettings{'update'} ne 'on'){ + $errormessage = $Lang::tr{'fwhost err remark'}; + } + + if ($fwhostsettings{'update'} eq 'on'){ + @target=$fwhostsettings{'COUNTRY_CODE'}; + $type='GeoIP Group'; + + #check if host/net exists in grp + my $test="$grp,$fwhostsettings{'oldremark'},@target"; + foreach my $key (keys %customgeoipgrp) { + my $test1="$customgeoipgrp{$key}[0],$customgeoipgrp{$key}[1],$customgeoipgrp{$key}[2]"; + if ($test1 eq $test){ + $errormessage=$Lang::tr{'fwhost err isingrp'}; + $fwhostsettings{'update'} = 'on'; + } + } + } + + if (!$errormessage){ + #on first save, we have an empty @target, so fill it with nothing + my $targetvalues=@target; + if ($targetvalues == '0'){ + @target="none"; + } + #on update, we have to delete the dummy entry + foreach my $key (keys %customgeoipgrp){ + if ($customgeoipgrp{$key}[0] eq $grp && $customgeoipgrp{$key}[2] eq "none"){ + delete $customgeoipgrp{$key}; + last; + } + } + &General::writehasharray("$configgeoipgrp", \%customgeoipgrp); + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); + #create array with new lines + foreach my $line (@target){ + push (@newgrp,"$grp,$rem,$line"); + } + #append new entries + my $key = &General::findhasharraykey (\%customgeoipgrp); + foreach my $line (@newgrp){ + foreach my $i (0 .. 3) { $customgeoipgrp{$key}[$i] = "";} + my ($a,$b,$c,$d) = split (",",$line); + $customgeoipgrp{$key}[0] = $a; + $customgeoipgrp{$key}[1] = $b; + $customgeoipgrp{$key}[2] = $c; + $customgeoipgrp{$key}[3] = $type; + } + &General::writehasharray("$configgeoipgrp", \%customgeoipgrp); + #update counter in Host/Net + $fwhostsettings{'update'}='on'; + } + #check if ruleupdate is needed + my $geoipgrpcount=0; + $geoipgrpcount=&getgeoipcount($grp); + if($geoipgrpcount > 0 ) + { + &General::firewall_config_changed(); + } + &addgeoipgrp; + &viewtablegeoipgrp; +} if ($fwhostsettings{'ACTION'} eq 'saveservice') { my $ICMP; @@ -798,6 +881,12 @@ if ($fwhostsettings{'ACTION'} eq 'editgrp') &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq 'editgeoipgrp') +{ + $fwhostsettings{'update'}='on'; + &addgeoipgrp; + &viewtablegeoipgrp; +} if ($fwhostsettings{'ACTION'} eq 'editservice') { $fwhostsettings{'updatesrv'}='on'; @@ -830,6 +919,12 @@ if ($fwhostsettings{'ACTION'} eq 'resetgrp') $fwhostsettings{'remark'} =""; &showmenu; } +if ($fwhostsettings{'ACTION'} eq 'resetgeoipgrp') +{ + $fwhostsettings{'grp_name'} =""; + $fwhostsettings{'remark'} =""; + &showmenu; +} # delete if ($fwhostsettings{'ACTION'} eq 'delnet') { @@ -887,6 +982,37 @@ if ($fwhostsettings{'ACTION'} eq 'deletegrphost') &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq 'deletegeoipgrpentry') +{ + my $grpremark; + my $grpname; + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); + foreach my $key (keys %customgeoipgrp){ + if($customgeoipgrp{$key}[0].",".$customgeoipgrp{$key}[1].",".$customgeoipgrp{$key}[2].",".$customgeoipgrp{$key}[3] eq $fwhostsettings{'delentry'}){ + $grpname=$customgeoipgrp{$key}[0]; + $grpremark=$customgeoipgrp{$key}[1]; + #check if we delete the last entry, then generate dummy + if ($fwhostsettings{'last'} eq 'on'){ + $customgeoipgrp{$key}[1] = ''; + $customgeoipgrp{$key}[2] = 'none'; + $customgeoipgrp{$key}[3] = ''; + $fwhostsettings{'last'}=''; + last; + }else{ + delete $customgeoipgrp{$key}; + } + } + } + &General::writehasharray("$configgeoipgrp", \%customgeoipgrp); + &General::firewall_config_changed(); + if ($fwhostsettings{'update'} eq 'on'){ + $fwhostsettings{'remark'}= $grpremark; + $fwhostsettings{'grp_name'}=$grpname; + } + &addgeoipgrp; + &viewtablegeoipgrp; +} + if ($fwhostsettings{'ACTION'} eq 'delgrp') { &General::readhasharray("$configgrp", \%customgrp); @@ -903,6 +1029,22 @@ if ($fwhostsettings{'ACTION'} eq 'delgrp') &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq 'delgeoipgrp') +{ + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); + &decrease($fwhostsettings{'grp_name'}); + foreach my $key (sort keys %customgeoipgrp) + { + if($customgeoipgrp{$key}[0] eq $fwhostsettings{'grp_name'}) + { + delete $customgeoipgrp{$key}; + } + } + &General::writehasharray("$configgeoipgrp", \%customgeoipgrp); + $fwhostsettings{'grp_name'}=''; + &addgeoipgrp; + &viewtablegeoipgrp; +} if ($fwhostsettings{'ACTION'} eq 'delservice') { &General::readhasharray("$configsrv", \%customservice); @@ -977,6 +1119,11 @@ if ($fwhostsettings{'ACTION'} eq $Lang::tr{'fwhost newgrp'}) &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq $Lang::tr{'fwhost newgeoipgrp'}) +{ + &addgeoipgrp; + &viewtablegeoipgrp; +} if ($fwhostsettings{'ACTION'} eq $Lang::tr{'fwhost newservice'}) { &addservice; @@ -1011,6 +1158,31 @@ if ($fwhostsettings{'ACTION'} eq 'changegrpremark') &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq 'changegeoipgrpremark') +{ + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); + if ($fwhostsettings{'oldrem'} ne $fwhostsettings{'newrem'} && (&validremark($fwhostsettings{'newrem'}) || $fwhostsettings{'newrem'} eq '')){ + foreach my $key (sort keys %customgeoipgrp) + { + if($customgeoipgrp{$key}[0] eq $fwhostsettings{'grp'} && $customgeoipgrp{$key}[1] eq $fwhostsettings{'oldrem'}) + { + $customgeoipgrp{$key}[1]=''; + $customgeoipgrp{$key}[1]=$fwhostsettings{'newrem'}; + } + } + &General::writehasharray("$configgeoipgrp", \%customgeoipgrp); + $fwhostsettings{'update'}='on'; + $fwhostsettings{'remark'}=$fwhostsettings{'newrem'}; + }else{ + $errormessage=$Lang::tr{'fwhost err remark'}; + $fwhostsettings{'remark'}=$fwhostsettings{'oldrem'}; + $fwhostsettings{'grp_name'}=$fwhostsettings{'grp'}; + $fwhostsettings{'update'} = 'on'; + } + $fwhostsettings{'grp_name'}=$fwhostsettings{'grp'}; + &addgeoipgrp; + &viewtablegeoipgrp; +} if ($fwhostsettings{'ACTION'} eq 'changesrvgrpremark') { &General::readhasharray("$configsrvgrp", \%customservicegrp ); @@ -1085,6 +1257,29 @@ if ($fwhostsettings{'ACTION'} eq 'changegrpname') &addgrp; &viewtablegrp; } +if ($fwhostsettings{'ACTION'} eq 'changegeoipgrpname') +{ + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp ); + if ($fwhostsettings{'oldgrpname'} ne $fwhostsettings{'grp'}){ + #Check new groupname + if (!&validhostname($fwhostsettings{'grp'})){ + $errormessage.=$Lang::tr{'fwhost err name'}."
"; + } + if (!$errormessage){ + # Rename group. + foreach my $key (keys %customgeoipgrp) { + if($customgeoipgrp{$key}[0] eq $fwhostsettings{'oldgrpname'}){ + $customgeoipgrp{$key}[0]=$fwhostsettings{'grp'}; + } + } + &General::writehasharray("$configgeoipgrp", \%customgeoipgrp ); + #change name in FW Rules + &changenameinfw($fwhostsettings{'oldgrpname'},$fwhostsettings{'grp'},6); + } + } + &addgeoipgrp; + &viewtablegeoipgrp; +} ### VIEW ### if($fwhostsettings{'ACTION'} eq '') { @@ -1096,7 +1291,7 @@ sub showmenu { print "$Lang::tr{'fwhost welcome'}"; print<
- +
END @@ -1381,6 +1576,113 @@ END print"
"; &Header::closebox(); } +sub addgeoipgrp +{ + &hint; + &error; + &showmenu; + &Header::openbox('100%', 'left', $Lang::tr{'fwhost addgeoipgrp'}); + + my %checked=(); + my $show=''; + $checked{'check1'}{'off'} = ''; + $checked{'check1'}{'on'} = ''; + $checked{'grp2'}{$fwhostsettings{'grp2'}} = 'CHECKED'; + $fwhostsettings{'oldremark'}=$fwhostsettings{'remark'}; + $fwhostsettings{'oldgrpname'}=$fwhostsettings{'grp_name'}; + my $grp=$fwhostsettings{'grp_name'}; + my $rem=$fwhostsettings{'remark'}; + if ($fwhostsettings{'update'} eq ''){ + print< + + $Lang::tr{'fwhost addgrpname'} +
+ + + $Lang::tr{'remark'}: + + + +
+ + +END + } else { + print< + + $Lang::tr{'fwhost addgrpname'} + + + + + + + + +
+ $Lang::tr{'remark'}: + + + + + + + + + +
+ +

+END + } + if ($fwhostsettings{'update'} eq 'on') { + my @geoip_locations = &fwlib::get_geoip_locations(); + + print< + + + + + + + +
+
+

+END + } + print < + + + + + + + +
+ + + + +
+ +END + &Header::closebox(); +} sub addservice { &error; @@ -1838,6 +2140,195 @@ sub viewtablegrp &Header::closebox(); } +} +sub viewtablegeoipgrp +{ + # If our filesize is "zero" there is nothing to read-in. + if (-z "$configgeoipgrp") { + return; + } + + &Header::openbox('100%', 'left', $Lang::tr{'fwhost cust geoipgrp'}); + &General::readhasharray("$configgeoipgrp", \%customgeoipgrp); + &General::readhasharray("$fwconfigfwd", \%fwfwd); + &General::readhasharray("$fwconfiginp", \%fwinp); + &General::readhasharray("$fwconfigout", \%fwout); + my @grp=(); + my $helper=''; + my $count=1; + my $country_code; + my $grpname; + my $remark; + my $number; + my $delflag; + my @counter; + my %hash; + + # If there are no groups we are finished here. + if (!keys %customgeoipgrp) { + print "
$Lang::tr{'fwhost err emptytable'}"; + return; + } + + # Put all groups in a hash. + foreach my $key (sort { ncmp($customgeoipgrp{$a}[0],$customgeoipgrp{$b}[0]) } + sort { ncmp($customgeoipgrp{$a}[2],$customgeoipgrp{$b}[2]) } keys %customgeoipgrp) { + push (@counter,$customgeoipgrp{$key}[0]); + } + + # Increase current used key. + foreach my $key1 (@counter) { + $hash{$key1}++ ; + } + + # Sort hash. + foreach my $key (sort { ncmp($customgeoipgrp{$a}[0],$customgeoipgrp{$b}[0]) } + sort { ncmp($customgeoipgrp{$a}[2],$customgeoipgrp{$b}[2]) } keys %customgeoipgrp) { + $count++; + if ($helper ne $customgeoipgrp{$key}[0]) { + $delflag='0'; + + foreach my $key1 (sort { ncmp($customgeoipgrp{$a}[0],$customgeoipgrp{$b}[0]) } + sort { ncmp($customgeoipgrp{$a}[2],$customgeoipgrp{$b}[2]) } keys %customgeoipgrp) { + + if ($customgeoipgrp{$key}[0] eq $customgeoipgrp{$key1}[0]) + { + $delflag++; + } + if($delflag > 1){ + last; + } + } + + $number=1; + + # Groupname. + $grpname=$customgeoipgrp{$key}[0]; + + # Group remark. + $remark="$customgeoipgrp{$key}[1]"; + + # Country code. + $country_code="$customgeoipgrp{$key}[2]"; + + if ($count gt 1){ + print""; + $count=1; + } + + # Display groups header. + print "
$grpname   \n"; + print "$Lang::tr{'remark'}:  $remark  \n" if ($remark ne ''); + + # Get group count. + my $geoipgrpcount=&getgeoipcount($grpname); + print "$Lang::tr{'used'}: $geoipgrpcount x"; + + # Only display delete icon, if the group is not used by a firewall rule. + if($geoipgrpcount == '0') { + print"
\n"; + print"\n"; + print"\n"; + print"\n"; + print"
"; + } + + # Icon for group editing. +print < + + + + + + + +END + # Display headlines if the group contains any entries. + if ($country_code ne "none") { +print < + + + + + + + + +END + } + } + + # Check if our group contains any entries. + if ($country_code eq "none") { + print "\n"; + } else { + # Check if we are currently editing a group and assign column backgound colors. + my $col=''; + if ( ($fwhostsettings{'ACTION'} eq 'editgeoipgrp' || $fwhostsettings{'update'} ne '') + && $fwhostsettings{'grp_name'} eq $customgeoipgrp{$key}[0]) { + $col="bgcolor='${Header::colouryellow}'"; + } elsif ($count %2 == 0){ + $col="bgcolor='$color{'color20'}'"; + } else { + $col="bgcolor='$color{'color22'}'"; + } + + # Get country flag. + my $icon = &GeoIP::get_flag_icon($customgeoipgrp{$key}[2]); + + # Print column with flag icon. + my $col_content; + if ($icon) { + $col_content = "$customgeoipgrp{$key}[2]"; + } else { + $col_content = "N/A"; + } + + print "\n"; + + # Print column with country code. + print "\n"; + + # Print column with full country name. + my $country_name = &GeoIP::get_full_country_name($customgeoipgrp{$key}[2]); + print "\n"; + + # Generate from for removing entries from a group. + print "\n"; + print "\n"; + } + + $helper=$customgeoipgrp{$key}[0]; + $number++; + } + + print"
+ $Lang::tr{'flag'} + + $Lang::tr{'countrycode'} + + $Lang::tr{'country'} +
$Lang::tr{'fwhost err emptytable'}
$col_content$customgeoipgrp{$key}[2]$country_name
\n"; + + if ($delflag > 0){ + print"\n"; + + # Check if this group only has a single entry. + foreach my $key2 (keys %hash) { + if ($hash{$key2}<2 && $key2 eq $customgeoipgrp{$key}[0]){ + print "" ; + } + } + } + + print "\n"; + print "\n"; + print "\n"; + print "
\n"; + print "
\n"; + &Header::closebox(); } sub viewtableservice { @@ -2196,6 +2687,44 @@ sub gethostcount } return $srvcounter; } +sub getgeoipcount +{ + my $groupname=shift; + my $counter=0; + + # GeoIP groups are stored as "group:groupname" in the + # firewall settings files. + my $searchstring = join(':', "group",$groupname); + + # Count services used in firewall - forward + foreach my $key1 (keys %fwfwd) { + if($fwfwd{$key1}[4] eq $searchstring){ + $counter++; + } + if($fwfwd{$key1}[6] eq $searchstring){ + $counter++; + } + } + #Count services used in firewall - input + foreach my $key2 (keys %fwinp) { + if($fwinp{$key2}[4] eq $searchstring){ + $counter++; + } + if($fwinp{$key2}[6] eq $searchstring){ + $counter++; + } + } + #Count services used in firewall - outgoing + foreach my $key3 (keys %fwout) { + if($fwout{$key3}[4] eq $searchstring){ + $counter++; + } + if($fwout{$key3}[6] eq $searchstring){ + $counter++; + } + } + return $counter; +} sub getnetcount { my $searchstring=shift; diff --git a/html/cgi-bin/geoip-block.cgi b/html/cgi-bin/geoip-block.cgi new file mode 100644 index 0000000000..ccbfa926a0 --- /dev/null +++ b/html/cgi-bin/geoip-block.cgi @@ -0,0 +1,263 @@ +#!/usr/bin/perl +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2014 IPFire Developemnt Team # +# # +# 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 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see . # +# # +############################################################################### + +use strict; +# enable only the following on debugging purpose +#use warnings; +#use CGI::Carp 'fatalsToBrowser'; + +require '/var/ipfire/general-functions.pl'; +require "${General::swroot}/geoip-functions.pl"; +require "${General::swroot}/lang.pl"; +require "${General::swroot}/header.pl"; +require "/usr/lib/firewall/firewall-lib.pl"; + +my $notice; +my $settingsfile = "${General::swroot}/firewall/geoipblock"; + +my %color = (); +my %mainsettings = (); +my %settings = (); +my %cgiparams = (); + +# Read configuration file. +&General::readhash("$settingsfile", \%settings); + +&General::readhash("${General::swroot}/main/settings", \%mainsettings); +&General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); + +&Header::showhttpheaders(); + +#Get GUI values +&Header::getcgihash(\%cgiparams); + +# Call subfunction to get all available locations. +my @locations = &fwlib::get_geoip_locations(); + +if ($cgiparams{'ACTION'} eq $Lang::tr{'save'}) { + # Check if we want to disable geoipblock. + if (exists $cgiparams{'GEOIPBLOCK_ENABLED'}) { + $settings{'GEOIPBLOCK_ENABLED'} = "on"; + } else { + $settings{'GEOIPBLOCK_ENABLED'} = "off"; + } + + # Loop through our locations array to prevent from + # non existing countries or code. + foreach my $cn (@locations) { + # Check if blocking for this country should be enabled/disabled. + if (exists $cgiparams{$cn}) { + $settings{$cn} = "on"; + } else { + $settings{$cn} = "off"; + } + } + + &General::writehash("$settingsfile", \%settings); + + # Mark the firewall config as changed. + &General::firewall_config_changed(); + + # Assign reload notice. We directly can use + # the notice from p2p block. + $notice = $Lang::tr{'p2p block save notice'}; +} + +&Header::openpage($Lang::tr{'geoipblock configuration'}, 1, ''); + +# Print notice that a firewall reload is required. +if ($notice) { + &Header::openbox('100%', 'left', $Lang::tr{'notice'}); + print "$notice"; + &Header::closebox(); +} + +# Checkbox pre-selection. +my $checked; +if ($settings{'GEOIPBLOCK_ENABLED'} eq "on") { + $checked = "checked='checked'"; +} + +# Print box to enable/disable geoipblock. +print"
\n"; + +&Header::openbox('100%', 'center', $Lang::tr{'geoipblock'}); +print < + + $Lang::tr{'geoipblock enable feature'} + + + +
+ + + +
+ + + + + +
+END + +&Header::closebox(); + +&Header::openbox('100%', 'center', $Lang::tr{'geoipblock block countries'}); +### JAVA SCRIPT ### +print < + // Function to allow checking all checkboxes at once. + function check_all() { + \$("#countries").find(":checkbox").prop("checked", true); + } + + function uncheck_all() { + \$("#countries").find(":checkbox").prop("checked", false); + } + + + + + + + + + + + + + + + + +END + +my $lines; +my $lines2; +my $col; +foreach my $location (@locations) { + # Country code in upper case. (DE) + my $ccode_uc = $location; + + # County code in lower case. (de) + my $ccode_lc = lc($location); + + # Full name of the country based on the country code. + my $cname = &GeoIP::get_full_country_name($ccode_lc); + + # Get flag icon for of the country. + my $flag_icon = &GeoIP::get_flag_icon($ccode_uc); + + my $flag; + # Check if a flag for the country is available. + if ($flag_icon) { + $flag="$ccode_uc"; + } else { + $flag="N/A"; + } + + # Checkbox pre-selection. + my $checked; + if ($settings{$ccode_uc} eq "on") { + $checked = "checked='checked'"; + } + + # Colour lines. + if ($lines % 2) { + $col="bgcolor='$color{'color20'}'"; + } else { + $col="bgcolor='$color{'color22'}'"; + } + + # Grouping elements. + my $line_start; + my $line_end; + if ($lines2 % 2) { + # Increase lines (background color by once. + $lines++; + + # Add empty column in front. + $line_start=""; + + # When the line number can be diveded by "2", + # we are going to close the line. + $line_end=""; + } else { + # When the line number is not divideable by "2", + # we are starting a new line. + $line_start=""; + $line_end; + } + + print "$line_start\n"; + print "\n"; + print "\n"; + print "$line_end\n"; + +$lines2++; +} + +print < + +
+ $Lang::tr{'flag'} + + $Lang::tr{'countrycode'} + + $Lang::tr{'country'} +   + $Lang::tr{'flag'} + + $Lang::tr{'countrycode'} + + $Lang::tr{'country'} +
 
$flag$ccode_uc$cname
+ + + + + + +
+ $Lang::tr{'check all'} / + $Lang::tr{'uncheck all'} +
+ +
+ + + + + + + + +
$Lang::tr{'geoipblock country is blocked'}$Lang::tr{'geoipblock country is allowed'}
+END + +&Header::closebox(); +print"\n"; + +&Header::closebigbox(); +&Header::closepage(); diff --git a/langs/en/cgi-bin/en.pl b/langs/en/cgi-bin/en.pl index 1986409349..fa014a92f9 100644 --- a/langs/en/cgi-bin/en.pl +++ b/langs/en/cgi-bin/en.pl @@ -435,6 +435,7 @@ 'bit' => 'bit', 'bitrate' => 'Bitrate', 'bleeding rules' => 'Bleeding Edge Snort Rules', +'block' => 'Block', 'blue' => 'BLUE', 'blue access' => 'Blue Access', 'blue access use hint' => 'You have to enter the MAC or the IP Address for a device. To enter both is also possible', @@ -550,6 +551,7 @@ 'chain' => 'Chain', 'change passwords' => 'Change passwords', 'change share' => 'edit share options', +'check all' =>'Check all', 'check for net traffic update' => 'Check for Net-Traffic updates', 'check vpn lr' => 'Check', 'choose config' => 'Choose config', @@ -1094,6 +1096,7 @@ 'fwhost OpenVPN static host' => 'OpenVPN static host', 'fwhost OpenVPN static network' => 'OpenVPN static network', 'fwhost Standard Network' => 'Standard network', +'fwhost addgeoipgrp' => 'Add new GeoIP group', 'fwhost addgrp' => 'Add new network/host group', 'fwhost addgrpname' => 'Group name:', 'fwhost addhost' => 'Add new host', @@ -1109,6 +1112,9 @@ 'fwhost change' => 'Modify', 'fwhost changeremark' => 'You modified just the remark', 'fwhost cust addr' => 'Hosts', +'fwhost cust geoip' => 'GeoIP Groups', +'fwhost cust geoipgroup' => 'GeoIP Groups', +'fwhost cust geoiplocation' => 'GeoIP Locations', 'fwhost cust grp' => 'Network/Host Groups', 'fwhost cust net' => 'Networks', 'fwhost cust service' => 'Services', @@ -1155,6 +1161,7 @@ 'fwhost ipsec net' => 'IPsec networks:', 'fwhost menu' => 'Firewall Groups', 'fwhost netaddress' => 'Network address', +'fwhost newgeoipgrp' => 'GeoIP Groups', 'fwhost newgrp' => 'Network/Host Groups', 'fwhost newhost' => 'Hosts', 'fwhost newnet' => 'Networks', @@ -1191,6 +1198,16 @@ 'generating the root and host certificates may take a long time. it can take up to several minutes on older hardware. please be patient' => 'Generating the root and host certificates may take a long time. It can take up to several minutes on older hardware. Please be patient.', 'genkey' => 'Generate PSK', 'genre' => 'Genre', +'geoip' => 'GeoIP', +'geoipblock' => 'GeoIP Block', +'geoipblock block countries' => 'Block countries', +'geoipblock configuration' => 'GeoIP Configuration', +'geoipblock country code' => 'Country Code', +'geoipblock country is allowed' => 'Traffic from this country is allowed', +'geoipblock country is blocked' => 'Traffic from this country will be blocked', +'geoipblock country name' => 'Country Name', +'geoipblock enable feature' => 'Enable GeoIP based blocking:', +'geoipblock flag' => 'Flag', 'global settings' => 'Global Settings', 'gpl i accept these terms and conditions' => 'I accept these terms and conditions', 'gpl license agreement' => 'License Agreement', @@ -2247,8 +2264,11 @@ 'type' => 'Type', 'umount' => 'Umount', 'umount removable media before to unplug' => 'Umount removable media before unplugging the device', +'uncheck all' => 'Uncheck all', 'unable to alter profiles while red is active' => 'Unable to alter profiles while RED is active.', 'unable to contact' => 'Unable to contact', +'unblock' => 'Unblock', +'unblock all' => 'Unblock all', 'unencrypted' => 'Unencrypted', 'uninstall' => 'Uninstall', 'unix charset' => 'UNIX Charset', diff --git a/lfs/Locale-Country b/lfs/Locale-Country index b2c1455efe..02bf7a026e 100644 --- a/lfs/Locale-Country +++ b/lfs/Locale-Country @@ -24,7 +24,7 @@ include Config -VER = 2.07 +VER = 3.33 THISAPP = Locale-Codes-$(VER) DL_FILE = $(THISAPP).tar.gz @@ -40,7 +40,7 @@ objects = $(DL_FILE) $(DL_FILE) = $(DL_FROM)/$(DL_FILE) -$(DL_FILE)_MD5 = af0537cc4a882096d0320612c440df6d +$(DL_FILE)_MD5 = bc7496f97889de8504e80addaa0ee40c install : $(TARGET) diff --git a/lfs/perl-Text-CSV_XS b/lfs/perl-Text-CSV_XS new file mode 100644 index 0000000000..f94593f983 --- /dev/null +++ b/lfs/perl-Text-CSV_XS @@ -0,0 +1,77 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2014 IPFire Team # +# # +# 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 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see . # +# # +############################################################################### + + +############################################################################### +# Definitions +############################################################################### + +include Config +VER = 1.12 + +THISAPP = Text-CSV_XS-$(VER) +DL_FILE = ${THISAPP}.tgz +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP) +TARGET = $(DIR_INFO)/$(THISAPP) + +############################################################################### +# Top-level Rules +############################################################################### + +objects = $(DL_FILE) + +$(DL_FILE) = $(DL_FROM)/$(DL_FILE) + +$(DL_FILE)_MD5 = b91f2d806054b68c2a29d3da5821fe87 + +install : $(TARGET) + +check : $(patsubst %,$(DIR_CHK)/%,$(objects)) + +download :$(patsubst %,$(DIR_DL)/%,$(objects)) + +md5 : $(subst %,%_MD5,$(objects)) + +############################################################################### +# Downloading, checking, md5sum +############################################################################### + +$(patsubst %,$(DIR_CHK)/%,$(objects)) : + @$(CHECK) + +$(patsubst %,$(DIR_DL)/%,$(objects)) : + @$(LOAD) + +$(subst %,%_MD5,$(objects)) : + @$(MD5) + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE) + cd $(DIR_APP) && perl Makefile.PL + cd $(DIR_APP) && make $(MAKETUNING) $(EXTRA_MAKE) + cd $(DIR_APP) && make install + @rm -rf $(DIR_APP) + @$(POSTBUILD) diff --git a/lfs/stage2 b/lfs/stage2 index 895ee153bc..4388114c12 100644 --- a/lfs/stage2 +++ b/lfs/stage2 @@ -55,7 +55,7 @@ $(TARGET) : -install -dv -m 1777 /tmp /var/tmp -mkdir -pv /usr/{,local/}{bin,include,lib{,/sse2},sbin,src} -mkdir -pv /usr/{,local/}share/{doc,info,locale,man} - -mkdir -v /usr/{,local/}share/{misc,terminfo,zoneinfo} + -mkdir -v /usr/{,local/}share/{misc,terminfo,xt_geoip,zoneinfo} -mkdir -pv /usr/{,local/}share/man/man{1..8} #-for dir in /usr /usr/local; do \ # ln -sv share/{man,doc,info} $$dir; \ diff --git a/lfs/xtables-addons b/lfs/xtables-addons new file mode 100644 index 0000000000..1848dc9088 --- /dev/null +++ b/lfs/xtables-addons @@ -0,0 +1,110 @@ +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2007-2014 IPFire Team # +# # +# 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 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see . # +# # +############################################################################### + +############################################################################### +# Definitions +############################################################################### + +include Config + +VERSUFIX = ipfire$(KCFG) +MODPATH = /lib/modules/$(KVER)-$(VERSUFIX)/extra/ + +VER = 2.6 + +THISAPP = xtables-addons-$(VER) +DL_FILE = $(THISAPP).tar.xz +DL_FROM = $(URL_IPFIRE) +DIR_APP = $(DIR_SRC)/$(THISAPP) + +ifeq "$(USPACE)" "1" + TARGET = $(DIR_INFO)/$(THISAPP) +else + TARGET = $(DIR_INFO)/$(THISAPP)-kmod-$(KVER)-$(VERSUFIX) +endif + +############################################################################### +# Top-level Rules +############################################################################### + +objects = $(DL_FILE) + +$(DL_FILE) = $(DL_FROM)/$(DL_FILE) + +$(DL_FILE)_MD5 = 087835ba7e564481b6fd398692268340 + +install : $(TARGET) + +check : $(patsubst %,$(DIR_CHK)/%,$(objects)) + +download :$(patsubst %,$(DIR_DL)/%,$(objects)) + +md5 : $(subst %,%_MD5,$(objects)) + +dist: + $(PAK) + +############################################################################### +# Downloading, checking, md5sum +############################################################################### + +$(patsubst %,$(DIR_CHK)/%,$(objects)) : + @$(CHECK) + +$(patsubst %,$(DIR_DL)/%,$(objects)) : + @$(LOAD) + +$(subst %,%_MD5,$(objects)) : + @$(MD5) + +############################################################################### +# Installation Details +############################################################################### + +$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) + @$(PREBUILD) + @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE) + + # Only build the specified modules. + cp -avf $(DIR_SRC)/config/xtables-addons/mconfig \ + $(DIR_APP)/mconfig + +# Check if we build the modules for a kernel or the userspace parts. +ifeq "$(USPACE)" "1" + cd $(DIR_APP) && ./configure \ + --prefix=/usr \ + --without-kbuild + + cd $(DIR_APP) && make $(MAKETUNING) + cd $(DIR_APP) && make install +else + cd $(DIR_APP) && ./configure \ + --with-kbuild=/usr/src/linux-$(KVER)/ + + cd $(DIR_APP) && make $(MAKETUNING) + + # Install the built kernel modules. + cd $(DIR_APP) && for f in $$(ls extensions/*.ko); do \ + install -m 644 $$f $(MODPATH); \ + done +endif + + @rm -rf $(DIR_APP) + @$(POSTBUILD) diff --git a/make.sh b/make.sh index 92edf78cea..9f77df59be 100755 --- a/make.sh +++ b/make.sh @@ -383,6 +383,7 @@ buildipfire() { export LOGFILE ipfiremake configroot ipfiremake backup + ipfiremake pkg-config ipfiremake libusb ipfiremake libusbx ipfiremake libpcap @@ -403,6 +404,8 @@ buildipfire() { ipfiremake multipath-tools ipfiremake freetype ipfiremake grub + ipfiremake libmnl + ipfiremake iptables case "${TARGET_ARCH}" in i586) @@ -413,6 +416,7 @@ buildipfire() { ipfiremake e1000e KCFG="-pae" ipfiremake igb KCFG="-pae" ipfiremake ixgbe KCFG="-pae" + ipfiremake xtables-addons KCFG="-pae" ipfiremake linux-initrd KCFG="-pae" # x86 kernel build @@ -422,6 +426,7 @@ buildipfire() { ipfiremake e1000e KCFG="" ipfiremake igb KCFG="" ipfiremake ixgbe KCFG="" + ipfiremake xtables-addons KCFG="" ipfiremake linux-initrd KCFG="" ;; @@ -430,6 +435,7 @@ buildipfire() { ipfiremake linux KCFG="-rpi" ipfiremake backports KCFG="-rpi" ipfiremake cryptodev KCFG="-rpi" + ipfiremake xtables-addons KCFG="-rpi" ipfiremake linux-initrd KCFG="-rpi" # arm multi platform (Panda, Wandboard ...) kernel build @@ -439,6 +445,7 @@ buildipfire() { ipfiremake e1000e KCFG="-multi" ipfiremake igb KCFG="-multi" ipfiremake ixgbe KCFG="-multi" + ipfiremake xtables-addons KCFG="-multi" ipfiremake linux-initrd KCFG="-multi" # arm-kirkwood (Dreamplug, ICY-Box ...) kernel build @@ -448,10 +455,11 @@ buildipfire() { ipfiremake e1000e KCFG="-kirkwood" ipfiremake igb KCFG="-kirkwood" ipfiremake ixgbe KCFG="-kirkwood" + ipfiremake xtables-addons KCFG="-kirkwood" ipfiremake linux-initrd KCFG="-kirkwood" ;; esac - ipfiremake pkg-config + ipfiremake xtables-addons USPACE="1" ipfiremake openssl ipfiremake openssl-compat ipfiremake libgpg-error @@ -526,8 +534,6 @@ buildipfire() { ipfiremake mtools ipfiremake initscripts ipfiremake whatmask - ipfiremake libmnl - ipfiremake iptables ipfiremake conntrack-tools ipfiremake libupnp ipfiremake ipaddr @@ -809,6 +815,7 @@ buildipfire() { ipfiremake squid-accounting ipfiremake pigz ipfiremake tmux + ipfiremake perl-Text-CSV_XS ipfiremake swconfig } diff --git a/src/initscripts/init.d/firewall b/src/initscripts/init.d/firewall index c383652e0b..8ca02bc9d1 100644 --- a/src/initscripts/init.d/firewall +++ b/src/initscripts/init.d/firewall @@ -179,6 +179,11 @@ iptables_init() { iptables -A OUTPUT -o "${BLUE_DEV}" -j DHCPBLUEOUTPUT fi + # GeoIP block + iptables -N GEOIPBLOCK + iptables -A INPUT -j GEOIPBLOCK + iptables -A FORWARD -j GEOIPBLOCK + # trafic from ipsecX/TUN/TAP interfaces, before "-i GREEN_DEV" accept everything iptables -N IPSECINPUT iptables -N IPSECFORWARD diff --git a/src/initscripts/init.d/networking/red.up/99-geoip-database b/src/initscripts/init.d/networking/red.up/99-geoip-database new file mode 100644 index 0000000000..020f2fa2da --- /dev/null +++ b/src/initscripts/init.d/networking/red.up/99-geoip-database @@ -0,0 +1,20 @@ +#!/bin/bash + +# Get the GeoIP database if no one exists yet. + +DIR=/usr/share/xt_geoip + +found=false + +# Check if the directory contains any data. +for i in $DIR/*; do + found=true + break +done + +# Download ruleset if none has been found. +if ! ${found}; then + /us/local/bin/xt_geoip_update >/dev/null 2>&1 +fi + +exit 0 diff --git a/src/scripts/xt_geoip_build b/src/scripts/xt_geoip_build new file mode 100644 index 0000000000..202156f130 --- /dev/null +++ b/src/scripts/xt_geoip_build @@ -0,0 +1,89 @@ +#!/usr/bin/perl +# +# Converter for MaxMind CSV database to binary, for xt_geoip +# Copyright © Jan Engelhardt, 2008-2011 +# +use Getopt::Long; +use IO::Handle; +use Text::CSV_XS; # or trade for Text::CSV +use strict; + +my $csv = Text::CSV_XS->new({ + allow_whitespace => 1, + binary => 1, + eol => $/, +}); # or Text::CSV +my $target_dir = "."; + +&Getopt::Long::Configure(qw(bundling)); +&GetOptions( + "D=s" => \$target_dir, +); + +if (!-d $target_dir) { + print STDERR "Target directory $target_dir does not exist.\n"; + exit 1; +} + +my $dir = "$target_dir/LE"; +if (!-e $dir && !mkdir($dir)) { + print STDERR "Could not mkdir $dir: $!\n"; + exit 1; +} + +&dump(&collect()); + +sub collect +{ + my %country; + + while (my $row = $csv->getline(*ARGV)) { + if (!defined($country{$row->[4]})) { + $country{$row->[4]} = { + name => $row->[5], + pool_v4 => [], + pool_v6 => [], + }; + } + my $c = $country{$row->[4]}; + + push(@{$c->{pool_v4}}, [$row->[2], $row->[3]]); + + if ($. % 4096 == 0) { + print STDERR "\r\e[2K$. entries"; + } + } + + print STDERR "\r\e[2K$. entries total\n"; + return \%country; +} + +sub dump +{ + my $country = shift @_; + + foreach my $iso_code (sort keys %$country) { + &dump_one($iso_code, $country->{$iso_code}); + } +} + +sub dump_one +{ + my($iso_code, $country) = @_; + my($file, $fh_le, $fh_be); + + printf "%5u IPv4 ranges for %s %s\n", + scalar(@{$country->{pool_v4}}), + $iso_code, $country->{name}; + + $file = "$target_dir/LE/".uc($iso_code).".iv4"; + if (!open($fh_le, "> $file")) { + 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]); + } + close $fh_le; +} diff --git a/src/scripts/xt_geoip_update b/src/scripts/xt_geoip_update new file mode 100644 index 0000000000..3ad34d0c6d --- /dev/null +++ b/src/scripts/xt_geoip_update @@ -0,0 +1,118 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2014 IPFire Development Team # +# # +# 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 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty 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, see . # +# # +############################################################################### + +TMP_PATH=$(mktemp -d) +TMP_FILE=$(mktemp) + +SCRIPT_PATH=/usr/libexec/xtables-addons +DEST_PATH=/usr/share/xt_geoip + +DL_URL=http://geolite.maxmind.com/download/geoip/database +DL_FILE=GeoIPCountryCSV.zip + +CSV_FILE=GeoIPCountryWhois.csv + +ARCH=LE + +function download() { + echo "Downloading latest GeoIP ruleset..." + + # Get the latest GeoIP database from server. + wget $DL_URL/$DL_FILE -O $TMP_PATH/$TMP_FILE + + # Extract files. + unzip $TMP_PATH/$TMP_FILE -d $TMP_PATH + + return 0 +} + +function build() { + echo "Convert database..." + + # Check if the csv file exists. + if [ ! -e $TMP_PATH/$CSV_FILE ]; then + echo "$TMP_PATH/$CSV_FILE not found. Exiting." + return 1 + fi + + # Run script to convert the CSV file into several xtables + # compatible binary files. + if ! $SCRIPT_PATH/xt_geoip_build $TMP_DIR/$CSV_FILE -D $TMP_DIR; then + echo "Could not convert ruleset. Aborting." >&2 + return 1 + fi + + return 0 +} + +function install() { + echo "Install databases..." + + # Check if our destination exist. + if [ ! -e "$DEST_PATH" ]; then + mkdir -p $DEST_PATH &>/dev/null + fi + + # Install databases. + if ! cp -af $TMP_PATH/$ARCH $DEST_PATH &>/dev/null; then + echo "Could not copy files. Aborting." >&2 + return 1 + fi + + return 0 +} + +function cleanup() { + echo "Cleaning up temporary files..." + if ! rm -rf $TMP_PATH &>/dev/null; then + echo "Could not remove files. Aborting." >&2 + return 1 + fi + + return 0 +} + +function main() { + # Download ruleset. + download || exit $? + + # Convert the ruleset. + if ! build; then + # Do cleanup. + cleanup || exit $? + exit 1 + fi + + # Install the converted ruleset. + if ! install; then + # Do cleanup. + cleanup || exit $? + exit 1 + fi + + # Finaly remove temporary files. + cleanup || exit $? + + return 0 +} + +# Run the main function. +main