Fail2ban persistent banning

May 18th, 2021 by Philip Iezzi 3 min read
cover image

If you are using Fail2ban, there is no standard recommended way to persistently ban IPs. Some people recommend to do this outside of Fail2ban, using e.g. iptables-persistent, which is actually super easy to install and configure. But let's say, we don't want to install any extras and want to accomplish the same with Fail2ban, as we already have fail2ban on every single host (which is a must!).

Google for "fail2ban ban ip persistently" lead me to the following interesting solutions:

But this did not work out for me. The thing is, if we extend actionstart in action.d/iptables-multiport.conf (or iptables-multiport.local override) as recommended in above tutorials, that is not going to add any IPs on a Fail2ban restart, but only once the first IP gets added to any jail.

So these are my two proposed solutions:

Using recidive jail (ban for 1 week)

The provided recidive jail/filter monitors the fail2ban log file, and enables you to add long time bans for ip addresses that get banned by fail2ban multiple times. Default configuration looks like this:

jail.conf
[recidive]
logpath  = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime  = 1w
findtime = 1d

Simply enable this jail, e.g. in jail.d/custom.conf:

jail.d/custom.conf
[recidive]
enabled = true

We could then ban an IP manually for a whole week by adding it to that jail:

$ fail2ban-client set recidive banip 11.22.33.44

verify:

$ iptables -S f2b-recidive
-N f2b-recidive
-A f2b-recidive -s 11.22.33.44/32 -j REJECT --reject-with icmp-port-unreachable
-A f2b-recidive -j RETURN

Using manual jail (ban forever)

Let's configured a custom manual jail for manual banning:

filter.d/manual.conf
[Definition]
failregex = 
ignoreregex = 
jail.d/custom.conf
[manual]
banaction = %(banaction_allports)s
bantime = -1
enabled = true

Every jail needs a filter. But as we don't need that jail to parse any logfile, we have simply set up a dummy filter definition.

We could ban an IP manually forever by adding it to that jail:

$ fail2ban-client set manual banip 11.22.33.44

And remember the following command if you wish to ever unban that IP:

$ fail2ban-client set manual unbanip 11.22.33.44

Loading a whole blocklist could be done like this:

$ grep -v '^#' ip.blocklist | while read IP; do fail2ban-client set manual banip $IP; done

You could then add this to some blocklist loading script, and triggering it e.g. by using ExecStartPost in a Systemd unit file override. But actually, that should not be needed, as Fail2ban persists its state and keeps banned IPs after a Fail2ban restart or even after a full system reboot.