Fail2Ban watches authentication logs, matches repeated failures, and triggers an action such as a temporary firewall ban. For an internet-facing SSH service, it can reduce noise from repeated password guessing and slow simple automated attacks.
Fail2Ban is not a substitute for strong SSH configuration. Key-based authentication, restricted administrative access, disabled direct root login, current software, and reliable logging remain more important controls.
Harden SSH before adding automatic bans
Begin with a second administrative session open so a configuration mistake does not lock you out. Create and test a non-root administrative account with an SSH key. Confirm that privilege escalation works as intended before disabling direct root access or password authentication.
- Use unique SSH keys protected with suitable passphrases.
- Disable direct root login with
PermitRootLogin no. - Disable password authentication only after key access is verified.
- Limit which users or groups may connect when practical.
- Restrict network access at the provider firewall or VPN layer when possible.
- Keep OpenSSH and the operating system patched.
Configure a focused sshd jail
Install Fail2Ban through the operating system’s supported package manager. Keep local changes in jail.local or a file under jail.d/. The project warns against editing the distributed jail.conf because package updates may replace or improve that file.
[sshd]
enabled = true
port = ssh
backend = systemd
findtime = 10m
maxretry = 5
bantime = 1h
# Add only verified administrative source addresses.
# Never copy an example address into production.
ignoreip = 127.0.0.1/8 ::1The correct backend and log source depend on the distribution. Systems using systemd may read the journal, while others use a path such as /var/log/auth.log or /var/log/secure. Confirm the actual SSH logs before choosing a backend.
findtime defines the observation window, maxretry sets the number of matched failures, and bantime controls how long the action remains active. Tune them to the environment. Aggressive values can lock out legitimate users without stopping distributed attacks.
Test before depending on it
Validate the service configuration, start Fail2Ban, and confirm the sshd jail is active. Then use fail2ban-client to view jail status and the current ban list.
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo journalctl -u fail2ban --since "30 minutes ago"Use fail2ban-regex when you need to confirm that a filter matches the real log format. Test from a separate authorized source and keep a recovery path available. Do not intentionally trigger bans from the only address you can use for administration.
Operate Fail2Ban as part of a layered control set
Review bans for patterns and false positives. A large number of blocked attempts may be normal internet noise, but sudden changes can still be useful operational signals. Preserve logs long enough to support investigation, and make sure automated bans do not hide a persistent authentication problem.
When the server is behind Cloudflare for web traffic, remember that normal SSH traffic is separate. Cloudflare’s standard web proxy does not automatically protect the SSH port. Provider firewall rules, a VPN, or a suitable access proxy can reduce exposure more effectively than relying on Fail2Ban alone.
A sensible priority order is: restrict network reachability, require strong SSH keys, limit privileged accounts, patch the service, collect useful logs, and then use Fail2Ban to respond to repeated failures.