fail2ban Configuration
fail2ban is a log-watching daemon that adds firewall rules to ban IPs that repeatedly fail to authenticate. It's not magic โ it doesn't stop a determined attacker โ but it cuts brute-force log noise by 99% on any public-facing server, and the configuration is straightforward.
Concepts
A jail ties together a filter (regex that matches failed-auth lines), one or more log paths, and an action (what to do when threshold is hit). The shipped jail.conf has dozens of templates; you override them in jail.local.
Minimum useful config
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd # read from journald, not text logs
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 # never ban your own subnets
# Send notification emails (optional)
destemail = ops@example.com
sender = fail2ban@example.com
mta = sendmail
action = %(action_mwl)s # ban + email + whois + log lines
[sshd]
enabled = true
port = ssh
filter = sshd
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
[nginx-noscript]
enabled = true
port = http,https
filter = nginx-noscript
logpath = /var/log/nginx/access.log
maxretry = 6
systemctl reload fail2ban
fail2ban-client status
fail2ban-client status sshd
Custom filter
To watch a custom app's auth log, write a filter. A filter is a regex with <HOST> as the IP placeholder:
# /etc/fail2ban/filter.d/myapp.conf
[Definition]
failregex = ^.* login failed for user .* from $
ignoreregex =
Test it before enabling:
fail2ban-regex /var/log/myapp.log /etc/fail2ban/filter.d/myapp.conf
Aggressive jail (use sparingly)
For repeat offenders that come back after a 1-hour ban, fail2ban can ban them for much longer. Use the recidive jail, which watches fail2ban's own log for IPs that have already been banned:
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
maxretry = 3
findtime = 1d
bantime = 1w
action = iptables-allports[name=recidive]
Unbanning
fail2ban-client set sshd unbanip 198.51.100.42
fail2ban-client unban --all
False positives
Common causes: an HTTP load balancer or CDN โ fail2ban sees the proxy IP getting banned, not the actual client. Fix with X-Forwarded-For aware nginx config plus real_ip_header directives that rewrite the logged IP. Or run fail2ban behind your CDN's IP list in ignoreip and rely on the CDN's own rate limiting.
What fail2ban is not
Not a WAF. Not a DDoS defense. Not a substitute for password-less auth. It's the log-noise filter for low-effort attacks. For everything else, use the right tool.