Blocking an entire country with iptables and ipset

The iptables firewall works great for blocking pesky single IPs, or ranges of IPs – but what if you want to do more than that, like blocking an entire country? Even if you’re blocking large ranges with iptables it’ll still take a while to run through them all, and you may well miss a few here and there. This is where ipset comes in handy.

You can technically block any country, but I’ll use China as an example here.

To begin with, we need to create an ipset – essentially a glob of IPs and IP ranges in a single combined group:

ipset create china hash:net

We then pull the IPs into our set. I’m using the blocks listed at ipdeny, but any similar source should do the job:

wget -O /tmp/cn.zone http://www.ipdeny.com/ipblocks/data/countries/cn.zone
for i in `cat /tmp/cn.zone`; do ipset add china $i; done

We then add this ipset to iptables, dropping any TCP traffic that uses an IP from the set:

iptables -I INPUT -p tcp -m set --match-set china src -j DROP

If you’re using iptables-persistent, you’ll need to add a similar rule to /etc/rules.v4 and /etc/rules.v6 (or equivalents on non-Debian/Ubuntu).

This is by no means as sophisticated as a real hardware firewall with intelligent traffic filtering, but it does a fairly good job for aggressive search bots or crawlers.

Leave a Reply

Your email address will not be published. Required fields are marked *