Blazing Fast Block Many IPs With Fail2Ban and IP Sets
I am a big fan of the software Fail2Ban to ban hackers, script-kiddies and spambots from my server. If you don’t know the software, it works like this on a SSH server:
Fail2Ban monitors the log file of the SSH server, someone tries to log in and enters the wrong password. If Fail2Ban registers this, it evaluates as “Fail”. If someone creates e.g. 4 Fails in a row, an iptables rule is automatically created which blocks the access of the attacker’s IP to port 22 (SSH) for a certain time (temporary ban).
For the more adventurous attackers I have set Fail2Ban to evaluate its own logs. If someone manages to get a temporary ban three times a day, this IP will be blocked for a whole week from all ports.
Now there are a lot of automated scripts on the Internet, which are constantly hitting my server. This means that in one week I have accumulated a lot of IPs in my iptables, about 3000 – 5000 entries. iptables is already very fast, but these entries are still processed in a loop for every IP packet that hits my server.
Among other things, IP sets was developed for those cases where you want to filter many IPs or IP ranges with iptables. It lives like iptables in the kernel, works together with iptables and is very fast thanks to hash sets.
Unfortunately Fail2Ban does not have the possibility to use IP sets out of the box, but it is extremely extensible. So here is a tutorial how I taught Fail2Ban to manage its blocklists with ipsets. Fail2Ban is really very customizable, one of the main reasons why I am so enthusiastic about this software. It was enough to create a tiny and manageable file to teach Fail2Ban what I wanted.
Now for the tutorial:
First you need the ipset tool, but if you have iptables installed chances are good you allready have it installed. Just try to run the following command:
ipsets -v
Create the following file /etc/fail2ban/action.d/ipsets.conf
or download it from my gist at github (see bottom of the page):
# IP Sets configuration file
# Author: David Ewelt
# ipset.conf
# Uses IP Sets (https://ipset.netfilter.org/) to speed up iptables processing
# this action can used as a replacement for the iptables action
[Definition]
actionflush = iptables -F f2b-ip4set-<name>
ip6tables -F f2b-ip6set-<name>
# at the start of fail2ban create the ipset's and iptables rules to drop packets matching this sets
actionstart = ipset create f2b-ip4set-<name> hash:ip
ipset create f2b-ip6set-<name> hash:ip family inet6
iptables -I INPUT -p <protocol> --dport <port> -m set --match-set f2b-ip4set-<name> src -j REJECT --reject-with icmp-port-unreachable
ip6tables -I INPUT -p <protocol> --dport <port> -m set --match-set f2b-ip6set-<name> src -j REJECT --reject-with icmp6-port-unreachable
# at the end of fail2ban remove the rule from iptables and delete the ipset
actionstop = iptables -D INPUT -p tcp --dport <port> -m set --match-set f2b-ip4set-<name> src -j REJECT --reject-with icmp-port-unreachable
ip6tables -D INPUT -p tcp --dport <port> -m set --match-set f2b-ip6set-<name> src -j REJECT --reject-with icmp6-port-unreachable
ipset destroy f2b-ip4set-<name>
ipset destroy f2b-ip6set-<name>
# check if the iptables rules exists
actioncheck = (iptables -n -L INPUT | grep 'match-set f2b-ip4set-<name>') && (ip6tables -n -L INPUT | grep 'match-set f2b-ip6set-<name>')
# add the ip to the ipset
actionban = ipset add <ipset_name> <ip>
# remove the ip from the ip set
actionunban = ipset del <ipset_name> <ip>
[Init]
name = default
port = ssh
protocol = tcp
ipset_name = f2b-ip4set-<name>
[Init?family=inet6]
ipset_name = f2b-ip6set-<name>
Like the iptables version this action can only ban IPs for specific ports, so i have also written allports version, which I dont include here. You can find it down below where the downloads are.
Now you just have to change the action in your jails from iptables to ipsets, your config could look like this:
[sshd]
enabled = true
action = ipsets
To change the port you can give the action an argument like so:
action = ipsets[port=80]
Downloads / Links:
I hope you find it usefull, let me know if you have problems following this tutorial.