Fail2ban is one of those tools that gets installed once and never looked at again. It shows up in every "secure your VPS" guide. People install it, see the service is running, and assume they're protected.
Most of the time they're not. The default configuration is wrong for modern Ubuntu servers, the ban times are too short to matter, and the most common setup has a gap that lets brute force attacks run for hours before a single ban fires.
Here's how to check your setup in 5 minutes.
Check 1: Is fail2ban actually running?
sudo systemctl status fail2ban sudo fail2ban-client status
The second command is the important one. It shows you active jails. If you see |- Number of jail: 0 — fail2ban is running but protecting nothing. No jails means no bans.
Check 2: Is the SSH jail active?
sudo fail2ban-client status sshd
If this returns ERROR No such jail: sshd — your SSH port is completely unprotected by fail2ban despite the service running.
On Ubuntu 22.04 with systemd, the default jail name is sshd. On older configs it might be ssh. If neither works, your SSH jail is not configured.
Check 3: What backend is fail2ban using?
grep "backend" /etc/fail2ban/jail.conf /etc/fail2ban/jail.local 2>/dev/null
On Ubuntu 20.04+, the correct backend is systemd because SSH logs go to the journal, not to /var/log/auth.log. If fail2ban is configured with backend = auto or backend = polling on a systemd server, it may be reading the wrong log source and missing all SSH login attempts.
This is the most common misconfiguration: fail2ban is running, the sshd jail is active, but it is reading from /var/log/auth.log on a server where SSH logs only go to journald. Zero bans fire. Zero protection.
Check 4: Are your ban times long enough to matter?
sudo fail2ban-client get sshd bantime sudo fail2ban-client get sshd maxretry sudo fail2ban-client get sshd findtime
Default values: bantime = 10m, maxretry = 5, findtime = 10m.
10 minutes is not a deterrent. A distributed brute force attack rotates IPs. Ban an IP for 10 minutes and the attacker just waits or switches. A useful ban time is at least 1h — better is 1d for repeat offenders using recidive jail.
The correct configuration for Ubuntu 22.04
Create or edit /etc/fail2ban/jail.local — never edit jail.conf directly, it gets overwritten on updates.
# /etc/fail2ban/jail.local [DEFAULT] bantime = 1h findtime = 10m maxretry = 3 backend = systemd [sshd] enabled = true port = ssh logpath = %(sshd_log)s backend = %(sshd_backend)s maxretry = 3 bantime = 24h [recidive] enabled = true logpath = /var/log/fail2ban.log banaction = %(banaction_allports)s bantime = 1w findtime = 1d maxretry = 5
The recidive jail bans IPs that have been banned multiple times — for a full week, on all ports. This is the configuration that actually stops persistent attackers.
sudo systemctl restart fail2ban sudo fail2ban-client status sshd # Should show: Currently banned: 0, Total banned: N
Check 5: Is your SSH port in the ban list?
If you changed your SSH port from 22, fail2ban's sshd jail needs to know. By default it only watches port 22.
# Check your SSH port: grep "^Port" /etc/ssh/sshd_config # If it's not 22, update jail.local: [sshd] port = 2222 # Your actual SSH port
Check 6: Is localhost ignored?
sudo fail2ban-client get sshd ignoreip
Should include 127.0.0.1/8 ::1. If you've locked yourself out before by accidentally triggering a ban on your own IP, add your static IP or home network here.
Paste your ufw status verbose to audit firewall rules alongside your fail2ban setup — UFW and fail2ban work together but can have gaps.
Quick audit script
#!/bin/bash echo "=== Fail2ban Status ===" systemctl is-active fail2ban echo "=== Active Jails ===" fail2ban-client status 2>/dev/null | grep "Jail list" echo "=== SSH Jail ===" fail2ban-client status sshd 2>/dev/null || echo "sshd jail NOT active" echo "=== Ban Settings ===" fail2ban-client get sshd bantime 2>/dev/null fail2ban-client get sshd maxretry 2>/dev/null fail2ban-client get sshd findtime 2>/dev/null echo "=== Backend ===" grep -h "backend" /etc/fail2ban/jail.local /etc/fail2ban/jail.conf 2>/dev/null | head -3
Run this on any server you manage. If you see missing jails, wrong backend, or 10-minute ban times — fix them before the next scan hits your SSH port.