Expose an SSH port to the internet and the probes start within minutes: dictionaries of usernames, thousands of attempts a day, all logged as failed password entries in auth.log. Blocking them by hand is a losing game, which is exactly what fail2ban automates — it watches service logs for repeated failures and injects temporary firewall bans against the offending IP. This guide sets up fail2ban on a VPS, tunes the jail for SSH and web services, and shows you how to test it without locking yourself out.
Fail2ban is a layer on top of your host firewall, so the ruleset from the previous setup should already be in place. It is also worth checking your provider’s abuse policies first — some hosts frown on aggressive scanning, and the underlying hardware needs to handle connection tracking for thousands of banned IPs; compare VPS plans on our comparison table to pick a host that gives you full root control over both.
Install and Start the Default Jails
Install fail2ban from the distribution repositories — never from random PPAs, since this daemon runs as root:
apt update && apt install -y fail2ban
systemctl enable --now fail2ban
fail2ban-client status # lists active jails
Out of the box you get an sshd jail with conservative defaults: 5 failures within 10 minutes earns a 10-minute ban. Configuration lives in /etc/fail2ban/jail.local, which overrides the packaged jail.conf without being clobbered by updates. Start with realistic thresholds — on a busy server 3 failures can be a flaky client, but 5 is usually malice:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8
[sshd]
enabled = true
backend = systemd
bantime can be a duration string like 1h or 7d; the recidive jail (enabled separately) escalates repeat offenders by watching the main fail2ban log itself and banning for a week. Two settings worth knowing: banaction selects the firewall backend — nftables-multiport on modern systems, iptables-multiport on older ones — and must match the firewall you actually run, or bans silently do nothing. backend = systemd reads the journal instead of a log file, which is correct on Debian 12 and Ubuntu 22.04+ where sshd logs to the journal. Restart the service after changes: systemctl restart fail2ban, and confirm each jail loaded with fail2ban-client status.
Jails Beyond SSH
SSH is only the beginning. Fail2ban ships with hundreds of filters, and the ones worth enabling on a typical VPS are:
| Jail | Protects | Log file |
|---|---|---|
sshd | SSH brute force | auth.log (systemd) |
nginx-http-auth | Basic-auth password guessing | nginx error.log |
nginx-botsearch | Scanners hitting 404 paths | nginx access.log |
postfix-sasl | SMTP AUTH brute force | mail.log |
proftpd / vsftpd | FTP login attacks | ftp logs |
Enable one, verify its log path actually exists (a wrong path silently disables the jail), then restart. A typical pair for a web server looks like this — note the custom maxretry for the bot jail, since bots are more persistent than humans:
[nginx-botsearch]
enabled = true
logpath = /var/log/nginx/access.log
maxretry = 3
findtime = 1h
bantime = 12h
If you are running this on rented hardware, the ban actions themselves consume a little CPU and memory per banned IP, but nothing that matters until you hit tens of thousands of entries. A VPS with a decent CPU and 2 GB of RAM handles that easily — InterServer’s VPS plans include root access and flat-rate pricing, so you can tune jails aggressively without worrying about metered abuse charges.
Test It Safely, Then Watch It Work
Never test a ban from the machine you are sitting on without a fallback. The safe procedure: open a second SSH session, then deliberately trigger failures from another IP (a phone on mobile data works well):
# from the attacking machine: 5 wrong passwords in a row
ssh root@your-vps # fail 5 times
# back on the VPS:
fail2ban-client status sshd
# "Currently banned: 1" — and the IP is in your firewall:
nft list set inet f2b-sshd # or: iptables -L f2b-sshd -n
To unban manually: fail2ban-client set sshd unbanip 203.0.113.9. To ban immediately for testing: fail2ban-client set sshd banip 203.0.113.9. If you ever see legitimate users getting caught, raise maxretry or add their IP to ignoreip — a whitelist entry is always better than a support ticket.
Two operational notes. First, if your VPS sits behind Cloudflare, ban by X-Forwarded-For requires the apache-shared-style proxy filter or you will ban Cloudflare’s edge IPs and take your own site down. Second, monitor the fail2ban.log for Ban/Unban lines — a steady stream of bans means your setup is earning its keep. Combined with key-based SSH authentication and a stateful firewall, fail2ban turns passive exposure into an automated defense; for the hardware to run it 24/7, see the full specs and pricing on our comparison table.

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