Fail2Ban: Permanent SSH Bans

Fail2ban is a Python script that scans your security logs for brute force attack signatures and creates iptable rules to ignore traffic from those IPs. It’s very handy for securing SSH.

It has the option to permanently ban IPs, but it gets its list of bad IPs from /var/log/secure. Once those logs are rotated and the fail2ban process gets restarted you’ll no longer be blocking them. So I tweaked it to save all the blocked IPs to a file so you can always blacklist them.

All the changes were in /etc/fail2ban/actions.d/iptables.conf. The first addition loads the list of saved IPs to blacklist (/etc/fail2ban/ip.deny) when the process is first started (the addition is in bold).

actionstart = iptables -N fail2ban-<name>
iptables -A fail2ban-<name> -j RETURN
iptables -I INPUT -p <protocol> –dport <port> -j fail2ban-<name>
for IP in `cat /etc/fail2ban/ip.deny`; do iptables -I fail2ban-SSH 1 -s $IP -j DROP;done

Then under actionban we want to check the list of IP’s that we explicitly allow (/etc/fail2ban/ip.allow), if it’s not in that list, ban it and add it to ip.deny:

actionban =  if [ -z `awk ‘$1 == “<ip>” { print “true” }’ /etc/fail2ban/ip.allow` ]; then iptables -I fail2ban-<name> 1 -s <ip> -j DROP;fi
if [ -z `awk ‘$1 == “<ip>” { print “true” }’ /etc/fail2ban/ip.deny` ] && [ -z `awk ‘$1 == “<ip>” { print “true” }’ /etc/fail2ban/ip.allow` ]; then echo “<ip>” >> /etc/fail2ban/ip.deny;fi

This next change is optional since the unban functionality hasn’t been added to fail2ban yet:

actionunban = if [ -z `awk ‘$1 == “<ip>” { print “true” }’ /etc/fail2ban/ip.deny` ]; then iptables -D fail2ban-<name> -s <ip> -j DROP;fi
if [ -z `awk ‘$1 == “<ip>” { print “true” }’ /etc/fail2ban/ip.deny` ] && [ -z `awk ‘$1 == “<ip>” { print “true” }’ /etc/fail2ban/ip.allow` ]; then echo “<ip>” >> /etc/fail2ban/ip.allow;fi

You can always ignore IPs by adding them to the ip.allow file, but I’d recommend using the jail.conf “ignoreip” variable until the unban functionality is finalized (probably in ver 0.9).

About this entry