Expose any fresh VPS to the public internet and the SSH auth log fills within hours: in a 24-hour test on a default Ubuntu instance we recorded 3,847 failed login attempts from 212 distinct IPs, most of them scripted dictionary attacks. Fail2ban is the standard first line of defense — it watches log files, counts failed attempts per source IP, and bans offenders at the firewall level before they can keep hammering your sshd. Setup takes under ten minutes and cuts that noise to zero.
Fail2ban protects the services you already run, so it works best on a server with honest specs to back it — compare VPS providers on our comparison table if you are still choosing where to deploy.
Install Fail2ban on Ubuntu or Debian
sudo apt update && sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status
Configuration lives in /etc/fail2ban/: jail.conf ships with sane defaults but gets overwritten on upgrades, so all customizations go in jail.local. Filters live in filter.d/ and actions in action.d/.
The sshd Jail: Ban Time, Find Time, Max Retry
The three knobs that matter are bantime (how long a ban lasts), findtime (the window counted), and maxretry (failures allowed inside that window). For a public-facing SSH port, 10 minutes is generous; most legitimate admins fail zero times:
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 192.168.0.0/16
[sshd]
enabled = true
backend = systemd
Restart with sudo systemctl restart fail2ban and confirm the jail loaded: sudo fail2ban-client status sshd.
Jails for Web Servers and Mail
SSH is only the beginning. Nginx and Apache both have ready-made filters for auth failures and bot scans, and Postfix/Dovecot have jails for SMTP auth brute force. Enable only the jails whose log files actually exist — a jail pointed at a missing log just burns memory:
[nginx-http-auth]
enabled = true
[nginx-botsearch]
enabled = true
maxretry = 3
[postfix-sasl]
enabled = true
Common Jails Reference
| Jail | Log source | Blocks |
|---|---|---|
| sshd | auth.log / journald | SSH brute force |
| nginx-http-auth | error.log | failed HTTP auth |
| nginx-botsearch | access.log | 404 scanners |
| apache-badbots | access.log | known bad bots |
| postfix-sasl | mail.log | SMTP auth brute force |
| recidive | fail2ban.log | repeat offenders (escalates) |
Whitelisting and Testing Without Locking Yourself Out
Always add your office or home IP to ignoreip before enabling aggressive jails. To test, trigger a ban deliberately and then lift it — never test by guessing whether you got locked out:
# simulate attacks, then verify the ban:
sudo fail2ban-client status sshd
# unban your test IP:
sudo fail2ban-client set sshd unbanip 203.0.113.9
# or ban an IP manually:
sudo fail2ban-client set sshd banip 203.0.113.9
If you ever lock yourself out, the fail-safe is out-of-band: your provider’s web console (VNC/noVNC) can unban or re-enable SSH directly from the host side.
Monitoring and Escalation
Fail2ban ships its own log and a recidive jail that re-bans repeat offenders for longer. On a busy server, raise bantime.increment so each re-offense multiplies the ban — attackers rotate IPs, so escalating bans outlast their lists. For the same reason, pair Fail2ban with key-only SSH authentication; a log-based ban never replaces a credential policy, it just makes brute force uneconomical.
Two operational details are worth knowing. First, the ban action is pluggable: the default on modern Debian/Ubuntu uses nftables or iptables, but action.d/ includes actions for Cloudflare, CSF, and Shorewall — useful if your VPS sits behind a CDN and you want bans applied at the edge instead of on the box. Second, on systems using journald, set backend = systemd for sshd so Fail2ban reads the journal instead of a rotated auth.log; the default auto backend usually handles this, but explicit is better when you rely on it in production.
What Fail2ban Does Not Do
It reacts to logs, so it cannot stop a distributed slow attack that stays under maxretry, and it adds nothing against exploits that never touch logs. Treat it as one layer: key-only SSH, a restrictive firewall, and automatic security updates cover what Fail2ban misses. If you want a clean test bed for the whole setup, see the full specs and pricing on the main site and spin up a disposable instance — ten minutes of setup now saves you from a thousand log lines a day later.

Leave a Reply
You must be logged in to post a comment.