Security

fail2ban Configuration

ยท2 min read

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.

Related