Install and Test Kernel Module
What would normally be the most time consuming portion has been taken care of for us by the Ubuntu package maintainers. We need to install xtables-addons, which will build, among other things, the GeoIP module for use with iptables. You will also need unzip for dealing with the country code data we will download later and the kernel source matching your running kernel. Without the kernel source, xtables-addons-dkms package will not automatically build modules for us.
sudo apt-get install linux-headers-XXX unzip xtables-addons-commonThat will also pull in xtables-addons-dkms as a dependency. If all goes well, the kernel modules will be automatically built immediately after installation. You should see xt_geoip.ko scroll by; that's the one we are interested in now.
Test the module now with a quick iptables command. At this point, the command will fail, but the output will still be useful to us. On the off chance that you have the GeoIP database already installed, I would recommend not using a port that you are currently using to access your Linux box, just in case.
sudo iptables -A INPUT -p tcp --dport 80 -m geoip ! --src-cc US -j DROPThis is what you want to see. It means that the geoip module loaded and is looking for a file in a statically defined location.
Could not open /usr/share/xt_geoip/LE/US.iv0: No such file or directoryIf you see an error like "Couldn't load match 'geoip'", it means that iptables was not able to load the geoip module, and that means that xtables-addons was not able to build them. The most likely cause of that is missing or incorrect kernel headers.
If you don't get any errors at all, it means the command succeeded and you now have a geoip filtering rule in your firewall set. You're done, go outside and play.
Install GeoIP Database
This is where Ubuntu 11.04 leaves you; you've got the module installed and working, but without a database, it is worthless. Ubuntu does offer other GeoIP packages, like geoip-bin and geoip-database. Of those, the database one looks promising on the surface, but it won't help us with filtering. Package geoip-database installs an IPv4 and IPv6 databases in /usr/share/GeoIP, but they are not in a format usable by the GeoIP filter kernel module.
To install a usable database, go the the xtables-addons home page on SourceForge and download the latest tar ball. The latest at the time of this writing is 1.38.
wget http://sourceforge.net/projects/xtables-addons/files/Xtables-addons/1.38/xtables-addons-1.38.tar.xzCreate the required directory structure:
sudo mkdir -p /usr/share/xt_geoipThere are only two files we need out of the tarball, a couple of perl scripts: xt_geoip_dl and xt_geoip_build. The former downloads zipped CSV country codes while the latter converts the CSV data into a binary database format for faster lookups. Extract them and move them to /usr/share/xt_geoip.
Run the download script first:
cd /usr/share/xt_geoipBefore running the build script, there are two additional steps required. First is the installation of a perl module that xt_geoip_dl requires. This module was not installed by default in my Ubuntu build.
sudo ./xt_geoip_dl
sudo apt-get install libtext-csv-xs-perl
That was the only dependency I was missing, but your mileage may vary.
Next, we need to tweak the script a little. The geoip kernel module will be looking for files named <CountryCode>.iv0, but the build script creates <CountryCode>.iv[4,6]. This discrepancy, I believe, is caused by a downlevel geoip module included in Ubuntu 11.04's xtable-addons package. You could solve this problem another way than I show here; for instance you can build the geoip module from source using the tar file downloaded earlier. The following method, however, is quicker and it works fine for me.
Edit xt_geoip_build and locate the line '$file = "$target_dir/LE/".uc($iso_code).".iv4";'. In 1.38, it is line 106. Change the ".iv4" part into ".iv0" and save the file.
From this:
Now for a real test; this time we are hoping for success! Try the previous iptables command again, and if all goes well, you will be greeted with blessed nothingness:
From this:
106 $file = "$target_dir/LE/".uc($iso_code).".iv4";To this:
107 if (!open($fh_le, "> $file")) {
108 print STDERR "Error opening $file: $!\n";
109 exit 1;
110 }
106 $file = "$target_dir/LE/".uc($iso_code).".iv0";Now we can run the build script. The following will convert the CSV data into binary and store the result in the current directory, which should still be /usr/share/xt_geoip.
107 if (!open($fh_le, "> $file")) {
108 print STDERR "Error opening $file: $!\n";
109 exit 1;
110 }
sudo ./xt_geoip_build -D . *.csvTwo new directories are now created, BE and LE, and they are full of country code files. You might notice that we did not change the extension of the files in the BE directory. I don't believe this is necessary, because the xtables-addons geoip package only uses the LE files (which I think stands for Limited Edition, which is the freebie stuff offered by the kind folks at MaxMind).
Now for a real test; this time we are hoping for success! Try the previous iptables command again, and if all goes well, you will be greeted with blessed nothingness:
sudo iptables -A INPUT -p tcp --dport 80 -m geoip ! --src-cc US -j DROPIf there were no errors, you can double-check that the add was successful by running this:
sudo iptables -LHopefully you will see a line similar to the following in your INPUT chain:
DROP tcp -- anywhere anywhere tcp dpt:www Source country: ! USTo remove the rule, simply replace the add command with a delete (-A to -D):
sudo iptables -D INPUT -p tcp --dport 80 -m geoip ! --src-cc US -j DROPAll pau.