Ipset block for China


Some time ago I wrote an article (Blacklist met iptables) explaining how to use ipset and iptables to make a blacklist. This became a topic again because my girlfriend (the one having the site HappyMinds) got frustrated more and more by all those people from Russia and China ruining her stats. And I have to admit: what are they doing on a site with limited content in English, most of it is in Dutch. So the idea is to extend the blacklist with an ipset block for China (as an example).

In addition to that I switched (back) to using Ubuntu as a server platform. A good opportunity to look at the differences with CenOS.

chinese hackerThe idea

In the previous article I described how you can make an ipset table from a list of IP numbers and use that list in an iptables firewall. Obvious benefit being that by using ipset you don’t have to make a firewall rule per IP number, which greatly enhances the firewall performance.
That doesn’t cut it for blocking a country/region. It would be better to block the subnets in use by that country. The people at IpDeny have been so friendly as to compile such a list and publish it. This list (or lists actually) can be downloaded, just as the IP numbers in the previous example, and put into an ipset table.

ipsetThe implementation

The script to download the list of subnets and compile it into an ipset table resembles the script from the previous article. There are some minor differences. I named the script make_zone_blacklist, if you use it and give it another name than don’t forget to change the name in you firewall script as well. The country coded being used can be looked up at the Ipdeny site.

#! /bin/bash

# make_zone_blacklist
# load the zone blacklist for an iptables based firewall
# Written by Peter Kaagman <prjv.kaagman@gmail.com>;
# version 1.0.0 20150718

# Set the path so you know which executable you run
# being paranoid?
# The base url for the list at ipdeny
# The zones we are going to deny access
zones="cn ru"

function load_blacklist {
  # Load the blacklist in a copy list
  ipset destroy zone_blacklist2 >& /dev/null # destroy is if needed
  ipset create zone_blacklist2 hash:net # (re)create it
  # Iterate the zones
  for zone in $zones
    # Download the new list
    # and itterate it
    for CIDR in `wget -q $url/$zone.zone -O -|grep -v ^#`; do
      # add the ip to the newly created blacklist2
      ipset add zone_blacklist2 $CIDR
  # Swap this list with the excisting one
  # The list blacklist should be created by you iptables script
  ipset swap zone_blacklist zone_blacklist2
  # Remove zone_blacklist2
  ipset destroy zone_blacklist2

#echo Creating blacklist

As the the other example this script also assumes that the ipset table (zone_blacklist) excists. It has to be created before hand. My firewall example takes care of that.

There are some minor differences with script creating the IP blacklist:

  • The type of the ipset table is different to make it able to contain subnets instead of IP numbers.
  • The source of the download differs
  • The script is able to download several country codes

iptablesThe firewall script

The firewall script needs to be adapted to accommodate the new ipset table:

Add a variable for loading the table

int_if=eth0			# internal (local) interface, e.g. eth0
int_ip=		# internal (local) IP, e.g.

I use these kind of variables quite often. Whenever I move the script around I only have to change this one reference in the firewall script. When using this script you will have to adapt it to your needs off course.

Creating the ipset table and the filter rules.

# default policy
$iptables -P INPUT   DROP
$iptables -P FORWARD DROP
$iptables -P OUTPUT  DROP

# drop zone_blacklist
# first create the ipset zone_blacklist
# make_zone_blacklist assumes it excists
$ipset create zone_blacklist hash:net >& /dev/null
# no network at the moment,
# so we load the list later on

# log on match
$iptables -A INPUT -m set --match-set zone_blacklist src -p TCP -j LOG --log-prefix 'Zone_BlackListed '
# and drop on match
$iptables -A INPUT -m set --match-set zone_blacklist src -p TCP -j DROP

# drop blacklist
# first create the ipset blacklist
# make_blacklist assumes it excists
$ipset create blacklist hash:ip >& /dev/null
# no network at the moment,
# so we load the list later on

# log on match
$iptables -A INPUT -m set --match-set blacklist src -p TCP -j LOG --log-prefix 'BlackListed '
# and drop on match
$iptables -A INPUT -m set --match-set blacklist src -p TCP -j DROP

# drop broadcast (do not log)

I’ve chosen to first drop the zone_blacklist entries. This because I think this list is going to be hit a lot sooner than the blacklist. Following the “drop ASAP” paradigm.

Loading the ipset table.

# log all the rest before dropping
$iptables -A INPUT   -j LOG --log-prefix "IN "
$iptables -A INPUT   -j REJECT --reject-with icmp-port-unreachable
$iptables -A OUTPUT  -j LOG --log-prefix "OU "
$iptables -A OUTPUT  -j REJECT --reject-with icmp-port-unreachable
$iptables -A FORWARD -j LOG --log-prefix "FW "
$iptables -A FORWARD -j REJECT --reject-with icmp-port-unreachable

# firewall loaded, so lets load the blacklists
echo "Loading blacklist"
echo "Loading zone_blacklist"

I load the ipset tables just after the logging block. At this point all the network connection I want will be restored.

ubuntu bootingHow to survive a reboot

In the previous article I explained how you can survive a reboot on a CentOS system. In essence that meant executing some code whenever an interface comes on line. Ubuntu has a similar option but (IMHO) a bit simpler though. Ubuntu has an directory (/etc/network/ip-up.d) in which you can place a script, there are all ready some present. I’ve placed a script with the following content in that directory and made it executable:

#! /bin/bash

/home/pkn/scripts/bash/firewall/firewall.sh start

To periodically refresh the blacklist you can place the same script in /etc/cron.daily. That way the firewall is refreshed on a daily basis. You could use to only run the blacklist scripts, in that case the firewall stays loaded.

reflectieSo now are we don?

Well… I don’t know a lot…. but I do know this: you’re never completely done. With this kind of filtering you are always one step behind on the reality. So… no.. we are not done :D.
Spamhaus has 2 list which look promising: drop and edrop. Perhaps I’ll incorporate those. Analysing the log files to identify abusers seems promising to. But first I’m going to do some stats with Tobi Oetikers library. I’m kind of a stats junkie :D.

Een gedachte over “Ipset block for China”

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *