Fail2Ban is a service that watches the log files of your services, such as SSH, HTTP, and FTP, looking for consecutive authentication failures that may indicate an unauthorized login attempt.

When it detects a possible intruder that fails to log in X times within Y period of time, it bans the origin IP address for Z time by creating a firewall rule, which is automatically removed after the ban expires.

sudo apt update
sudo apt install fail2ban
sudo systemctl status fail2ban

You should see the service as active (running).

sudo cp /etc/fail2ban/jail.{conf,local}
sudo nano /etc/fail2ban/jail.local

Set up your whitelist by uncommenting the line below and filling it with trusted IP addresses. Typically, this includes the loopback interfaces (127.0.0.1/8 and ::1), and if you access your network remotely via VPN, also include the VPN subnet (e.g., 10.8.0.0/24).

ignoreip = 127.0.0.1/8 ::1 10.8.0.0/24

Before saving the file, define X, Y, and Z:

bantime = 1d
findtime = 60m
maxretry = 5
backend = systemd

In this example, if someone fails 5 times within 60 minutes, they will be banned for 1 day. Also change the backend to “systemd”, since the default value “auto” may not catch any events.

To configure e-mail alert notifications when someone is banned (requires an SMTP server):

destemail = [email protected]
sender = [email protected]
action = %(action_mw)s

Scroll down to find the services you want to protect. Only enable the ones you actually need.

[sshd]
enabled = true
#mode = normal
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Add enabled = true to each jail you want to activate.

In the example above, I enabled it for SSH. I would do the same for HTTP, FTP, and any other service exposed to the internet that requires authentication.

Note the commented line in the example above. You can uncomment mode = normal and switch to a more aggressive approach, such as DDoS, extra, or aggressive. See “filter.d/sshd.conf” for usage examples and details.

Save the configuration file, restart the service, and verify it is running without errors:

sudo systemctl restart fail2ban
sudo systemctl status fail2ban

Fail2Ban includes a CLI tool called fail2ban-client for interacting with the service. Usage examples:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 1.1.1.1
sudo fail2ban-client set sshd banip 1.1.1.1
sudo fail2ban-client -h

Right after setting up the service, I received 46 e-mails about banned IPs trying to log in to my SSHD as root (last digits omitted):

Total failed: 1106
Total banned: 38
Banned IP list: 93.39.184.1X 95.78.251.11X 208.109.11.3X 167.71.237.7X 162.243.130.8X 82.65.23.6X 100.26.163.9X (...)

Looking up the origin of those IP addresses, they come from all over: USA, CH, IND, SG, RU, IT, FR, UK, GER, VN, NL, HK, etc. Most of them belong to OVH SAS and DigitalOcean.

Due to the high volume of bans, I ended up disabling e-mail notifications (more than 10 per hour).

A week after setting up Fail2Ban, the number of daily bans on my SSH dropped from 200 to 4. My guess is that once attackers get banned, many stop trying. For the same reason, I also plan to disable ping responses to avoid advertising that the server is live.

To get the status of all jails at once (this is a single long command):

fail2ban-client status | sed -n 's/,//g;s/.*Jail list://p' | xargs -n1 fail2ban-client status

BONUS

Did you know you can use Fail2Ban to protect your WordPress website as well? See more in WordPress Configuration Tips and Tricks [Link].

As an alternative, the open source SSHGuard aims to accomplish the same goal [Link].

sudo apt update && sudo apt install sshguard -y
echo '192.168.1.0/24' >> /etc/sshguard/whitelist
sudo nano /etc/sshguard/sshguard.conf

Configure accordingly.

# For IPTABLES
BACKEND="/usr/lib/sshguard/sshg-fw-iptables"
# For NFTABLES
#BACKEND="/usr/lib/sshguard/sshg-fw-nft-sets"
WHITELIST_FILE="/etc/sshguard/whitelist"
BLOCK_TIME=1200
DETECTION_TIME=1800
THRESHOLD=30

Start the service and monitor the logs.

sudo systemctl enable sshguard --now
sudo journalctl -u sshguard -f

List banned IPs and unban by line number.

sudo iptables --list sshguard --line-numbers --numeric
sudo iptables --delete sshguard <line-number>