Country-based packet filtering with iptables
Posted by imagine on Tue 17 Apr 2007 at 17:59
Bruteforce attacks shouldn't pose a real security risk to any server but are still annoying and clog up your logfiles. Many methods to block these break-in attempts exist, like BlockHosts, Fail2ban or rate-limiting incoming connections. However, on my search I also came across one tool for which I couldn't find an easy guide: geoip. geoip is a module for netfilter/iptables and allows you to filter packets based on the country they come from or go to. Following is a step-by-step guide on how to install geoip.
Obviously the module can also be used for other things than just blocking bruteforce attacks. For example for what the original author calls "racist routing", that is to prevent users from certain countries from accessing your webserver or whatever. But as always it's up to everyone individually what he uses it for.
First off let me say that I don't administrate servers for a living but only do this in my spare time, so be warned. If you find any errors or wrongdoings please correct them in the comments.
I'll use Debian 4.0 in this howto, but in principle it should work with most others GNU/Linux distribution too. I also tried it on Ubuntu 6.10, where it works with very minor changes. Of course you'll have to use something else than apt-get on non-Debian systems, but people who spend their time setting up iptables-rules will probably figure this out for themselves.
What we'll need for geoip to work is a new kernel module, a library for iptables and a file with the IP-to-country mapping. There will be no kernel recompilation.
First get the sources of the kernel you use. If you use the standard kernel of Etch that currently is:
# apt-get install linux-source-2.6.18apt-get will put a compressed archive containing the source code in /usr/src/, which we will extract:
# tar xjf /usr/src/linux-source-<VERSION>.tar.bz2 -C /usr/src/Replace <VERSION> by the version number of your kernel, in Etch it's currently 2.6.18. Since the source code is about 300MB big, this will take some time.
Next get the source code of iptables. We won't recompile iptables, but we need the sources to build the necessary library. We'll create a temporary directory to work in:
# mkdir ~/geoip # cd ~/geoip/ # apt-get source iptablesYou must have the dpkg-dev package installed to use the last command.
Now only the geoip-files are missing:http://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/. If you use a very old kernel, you may have to pick an older version, but other than that the newest snapshot is fine. At the moment that is:
# tar xjf patch-o-matic-ng-20070414.tar.bz2Then extract the geoip-files into a subfolder of the new patch-o-matic-ng-directory:
# tar xzf geoip.tar.gz -C patch-o-matic-ng-20070414/patchlets/
Patch the kernel and the iptables source code with patch-o-matic-ng:
# cd patch-o-matic-ng-20070407/ # KERNEL_DIR=/usr/src/linux-source-<VERSION>/ IPTABLES_DIR=~/geoip/iptables-<VERSION>/iptables/ ./runme geoipAgain, replace both <VERSION>-tags with the appropriate versions of your kernel and iptables. At the moment of this writing the version of iptables in Etch is 18.104.22.168debian1.
If everything's right, patch-o-matic-ng will present you an explanation of the geoip-patch and ask if you want to apply it. Answer y, patch-o-matic-ng will then print a success message and exit.
3. Building and installing the geoip kernel module
To build, we need the build-essential package or anything similar which will provide us with gcc, make, etc:
# apt-get install build-essentialBecause we need a configuration file for the kernel, we will just use the configuration of the currently running kernel:
# cd /usr/src/linux-source-<VERSION>/ # make oldconfigDuring the configuation process make will ask:
geoip match support (IP_NF_MATCH_GEOIP) [N/m/?] (NEW)Type m to use it as a module.
Prepare the build process of the kernel modules:
# make modules_prepareThen compile the modules. Unfortunately I don't know how to compile only the geoip module, so we'll have to compile all netfilter modules until someone has a better idea:
# make -C $(pwd) M=net/ipv4/netfilter/ modules
If all went well, ipt_geoip.ko should have been created in net/ipv4/netfilter/. We copy it to the other modules of our current kernel:
# cp net/ipv4/netfilter/ipt_geoip.ko /lib/modules/$(uname -r)/kernel/net/ipv4/netfilter/Activate the new module:
# depmod # modprobe ipt_geoip # echo "ipt_geoip" >> /etc/modules
4. Building and installing the iptables library
Build the shared object:
# cd ~/geoip/iptables-<VERSION>/iptables/ make KERNEL_DIR=/usr/src/linux-source-<VERSION>/ extensions/libipt_geoip.soAs before, substitute <VERSION> with the version of iptables and the kernel.
Copy the created file to the other iptables libraries:
cp extensions/libipt_geoip.so /lib/iptables/
5. Creating the IP-country mapping
We will use the freely available database from MaxMind. It has a claimed accuracy of 98% and is updated once a month. If that's not enough, you can buy a more accurate version from MaxMind.
Download the file and extract it:
# cd ~/geoip/ # wget http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip # unzip GeoIPCountryCSV.zipAs you can check with an editor, the extracted file is a list of comma separated values. Since seeking through such a list is pretty slow, we will convert the file into binary format using csv2bin, a tool also supplied by the author of geoip.
# wget http://people.netfilter.org/peejix/geoip/tools/csv2bin-20041103.tar.gz # tar xzf csv2bin-20041103.tar.gz # cd csv2bin/ # make # ./csv2bin ../GeoIPCountryWhois.csvThat will create two files, geoipdb.bin and geoipdb.idx, which the geoip module expects in /var/geoip.
# mkdir /var/geoip # mv geoipdb.* /var/geoip/
6. Using iptables with geoip support
That was it, you can now filter packets on a country basis:
# # Block access to your SSH daemon except from Afghanistan # iptables -A INPUT -p tcp --dport 22 -m geoip ! --src-cc AF -j REJECT # # Block pinging hosts in France, Italy, Spain # iptables -A OUTPUT -p icmp -m geoip --dst-cc FR,IT,ES -j REJECT # # Help # iptables -m geoip --help
If you want, you can delete the ~/geoip/ and /usr/src/linux-source-<VERSION> directories now.