Block SSH brute-force with fail2ban (Linux)
Install fail2ban and configure an SSH jail that auto-bans IPs after repeated failed login attempts. Works on Ubuntu, Debian, Fedora, and openSUSE.
bash# Install fail2ban
# Ubuntu / Debian:
sudo apt-get install -y fail2ban
# Fedora / Rocky / AlmaLinux:
# sudo dnf install -y fail2ban
# openSUSE:
# sudo zypper install -y fail2ban
# Create jail.local — never edit jail.conf directly (it gets overwritten on updates)
sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
# Ban for 1 hour after 5 failures within 10 minutes
bantime = 3600
findtime = 600
maxretry = 5
# Use systemd journal as the log backend (works on all modern distros)
backend = systemd
# Email alerts (optional — set to your address or leave blank)
destemail =
sendername = fail2ban
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
maxretry = 3
EOF
# Enable and start
sudo systemctl enable --now fail2ban
# Verify the SSH jail is active
sudo fail2ban-client status sshd
What this does
Installs fail2ban and configures a jail for SSH that:
- Monitors
/var/log/auth.log(or the systemd journal on modern distros) for failed login attempts - Bans the offending IP via
iptablesafter 3 failures within 10 minutes - Keeps the ban in place for 1 hour
On internet-exposed servers, fail2ban typically reduces SSH log noise by 90%+ within hours.
Why this approach
Even with key-only SSH authentication, connection attempts still show up in your auth log — bots scanning the internet probe every host on port 22, attempting to authenticate with default credentials or known username lists. These attempts don’t succeed with key auth, but they generate log noise and consume a small amount of server resources for each connection. Fail2ban doesn’t change the cryptographic security — key auth already handles that — but it reduces noise and provides a practical defense against slower human-operated probing.
The approach here uses a drop-in jail configuration in /etc/fail2ban/jail.d/ rather than editing the main fail2ban.conf. Drop-ins survive package updates and make it easy to audit what’s custom versus what shipped with the package. The three-failures-in-ten-minutes threshold is conservative enough to avoid false-positives from someone mistyping a passphrase, but tight enough to catch any systematic attempt in seconds.
The backend = systemd option matters on modern Debian and Ubuntu installs because many don’t write /var/log/auth.log at all — auth events go only to the systemd journal. An older configuration using backend = auto or pointing at a log file can silently find no events and ban nothing, while looking like it’s working fine. Setting it explicitly ensures fail2ban reads from the right source regardless of distro defaults. If you’re on a distro that does write auth.log, systemd still works — it reads from the journal, which includes auth events.
Prerequisites
- A Linux distro with systemd (Ubuntu 20.04+, Debian 11+, Fedora 38+, openSUSE Leap 15+)
- Root or sudo access
- sshd running and accepting connections
Adjust ban settings
Edit /etc/fail2ban/jail.local to tune aggressiveness. For a server with only known users:
[DEFAULT]
bantime = 86400 # 24-hour ban
findtime = 300 # 5-minute window
maxretry = 3 # ban after 3 failures
[sshd]
enabled = true
maxretry = 2 # stricter for SSH specifically
Reload after any change:
sudo fail2ban-client reload
Whitelist your own IP
Add trusted IPs to ignoreip so you can never ban yourself:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
Separate multiple entries with spaces. CIDR ranges are supported.
If you changed the SSH port
Update the jail to match:
[sshd]
enabled = true
port = 2222
Useful management commands
# Show all active jails
sudo fail2ban-client status
# Show banned IPs for SSH
sudo fail2ban-client status sshd
# Manually unban an IP
sudo fail2ban-client set sshd unbanip 1.2.3.4
# Manually ban an IP
sudo fail2ban-client set sshd banip 1.2.3.4
# Test a regex pattern against a log line
sudo fail2ban-regex /var/log/auth.log sshd
Email alerts (optional)
To receive an email when an IP is banned, install sendmail and set destemail in jail.local:
[DEFAULT]
destemail = you@example.com
sendername = fail2ban
mta = sendmail
action = %(action_mwl)s
action_mwl sends the ban notification with the matching log lines included.
Notes
- fail2ban modifies
iptablesrules in real time — bans survive afail2ban-client reloadbut are cleared on reboot unlessdbpurgeageis set (bans are re-read from the database on restart by default) backend = systemdreads from the journal directly — no need for a log file on distros that don’t write to/var/log/auth.log- Pair this with the SSH hardening playbook (key-only auth) for layered defence