Blocking Brute-Force Attacks with fail2ban on Linux
fail2ban watches your logs and bans attackers automatically. Here's how to configure jails, filters, and bantime to lock down SSH and web services.
- #linux
- #security
- #fail2ban
- #ssh
- #hardening
- #firewall
Put a server on a public IP and within minutes the SSH login attempts start — thousands a day, automated bots cycling through usernames and passwords. Key-only SSH stops them from succeeding, but they still fill your logs and waste resources. fail2ban is the simple, decades-proven answer: it tails your logs, spots the patterns of an attack, and tells your firewall to ban the source IP. I run it on every internet-facing box. Here’s how to set it up so it actually protects you without locking you out.
How fail2ban works
The model is three pieces:
- Filters — regexes that recognize a “failure” line in a log (a failed SSH auth, a 401 storm, a bad POST).
- Jails — bind a filter to a log file and a policy: how many failures, in what window, trigger what ban.
- Actions — what to do on a ban, almost always “insert a firewall rule dropping this IP.”
It ships with filters for SSH, Apache, Nginx, Postfix, and dozens more. You mostly configure jails.
Install and the golden config rule
sudo apt install fail2ban # Debian/Ubuntu
sudo dnf install fail2ban # RHEL family
Never edit jail.conf. Package updates overwrite it. Put all your config in jail.local, which overrides jail.conf and survives upgrades:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
The default section: get this right first
At the top of jail.local, the [DEFAULT] block sets policy for every jail:
[DEFAULT]
# Whitelist your own networks so you can NEVER ban yourself
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/24 203.0.113.10
bantime = 1h # how long a ban lasts
findtime = 10m # window in which failures are counted
maxretry = 5 # failures within findtime to trigger a ban
# Use the modern backend that watches the systemd journal
backend = systemd
The ignoreip line is the most important one in the file. Put your office IP, your VPN range, and your monitoring hosts here so a typo’d password never bans you out of your own server. Test from a known-safe network the first time regardless.
backend = systemd is worth calling out: on modern distros, services log to the journal rather than to flat files, so the journal backend is more reliable than pointing at a logpath that may not exist.
A solid SSH jail
SSH is the jail everyone needs. Enable and tune it:
[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 1h
findtime = 10m
If you run SSH on a non-standard port, set port accordingly (or use 0.0.0.0/0 matching with the right filter). Three strikes in ten minutes is a reasonable SSH policy — aggressive enough to stop bots, forgiving enough for a fat-fingered password.
Escalating repeat offenders
A bot that comes back after its ban expires should get banned longer. The recidive jail watches fail2ban’s own log and hammers repeat offenders:
[recidive]
enabled = true
bantime = 1w # a week for repeat offenders
findtime = 1d
maxretry = 5
You can also enable incremental banning globally so each subsequent ban for the same IP lasts longer:
[DEFAULT]
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1w
This is my preferred setup: short first ban, exponentially longer for anything persistent, capped at a week.
Protecting web services
The same machinery defends HTTP. For an Nginx box getting hit with auth-failure or bad-bot floods:
[nginx-http-auth]
enabled = true
[nginx-botsearch]
enabled = true
For custom attack patterns (say, repeated hits to /wp-login.php on a non-WordPress site), write a filter in /etc/fail2ban/filter.d/ with a regex and a failregex capturing the offender’s IP, then point a jail at your access log. The fail2ban-regex tool lets you test a filter against a real log before deploying it:
fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/myfilter.conf
That test step saves you from a filter that matches nothing — or worse, matches everything.
Operating it day to day
sudo systemctl restart fail2ban
sudo fail2ban-client status # list active jails
sudo fail2ban-client status sshd # banned IPs, failure counts for one jail
To manually unban an IP (the one you’ll need when you ban a coworker):
sudo fail2ban-client set sshd unbanban 203.0.113.55
And to manually ban a known-bad IP immediately:
sudo fail2ban-client set sshd banip 198.51.100.7
Watch its activity:
sudo journalctl -u fail2ban -f
Where it fits, and its limits
fail2ban is a log-reactive tool — it bans after failures, so it’s a rate-limiter and noise-reducer, not a substitute for real hardening. Layer it on top of, not instead of: key-only SSH, a default-deny firewall, and disabled root login. Combined, a public box goes from “thousands of probes hammering sshd” to “attackers banned within three tries and forgotten.” If you’re building out the broader picture, our Linux admin guides cover SSH hardening and firewalling alongside this.
Where AI helps
Writing a correct failregex for a custom log format is fiddly — one wrong capture group and it silently matches nothing. Paste a few real offending log lines into a model and ask for a fail2ban filter regex, then verify it with fail2ban-regex. That loop turns a 30-minute regex-wrangling session into a couple of minutes. I keep a few Linux admin prompts for exactly this kind of log-pattern work.
fail2ban is cheap insurance: ten minutes of config, a careful ignoreip, and your public servers stop bleeding attention to brute-force noise. Set it up once, whitelist yourself, and let it quietly do its job.
Generated commands and configs are assistive, not authoritative. Always verify against your own systems before applying changes in production.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.