Check your auth log on any server that's been public for more than a day:

sudo grep "Failed password" /var/log/auth.log | wc -l

Thousands, probably. Bots hammer SSH 24/7 — they're not targeted at you specifically, they scan the entire IPv4 space continuously. fail2ban watches the logs and bans IPs that fail too many times.

It won't stop a sophisticated targeted attack, but it kills the automated noise and keeps your logs readable.

Install

sudo apt update
sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Don't edit jail.conf

/etc/fail2ban/jail.conf gets overwritten on updates. All your config goes in /etc/fail2ban/jail.local — which takes precedence and survives upgrades.

sudo nano /etc/fail2ban/jail.local

My jail.local

[DEFAULT]
# Ban IPs for 1 hour
bantime  = 3600
# Time window to count failures
findtime = 600
# Number of failures before ban
maxretry = 5
# Your own IPs - never ban these
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled  = true
port     = ssh
logpath  = %(sshd_log)s
backend  = %(syslog_backend)s
maxretry = 3

[nginx-http-auth]
enabled  = true
logpath  = /var/log/nginx/error.log

[nginx-botsearch]
enabled  = true
logpath  = /var/log/nginx/access.log
maxretry = 2

I use maxretry = 3 for SSH — three wrong passwords and you're out for an hour. For bots scanning for WordPress admin panels and PHP files on a server that has neither, two hits is enough.

If you're on a non-standard SSH port, change the port line:

[sshd]
enabled = true
port    = 2222

Apply and check

sudo systemctl restart fail2ban
sudo fail2ban-client status

You should see your enabled jails listed. Check a specific jail:

sudo fail2ban-client status sshd

Shows currently banned IPs, total bans, failed attempts. If you see zeroes across the board and you know there's attack traffic, the logpath is probably wrong — see troubleshooting below.

Add your own IP to ignoreip before testing

Seriously. I've locked myself out doing exactly this — running ssh user@server with the wrong key three times while setting up fail2ban. Add your home/office IP to ignoreip before you do anything:

ignoreip = 127.0.0.1/8 ::1 203.0.113.42

Manually ban and unban

# Ban an IP immediately
sudo fail2ban-client set sshd banip 1.2.3.4

# Unban an IP
sudo fail2ban-client set sshd unbanip 1.2.3.4

# Check if an IP is banned
sudo fail2ban-client get sshd banned | grep 1.2.3.4

Make bans persistent across reboots

By default fail2ban loses its ban list on restart. Enable the database:

sudo nano /etc/fail2ban/fail2ban.local
[Definition]
dbfile = /var/lib/fail2ban/fail2ban.sqlite3
dbpurgeage = 86400

dbpurgeage is how long to keep ban records — 86400 seconds = 24 hours. Tune to taste.

Troubleshooting: jail shows no bans despite attack traffic

Wrong log path — the most common issue. Verify the log actually exists and has content:

sudo tail /var/log/auth.log
sudo tail /var/log/nginx/access.log

On systems using systemd journald instead of flat log files, the sshd jail needs:

[sshd]
backend = systemd

Wrong log format — fail2ban uses regex filters to parse logs. If your Nginx log format is non-standard, the filter won't match. Check what filter is being used:

sudo fail2ban-client get nginx-botsearch logpath
cat /etc/fail2ban/filter.d/nginx-botsearch.conf

Test a filter manually:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-botsearch.conf

Shows how many lines matched. Zero matches = filter or log format problem.

What the logs look like when it's working

sudo tail -f /var/log/fail2ban.log
2026-04-25 03:14:28 INFO    [sshd] Found 91.234.55.12 - 2026-04-25 03:14:28
2026-04-25 03:14:31 INFO    [sshd] Found 91.234.55.12 - 2026-04-25 03:14:31
2026-04-25 03:14:34 INFO    [sshd] Found 91.234.55.12 - 2026-04-25 03:14:34
2026-04-25 03:14:34 NOTICE  [sshd] Ban 91.234.55.12

Three failures, ban. Exactly what you want to see.

Longer bans for repeat offenders

fail2ban 0.10+ supports incremental ban times. Add to [DEFAULT] in jail.local:

bantime.increment   = true
bantime.multiplier  = 2
bantime.maxtime     = 86400

First offense: 1h. Second: 2h. Third: 4h. Caps at 24h. Repeat scanners escalate automatically.


Related posts