Spammers, brute force attacks, malicious packets… none of these things you want on your network if you can avoid it. Unfortunately a good portion of this comes from countries without the computer crime laws that the United States has implemented. Granted, the US’s laws aren’t the greatest in the world but it’s better than nothing.
I’m going to show you how to implement a little hack I found that will let you drop traffic from specific countries using their two-letter country code in iptables. It should in theory work on most Linux distros but more specifically I’ll be guiding you through doing this on CentOS.
The first two things you’re going to need to make this work: your current kernel’s source code, and the source for the version of iptables you’re using. No worries, we just need them to compile modules and we’re not actually going to update the kernel nor iptables.
Unfortunately I found that getting the source RPMs through the CentOS Yum repositories *sucks* so we’ll just get the tarballs for each of them. We’ll also have to get the GeoIP stuff.
1. Find out what kernel version you have
uname -r
2. Check and see if you’ve got your kernel source. In CentOS you can look under /usr/src/kernels/ and see if there’s a directory in there that matches what you saw in step 1. If not, check out the code block. For the sake of organization, all the downloads are gonna go under /root.
yum install kernel-devel
3. Go out and get the GeoIP tarball from the netfilter website.
wget http://people.netfilter.org/peejix/patchlets/geoip.tar.gz
4. Get your iptables source code downloaded. This example uses IPTables 1.3.5, so modify it according to whatever your version of iptables is using. If you’re not sure, just stick a -h at the end of your iptables command. Don’t worry about a minor version difference. As long as you’re on the same major release you should be alright.
wget http://www.netfilter.org/projects/iptables/files/iptables-1.3.5.tar.bz2
5. Go get patch-o-matic-ng from the Netfilter website too while we’re at it.
wget http://ftp.netfilter.org/pub/patch-o-matic-ng/snapshot/patch-o-matic-ng-20070414.tar.bz2
6. Let’s get all of this stuff extracted, organized, and ready to hopefully not break anything.
cd /root
mkdir geoip
And…. extract
cd /root
tar xjf iptables-1.3.5.tar.bz2
tar xjf patch-o-matic-ng-20070414.tar.bz2
tar xzf geoip.tar.gz -C patch-o-matic-ng-20070414/patchlets/
Now here’s where it can get a little hairy. I’m assuming you already have all the stuff you need to compile code. If you don’t, then Google it for your distro.
We’re going to use patch-o-matic-ng to patch the source code for the kernel and iptables. Don’t worry, it’s not going to modify your kernel and when you update it using Yum.
cd patch-o-matic-ng-20070414
./runme geoip
It’s going to ask you for the paths to your kernel source, and then your iptables source. Just give it the information of where we extracted the iptables source, and where our kernel source is located. The following has examples of how I accomplished it on my CentOS box:
Hey! KERNEL_DIR is not set.
Where is your kernel source directory? [/usr/src/linux] /usr/src/kernels/2.6.18-194.8.1.el5-i686
Hey! IPTABLES_DIR is not set.
Where is your iptables source code directory? [/usr/src/iptables] /root/iptables-1.3.5
It’ll go through a bunch of stuff, I’ll let you read it if you so desire but it’s just debugging information and an explanation of the geoip patch. It’ll come to a line that looks like this… hit y to apply the patch:
------------------------------------------
do you want to apply this patch [N/y/t/f/a/r/b/w/q/?] y
You can ignore the messages about recompiling the kernel and iptables. This is a lazy admin blog isn’t it?
However, we’ve got to build the module to install via modprobe, and then build the shared object for iptables. We’re gonna do a little trickery so it doesn’t recompile all the modules though.
cd /usr/src/kernels/2.6.18-194.8.1.el5-i686
make oldconfig
It’ll scroll a bunch of stuff you probably won’t find important, then it’ll come to this line, to which you’ll want to answer “m”:
geoip match support (IP_NF_MATCH_GEOIP) [N/m/?] (NEW)
Now we’re going to modify the makefile for the netfilter modules. Make a backup of the Makefile in /usr/src/kernels/2.6.18-194.8.1.el5-i686/net/ipv4/netfilter because we might want it someday. Then use vi to create a new makefile and paste the following into it…
obj-m = ipt_geoip.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
Now it’s building time…
cd /usr/src/kernels/2.6.18-194.8.1.el5-i686
make -C $(pwd) M=net/ipv4/netfilter modules
Unless something was broken or otherwise went horribly wrong, you should now have the file ipt_geoip.ko sitting in /usr/src/kernels/2.6.18-194.8.1.el5-i686/net/ipv4/netfilter/ and we want to copy it to where all your other libraries are:
cp /usr/src/kernels/2.6.18-194.8.1.el5-i686/net/ipv4/netfilter/ipt_geoip.ko /lib/modules/2.6.18-194.8.1.el5-i686/kernel/net/ipv4/netfilter/
Now… to build the shared library for it…
cd /root/iptables-1.3.5
make KERNEL_DIR=/usr/src/kernels/2.6.18-194.8.1.el5-i686/ extensions/libipt_geoip.so
Again, if everything was happy and it didn’t blow up… you should have a file called libipt_geoip.so sitting in /root/iptables-1.3.5/extensions/
so copy it to where iptables is going to be looking for it.
cp extensions/libipt_geoip.so /lib/iptables/
Now all we have to do is modprobe the module into kernelspace and then we’re ready to use it.
depmod
modprobe ipt_geoip
Lastly, we have to have a working database file for the iptables country lookups, so off we go to do two more downloads…
cd /root
wget http://www.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
unzip GeoIPCountryCSV.zip
Now we need a utility to convert this wonderfully huge text file into a binary file:
wget http://people.netfilter.org/peejix/geoip/tools/csv2bin-20041103.tar.gz
tar xzf csv2bin-20041103.tar.gz
cd csv2bin/
make
./csv2bin ../GeoIPCountryWhois.csv
Now to put things where they need to be…
mkdir /var/geoip
mv geoipdb.* /var/geoip/
If everything worked up til now, you just need to write iptables rules using the GeoIP module… here’s an example:
/sbin/iptables -A INPUT -m geoip --src-cc CN -j DROP
Have fun!
Recent Comments