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.
1. Preparations
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:
# wget http://people.netfilter.org/peejix/patchlets/geoip.tar.gzTo apply them we need the netfilter tool patch-o-matic-ng from 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:
# wget http://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/patch-o-matic-ng-20070414.tar.bz2Extract patch-o-matic-ng:
# 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/
2. Patching
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 1.3.6.0debian1.
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.
cp /boot/config-$(uname -r) .config--------
Felipe Sateler
[ Parent | Reply to this comment ]
make oldconfig created an exact copy of /boot/config-$(uname -r) (except the timestamp of course) also without copying the file first. So I wonder if this step can be omitted.
[ Parent | Reply to this comment ]
--------
Felipe Sateler
[ Parent | Reply to this comment ]
You don't block a whole country because of a bruteforce attack. However, here
are some situations where you can encounter it:
http://news.netcraft.com/archives/2004/10/26/bush_campaign_web_si te_rejects_nonus_visitors.html
http://newsvote.bbc.co.uk/2/hi/technology/3958665.stm
I can't think of anything positive to do with this technology.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
and now to something completely non-techie:
speaking of "racist routing" seems to me to be multi-dimensional rubbish. the article presents a technology, that gives you the ability to alter the behaviour of your firewall based on certan ip-ranges. paralleling ip-ranges with countries, and countries with nationalities, or countries with "races" (a concept without a scientific basis, but a long discriminatory history) is politically speaking simply non-sense. i'm definitely unable to think of any explanatory value of the word "race" in this context.
what's next? elitist routing, class-based routing, os-based routing (... -m geoip ! --src-os un*x -j REJECT)
sorry, but also technical articles should be based on a certain amount of critical scrutiny.
raf
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
This way, you can limit say ssh to only allow IPs in the UK.
That seems pretty useful to me.
[ Parent | Reply to this comment ]
I'm using atm a /etc/hosts.deny which blocks the whole Asian-IP's... and why?
Because I'll NEVER login from this part of this world and thus no one else should.
[ Parent | Reply to this comment ]
Similarly, you make have an 'intranet' for your roving employees. Rather than solving it with everyones blanket soltuion - ie a VPN solution (massive overkill), you can just block http/https from non-local ip addresses.
You could even block your VPN ports from non-local.
[ Parent | Reply to this comment ]
I do like the term "rascist routing" sounds real dramatic..
[ Parent | Reply to this comment ]
In my opinion it's not about right or wrong, used or abused, problem or not, not if geoip is good or bad, but more about your point of view, your personal belief or more general your philosophy of life.
I don't think censorship or the withholding of knowledge creates a better or safer world. I believe in full disclosure, not only of security issues but of any non-personal information. But there were already so many articles written for and against it, that everything I could write here would just be a repetition, so I'm not going to dig into it any further.
[ Parent | Reply to this comment ]
Iptables can't filter races, radio stations, tv channels or anything else that isn't an IP packet.
Can't think of anything positive to do with this technology? Not surprising considering your opening statement.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
The most effective method I have found for preventing these brute force attacks is to drop connections after a certain number of attempts within a certain amount of time (from a given IP address).
It seems that the attack machines assume that the host is no longer reachable and move onto other potential targets, so this method is better than rate limiting.
I think this has been covered in Debian Administration before, but I couldn't find the article, so here are the lines that I add to my /etc/network/interfaces file:
up /sbin/iptables -A INPUT -m state --state NEW -p tcp --dport 22 -m recent --update --seconds 300 --hitcount 5 -j DROP up /sbin/iptables -A INPUT -m state --state NEW -p tcp --dport 22 -m recent --set -j ACCEPT down /sbin/iptables -F INPUT
This will allow 5 connections within 5 minutes (300s). Subsequent connections will be dropped.
[ Parent | Reply to this comment ]
> "I think this has been covered in Debian Administration before, but I couldn't find the article" It's the third link at the beginning of the article :)
[ Parent | Reply to this comment ]
* It does for a while, but after n days of continual use it stops working. See this thread here http://www.debian-administration.org/articles/187#comment_22
--
"It's Not Magic, It's Work"
Adam
[ Parent | Reply to this comment ]
> is to drop connections after a certain number of attempts within a certain
> amount of time (from a given IP address).
Then I send fake packets pretending to be you and you are locked out your own box.
[ Parent | Reply to this comment ]
There are plenty of reasons where this can be used. Linux = Freedom and can't that mean I am free to block anybody I want.
If I am in a business and I only do business in the U.S. what would be wrong with doing this. Worse thing happens is somebody is not able to see a service I provide from a country I cannot provide it for.
Now here is my word of warning. I was blocking very large IP blocks at one time when our SPAM filter could not keep up. While it worked, I also got the complaint when employee's had family or children (exchange students) in countries and their email would not go through.
Thanks again for the great article, I did not know this existed.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Isn't it a bad thing to leave the sources on a production web server? I'd like to use this, but I'm leary of recompiling the sources, leave the sources on the server, etc.
Is it safe to do on a prod box?
[ Parent | Reply to this comment ]
Which sources do you mean?
From the arcticle: "If you want, you can delete the ~/geoip/ and /usr/src/linux-source-<VERSION> directories now."
However if you're unexperienced with compiling software, I wouldn't recommand to try this tutorial out on a production machine the first time.
[ Parent | Reply to this comment ]
FATAL: Error inserting ipt_geoip (/lib/modules/2.6.9-55.ELsmp/kernel/net/ipv4/netfilter/ipt_geoip. ko): Invalid module format
[ Parent | Reply to this comment ]
make[1]: *** No rule to make target `net/ipv4/netfilter/ip_conntrack_standalone.s', needed by `net/ipv4/netfilter/ip_conntrack_standalone.o'. Stop.
make: *** [_module_net/ipv4/netfilter] Error 2
make: Leaving directory `/usr/src/kernels/2.6.11-1.1369_FC4-i686'
..I need help! I can't compile this module! I've got this error on two Fedora's yet.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Just instead of copying libipt_geoip.so to /lib/iptables/
i had to copy it to /usr/local/lib/iptables/
(Debian Etch 4.0)
Best regards,
k.
[ Parent | Reply to this comment ]
extensions/libipt_geoip_sh.o: In function `_init':
libipt_geoip.c:(.text+0x10): multiple definition of `_init'
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crti.o:(.init+0x0): first defined here
collect2: ld returned 1 exit status
RedHat Linux 5 box, im trying to figure out how to fix this... If anyone has any idea, pleease :)
[ Parent | Reply to this comment ]