Posted

Fail2ban is a great tool for detecting unwanted internet connections and doing something about them. It works by allowing you to specify RegExes that specify bad behavior and actions that can be any command to deal with them. Unfortunately, it forgets bans across resets. So I created a custom action to deal with this.

In my action, when an address is banned, it isn't just placed into iptables, it's also recorded in a file that's read during the action startup. In addition, an at job is created to undo the ban in case fail2ban is restarted. Unbanning involves undoing all of the ban actions, including removing the now useless at job. Here's the code:

cdombroski@aether:/etc/fail2ban/action.d$ cat iptables-permaban.conf
[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = iptables -N fail2ban-permaban-<name>
              iptables -A fail2ban-permaban-<name> -p tcp -j TARPIT
              iptables -A fail2ban-permaban-<name> -j DROP
              iptables -N fail2ban-permabans-<name>
              iptables -A fail2ban-permabans-<name> -j RETURN
              iptables -A INPUT -j fail2ban-permabans-<name>
              for host in $(cat /etc/fail2ban/permabans);do iptables -I fail2ban-permabans-<name> 1 -s $host -j fail2ban-permaban-<name>;done

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop = iptables -D INPUT -j fail2ban-permabans-<name>
             iptables -F fail2ban-permabans-<name>
             iptables -X fail2ban-permabans-<name>
             iptables -F fail2ban-permaban-<name>
             iptables -X fail2ban-permaban-<name>

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck = iptables -n -L INPUT | grep -q fail2ban-permabans-<name>

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    <ip>  IP address
#          <failures>  number of failures
#          <time>  unix timestamp of the ban time
# Values:  CMD
#
actionban = echo <ip> >> /etc/fail2ban/permabans
            atq=$(echo "sed -e '/<ip>/d' -i /etc/fail2ban/permabans; iptables -D fail2ban-permabans-<name> -s <ip> -j fail2ban-permaban-<name>" | at now + 1 month  2>&1 |grep job|cut -d' ' -f 2); iptables -I fail2ban-permabans-<name> 1 -s <ip> -j fail2ban-permaban-<name> -m comment --comment $atq

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    <ip>  IP address
#          <failures>  number of failures
#          <time>  unix timestamp of the ban time
# Values:  CMD
#
actionunban = sed -e '/<ip>/d' -i /etc/fail2ban/permabans
              atq=$(iptables -nL fail2ban-permabans-<name>|grep <ip>|sed -e 's@.*/\*@@' -e 's@\*/.*@@');atrm $atq;iptables -D fail2ban-permabans-<name> -s <ip> -j fail2ban-permaban-<name> -m comment --comment $atq

[Init]

# Defaut name of the chain
#
name = default

# Option:  protocol
# Notes.:  internally used by config reader for interpolations.
# Values:  [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp