Using fail2ban to secure ssh access

I found some notes from a collegue of my former company. Though I havent tested them by myself I have no reason to doubt that the steps described are working at all. The documentation was written in 2019.

The original request was:

  • block for 60 minutes after 3 failed ssh-logins
  • optional permablock after 3 temporary blocks within 24 hours

Copy&Paste follows

univention-install fail2ban

/etc/fail2ban/jail.local (please adjust the ignoreip line)

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

sed -i 's/ignoreip =\/8/ignoreip =\/8\/24' /etc/fail2ban/jail.local
sed -i 's/bantime  = 600/bantime  = 86400/' /etc/fail2ban/jail.local
sed -i 's/findtime  = 3600/findtime  = 3600/' /etc/fail2ban/jail.local
sed -i 's/maxretry = 5/maxretry = 3/' /etc/fail2ban/jail.local
sed -i 's/backend = auto/backend = systemd/' /etc/fail2ban/jail.local
sed -i '/^\[sshd\]/,/^:space:*$/ s/^:space:*$/enabled  = true/' /etc/fail2ban/jail.local

cat <<EOF >> /etc/fail2ban/jail.local

enabled  = true
backend  = auto
filter   = repeatoffender
action   = repeatoffender[name=repeatoffender]
logpath  = /var/log/fail2ban*
maxretry = 10
findtime = 31536000
bantime  = -1


sed -i 's/^\([^#]\)/#\1/g' /etc/logrotate.d/fail2ban

cat <<EOF >> /etc/logrotate.d/fail2ban
/var/log/fail2ban.log {
    rotate 13
    create 0600 root root
      /usr/bin/fail2ban-client set logtarget /var/log/fail2ban.log 2> /dev/null || true


cat <<EOF >> /etc/fail2ban/filter.d/repeatoffender.conf
_jailname = repeatoffender
failregex = fail2ban.actions\s+\[(?:.*)\]:\s+NOTICE\s+\[(?:.*)\]\s+Ban\s+<HOST>
ignoreregex = fail2ban.filter\s+\[(?:.*)\]:\s+WARNING\s+\[%(_jailname)s\]\s+Ban\s+<HOST>


cat <<\EOF >> /etc/fail2ban/action.d/repeatoffender.conf

before = iptables-common.conf


# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
actionstart = iptables -N fail2ban-<name>
              iptables -A fail2ban-<name> -j RETURN
              iptables -I <chain> -p <protocol> -j fail2ban-<name>
              # Establish chain and blocks for saved IPs
              iptables -N fail2ban-ip-blocklist
              iptables -A fail2ban-ip-blocklist -j RETURN
              iptables -I <chain> -p <protocol> -j fail2ban-ip-blocklist
              cat /etc/fail2ban/ip.blocklist.<name> |grep -v ^\s*#|awk '{print $1}' | while read IP; do iptables -I fail2ban-ip-blocklist 1 -s $IP -j REJECT --reject-with icmp-port-unreachable; done

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
actionstop = iptables -D <chain> -p <protocol> -j fail2ban-<name>
             iptables -F fail2ban-<name>
             iptables -X fail2ban-<name>
             # Remove chain and blocks for saved IPs to prevent duplicates on service restart
             iptables -D <chain> -p <protocol> -j fail2ban-ip-blocklist
             iptables -F fail2ban-ip-blocklist
             iptables -X fail2ban-ip-blocklist

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
actioncheck = iptables -n -L <chain> | grep -q 'fail2ban-<name>[ \t]'

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
actionban = VERIFY="<ip>*" 
            ADD="<ip>        # fail2ban/$( date '+%%Y-%%m-%%d %%T' ): Perma-Banned" 
            grep -q "$VERIFY" "$FILE" || iptables -I fail2ban-<name>  1 -s <ip> -j DROP
            grep -q "$VERIFY" "$FILE" || echo "$ADD" >> "$FILE" 

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
actionunban = # Do nothing because their IP is in the blocklist file

# To manually unban from the ip blocklist file run this command:
# Be warned that if the ip is in log rotated files it must be whitelisted
# sed -i '/^<ip>/d' /etc/fail2ban/ip.blocklist.repeatoffender


# Default 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

# Option:  chain
# Notes    specifies the iptables chain to which the fail2ban rules should be
#          added
# Values:  STRING  Default: INPUT
chain = INPUT

Regarding IPv6 support refer to (fail2ban 0.10 is available in Debian Buster and therefor with UCS 5)

hth and have fun