, 2 min read
Blocking IP addresses with ipset
Original post is here eklausmeier.goip.de/blog/2020/07-14-blocking-ip-addresses-with-ipset.
In Chinese Hackers I mentioned that I block ssh attackers with the help of fail2ban. Unfortunately, fail2ban uses iptables
to create firewall rules in "Chain f2b-SSH
" for each individual IP address. For a modern processor this is no problem, even if you have thousands of these rules. While for a low powered ARM processer this can have a noticeable influence on network performance. In Using Odroid as IP Router I wrote:
Added 10-Jan-2019: I previously added ca. 3000 iptables rules for blocking IP address ranges which attacked me on port 22 (ssh). That many rules will deteriorate your network performance significantly. My download speed went down from 100 MBit/s to 20 MBit/s.
An alternate or additional approach to this slowdown due to iptables
is to use ipset
, Arch package ipset. This ipset
maintains hash tables of IP addresses or networks. At the time when I still used the Odroid, then the main sshd-server copied the blocked IP addresses to the Odroid, which in turn populated the hash table with the IP addresses to be blocked.
Setting up ipset
and populating the hash tables from fail2ban can be done as below.
sqlite3 -csv /var/lib/fail2ban/fail2ban.sqlite3 "select distinct ip from bips order by ip" | \
perl -e 'BEGIN {print "create reisTmp hash:ip family inet hashsize 65536 maxelem 65536\n"; }
print "add reisTmp $_" while (<>);' \
> ~/tmp/reisTmp
The name reisTmp
is arbitrary. This way we have a file which looks like this:
create reisTmp hash:ip family inet hashsize 65536 maxelem 65536
add reisTmp 1.186.57.150
add reisTmp 1.193.76.18
add reisTmp 1.2.206.30
add reisTmp 1.202.77.210
add reisTmp 1.214.156.164
add reisTmp 1.214.245.27
. . .
This file is transfered from the sshd/fail2ban-server to our router, if required, and is the input to be run through ipset
:
ipset restore -f ~klm/tmp/reisTmp
ipset swap reisTmp reisbauer
ipset destroy reisTmp
This assumes you have created a hash table in ipset called reisbauer
. Again, this name is arbitrary. Above scenario assumes that populating this hash table takes some time, then just swap hash tables, which is almost instant.
To re-initiate the hash table after reboot, you use
systemctl enable ipset
systemctl start ipset
This basically does
ipset -f /etc/ipset.conf restore
To activate your set for blocking you must tell iptables to check elements in your ipset:
iptables -t raw -A PREROUTING -i eth0 -p tcp -m tcp --dport 22 -m set --match-set reisbauer src -j DROP