What is Fail2ban?

Fail2ban is a daemon that runs as a systemd service and monitors log files in real time. When it sees a configured failure pattern repeat too many times within a set time window, it adds a firewall rule that blocks that IP for a defined period, then removes the rule automatically.

By default it uses iptables or ufw to set bans. Each monitored service is its own "jail" with individual thresholds for failure count and ban duration.

Fail2ban does not catch distributed attacks from thousands of IPs with one attempt per IP. Key-based SSH login handles that threat. Fail2ban filters the routine scanner noise.

Prerequisites

  • Raspberry Pi or a server running Debian, Ubuntu or Pi OS
  • SSH access with sudo privileges
  • UFW installed and active (recommended; iptables works too)
  • SSH hardening already in place — see the SSH hardening guide if you haven't done that yet

Install

Update the package list and install Fail2ban:

sudo apt update && sudo apt install fail2ban -y

Fail2ban starts automatically as a systemd service after installation. Confirm it is running:

sudo systemctl status fail2ban

You should see active (running) in the output.

Never edit jail.conf

The file /etc/fail2ban/jail.conf gets overwritten on every package update. Changes you make there disappear the next time Fail2ban updates. All configuration goes in /etc/fail2ban/jail.local, which takes precedence over jail.conf.

If jail.local does not exist on your system, create it. That is the only file you need to edit.

SSH jail

Create or edit /etc/fail2ban/jail.local:

sudo nano /etc/fail2ban/jail.local

Paste in:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
banaction = ufw

[sshd]
enabled  = true
port     = ssh
logpath  = %(sshd_log)s
backend  = %(sshd_backend)s
maxretry = 3
šŸ“Œ If you moved SSH off port 22 (for example to 2222), set port = 2222 instead of port = ssh. Fail2ban resolves the service name to port 22 via the system services file, so it will monitor the wrong port if you leave it as ssh after changing it.

Save the file and restart Fail2ban:

sudo systemctl restart fail2ban && sudo systemctl enable fail2ban

Check status

List all active jails:

sudo fail2ban-client status

Check the SSH jail specifically, including currently banned IPs:

sudo fail2ban-client status sshd

The output shows total failure count, current bans, and the list of banned addresses.

Traefik and Nginx jail

If you run Traefik or Nginx, add a jail for their access logs. For Traefik, append to /etc/fail2ban/jail.local:

[traefik-auth]
enabled  = true
port     = http,https
filter   = traefik-auth
logpath  = /var/log/traefik/access.log
maxretry = 5

Fail2ban needs a filter to know what to look for in the Traefik log. Create the filter file:

sudo nano /etc/fail2ban/filter.d/traefik-auth.conf

Paste in:

[Definition]
failregex = ^<HOST> \S+ \S+ \[.*\] "\S+ \S+ \S+" 401 .*$
ignoreregex =

This matches 401 responses from Traefik, which signal failed authentication attempts. Verify the filter against your log before restarting:

sudo fail2ban-regex /var/log/traefik/access.log /etc/fail2ban/filter.d/traefik-auth.conf

Restart Fail2ban to load the new jail:

sudo systemctl restart fail2ban

Unban an IP and whitelist your own network

To lift a ban manually:

sudo fail2ban-client set sshd unbanip 1.2.3.4

Add ignoreip to the [DEFAULT] section so Fail2ban never bans your own machines:

[DEFAULT]
bantime    = 1h
findtime   = 10m
maxretry   = 5
banaction  = ufw
ignoreip   = 127.0.0.1/8 192.168.1.0/24
āš ļø Adjust the subnet to match your own network. If your LAN is 192.168.0.x, use 192.168.0.0/24. If it is 10.0.0.x, use 10.0.0.0/24.

Test it

From a different machine on your network, attempt SSH with the wrong password three times:

ssh wronguser@your-pi-ip
# Enter the wrong password three times

Then confirm the IP was banned:

sudo fail2ban-client status sshd

The IP should appear under "Banned IP list". Remove it afterwards:

sudo fail2ban-client set sshd unbanip YOUR_TEST_IP

Troubleshooting

Fail2ban's own log file:

sudo tail -f /var/log/fail2ban.log

The systemd journal for service-level errors:

sudo journalctl -u fail2ban -f

Common issues:

Frequently asked questions

Does Fail2ban protect against all brute-force attacks?

No. Fail2ban catches attacks from a single IP. Distributed attacks from many IPs with a low attempt count per IP slip through undetected. Key-based SSH login eliminates the problem entirely. An attacker without your private key can try for years without getting in.

Do bans survive a reboot?

Not by default. Fail2ban does not persist bans across restarts. To keep bans after reboot, enable the dbfile option in jail.local, but in practice it is rarely needed since bots retry and get caught again quickly.

Can Fail2ban ban me from my own server?

Yes, if you mistype your password or key passphrase too many times. Use ignoreip in [DEFAULT] to whitelist your home IP or LAN subnet: ignoreip = 127.0.0.1/8 192.168.1.0/24.

Sources