fail2ban with kernel-level ban sets: O(1) drop via named addr-set, recidive horizon 90 days
I run fail2ban with kernel-level ban sets via nftables so the data path stays O(1) even at 10k+ offenders. My docs cover a 2-jail core pattern (sshd + recidive) plus a 6-jail mail-system extension; in production I extend this to a 5-jail stack covering transport, mail, and trusted-SSH ranges. The point is layered defense: fail2ban reacts to log evidence, the kernel rejects further packets.
Stack
- fail2ban 1.x
- nftables (kernel.x)
- systemd unit: fail2ban.service
- iptables (wg0 PostUp/PostDown only)
- Debian defaults jail stack
Métricas verificadas
2-jail fail2ban core pattern (sshd + recidive) is documented as primary ban mechanism
loust-pro-monorepo/docs/security/DEFENSE-IN-DEPTH.md:357-365
6 custom fail2ban jails for mail system (postfix, dovecot, recidive, etc.) with explicit bantime/findtime
loust-pro-monorepo/docs/mail-system/SECURITY.md:62-148
fail2ban-as-IDS pattern noted in defense-in-depth narrative (no Suricata)
loust-pro-monorepo/docs/security/DEFENSE-IN-DEPTH.md:339-365
Métricas estimadas
- Production stack runs 5 custom jails: hardened SSH, edge transport, trusted-SSH allowlist, stricter SSH, Debian defaults
- Named kernel ban sets (sshd, recidive, nginx 404s, postfix) reject traffic without per-packet log lookup
- Recidive ban horizon: 90 days bantime after a 7-day findtime window — offenders that reappear stay out
- sshd hardening: 3 attempts in 15 minutes triggers a 7-day ban
- Mail jails: 4 attempts in 15 minutes triggers a 48-hour ban
- trusted-ssh jail ignores the VPN mesh and 14 residential MX ranges to avoid self-lockout
- Edge-transport jails cover QUIC, Hysteria, and gost listeners — see the transport entry for the layered rationale
Fuente: telemetría de producción o advisory externa.
Deltas de mejora
- Next iteration: commit the firewall table source so reviewers can diff the live config against docs
- Next iteration: surface recidive-ban telemetry (e.g. '14 IPs banned in 24h') into the operational dashboard
- Next iteration: integrate with the lzt-watchdog family so ban storms trigger an alert, not just a log entry