Fail2ban monitors your service logs for repeated failures and blocks offending IPs using your firewall. This guide explains the concept and gives copy paste jails for SSH on 22, HTTP on 80 or 443, and MySQL or MariaDB on 3306.

How Fail2ban works

  • Reads logs from services (for example: /var/log/auth.log, web server error or access logs, MySQL error log).
  • Filters match suspicious lines.
  • If failures exceed maxretry within findtime, Fail2ban bans the source IP for bantime via nftables on Debian 12.

Key terms:

  • jail: the rule that ties a filter and an action to specific logs and ports
  • filter: regex rules that match bad events in logs
  • action: how to ban (we use nftables-multiport)

Install Fail2ban

sudo apt update
sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

Install rsyslog

Fail2ban only works if it can see login failures in your logs. On Debian 12, the system journal (journald) already captures them, but many Fail2ban jails still expect a traditional log file like /var/log/auth.log. To keep things simple, install rsyslog so those logs are written out automatically:

sudo apt install rsyslog
sudo systemctl enable --now rsyslog

Base configuration

Do not edit jail.conf. Create your own overrides.

/etc/fail2ban/jail.local

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1
banaction = nftables-multiport
logtarget = /var/log/fail2ban.log

Reload after changes:

sudo fail2ban-client reload

Jail 1, protect SSH on port 22

/etc/fail2ban/jail.d/sshd.local

[sshd]
enabled  = true
port     = 22
backend  = auto
logpath  = /var/log/auth.log
maxretry = 5
findtime = 10m
bantime  = 1h

Check status:

sudo fail2ban-client status sshd
sudo tail -f /var/log/fail2ban.log

Jail 2, protect HTTP on ports 80 and 443

Fail2ban reacts to patterns in logs. Two common web auth cases are below. Use only the one that applies to your stack.

Nginx basic auth:
/etc/fail2ban/jail.d/nginx-http-auth.local

[nginx-http-auth]
enabled  = true
port     = http,https
filter   = nginx-http-auth
logpath  = /var/log/nginx/error.log
maxretry = 3
findtime = 10m
bantime  = 1h

Apache basic auth:
/etc/fail2ban/jail.d/apache-auth.local

[apache-auth]
enabled  = true
port     = http,https
filter   = apache-auth
logpath  = /var/log/apache2/error.log
maxretry = 3
findtime = 10m
bantime  = 1h

Tip: run ls /etc/fail2ban/filter.d to see other web filters such as nginx-noscript or apache-badbots, then point a jail at the filter and the correct log path.

Jail 3, watch MySQL or MariaDB on port 3306

Best practice is not to expose 3306 publicly. Bind to localhost or a private network and restrict with your firewall. If you must watch for brute force on 3306:

/etc/fail2ban/jail.d/mysqld-auth.local

[mysqld-auth]
enabled  = true
port     = 3306
filter   = mysqld-auth
logpath  = /var/log/mysql/error.log
maxretry = 3
findtime = 10m
bantime  = 6h

Confirm the error log path inside MariaDB or MySQL:

SHOW VARIABLES LIKE 'log_error';

If your DB logs only to the journal, you can switch a jail to use systemd:

[mysqld-auth]
enabled   = true
port      = 3306
filter    = mysqld-auth
backend   = systemd
journalmatch = _SYSTEMD_UNIT=mariadb.service + _COMM=mysqld
maxretry  = 3
findtime  = 10m
bantime   = 6h

Optional, recidive jail for repeat offenders

/etc/fail2ban/jail.d/recidive.local

[recidive]
enabled  = true
logpath  = /var/log/fail2ban.log
bantime  = 1d
findtime = 1d
maxretry = 5

Apply and verify

Check configuration syntax:

sudo fail2ban-client -d

Reload Fail2ban:

sudo fail2ban-client reload

List jails and show bans:

sudo fail2ban-client status
sudo fail2ban-client status sshd

Unban a specific IP:

sudo fail2ban-client set sshd unbanip 203.0.113.45

Check nftables sets for banned IPs:

sudo nft list ruleset | grep -A3 'f2b'

Troubleshooting

  • Filters available:
ls /etc/fail2ban/filter.d
  • Test a filter against a log:
sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf
  • Reverse proxy or CDN:
    Ensure your web server logs the real client IP, not the proxy, otherwise you will ban the proxy’s IP.
  • Dockerized services:
    Make sure containers write logs to files on the host or to journald so Fail2ban can read them.

Leave A Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.