[Michael T. Babcock] iptables blocklist creation

I was looking at the various tools for implementing IP subnet block lists on Linux for my firewall and didn't like any of the solutions available. One operates as a user space daemon that filters packets, another does various complex things and makes assumptions that aren't true for me. I tried the simplistic linblock.pl and although it did almost exactly what I wanted, it took over 6 hours to import and sort a full IP range list on my 500MHz PIII firewall box.

I decided to do the good Linux thing and reinvent the wheel. The result is my set of scripts/software below, released under the GPLv2 or later. The shell script is what I use to download and implement the iptables list generated by the second piece of code, a Python program I whipped up this morning which, taking its cue from linblock above, sorts a block list into network prefix size order and then outputs an iptables-restore format list for easy transactional importing into my firewall.


First off, I don't maintain any IP block lists for public consumption, nor can I recommend any, but I personally am using (as of when this was written) the list shown in the script below as it works with my software. If you want to use something different, the parsing should be straightforward. The one that I've written this program around is the splist.zip file distributed by http://bluetack.co.uk.


Create an empty chain in your iptables firewall named BadRanges (or edit the code to use another name if you prefer) and add an appropriate reference in your INPUT and/or FORWARD chains. If you're using this on a single host that doesn't act as a router, you'll not need an entry in FORWARD. Here's what I'm using:

iptables -N BadRanges
iptables -I INPUT -i eth0 -m state --state NEW,RELATED -j BadRanges
iptables -I FORWARD -i eth0 -m state --state NEW,RELATED -j BadRanges

The above assumes your external network adapter is called eth0. All new incoming connections, or packets related to existing connections will be checked against the BadRanges list. This will not filter outbound packets, and as such shouldn't prevent you from, for example, using a website hosted by an IP range that you don't want connecting back to you.

Now that our entries exist as above, save your iptables (which is iptables-save > /etc/sysconfig/iptables on Fedora at least) so it loads like this by default. As of the above, nothing is effectively different in how your firewall behaves. Now copy iptables-blocklist.py to /usr/local/libexec which parses the list into iptables-restore format and install zzz-badrangeupdate in your /etc/cron.daily or /etc/cron.weekly to regularly update and install the list.

The code

The basic program is written in Python. You will also need to download and install IPy, a fast IP class I use for creating subnet blocks from the list entries and for sorting them by network prefix length.


I've made a much smaller and simpler version using just the shell and sed for people with iptables and the "iprange" module who don't believe the sorting makes any difference. I haven't tested it as thoroughly, but it ought to work in all reasonable circumstances with no need for Python to be installed. See the shell script at the end of the download list.


The cron script downloads a zipped list of IP ranges to be blocked if it has changed since the last execution using wget. The list is then unzipped and a diff between the previous and current list is created simply for reference to see what has changed (although I could eventually parse this instead and reduce the amount of processing time required). The unzipped text list of IP ranges is then parsed by the iptables-blocklist.py program into a list of approximated subnets (some ranges given are not on exact subnet boundaries; IPy makes an encompassing subnet declaration that may block more or less IPs than you intend). This list is sorted into network prefix length order, shortest first, on the assumption that it will make for faster or easier matching, which may or may not be true. After this the sorted list is output in iptables-restore format, and piped through iptables-restore with the -n flag, effectively replacing the one BadRanges chain with a new one atomically.

Stumble it! XFN Friendly Powered by DJBDNS Powered by Zope Valid CSS! Website Security Test

Served by:  Zope 2.7.6

Page Copyright © 2014, Michael T. Babcock. All Rights Reserved.

To contact me, send an E-mail to sawyoursite at this domain.

If you'd really like your mail server reported for spam, send me some junk mail to junk-yum@mikebabcock.me or devnull@mikebabcock.me. This site powered by djbdns