Fail2ban einrichten – SSH, Nginx, WordPress, Mail & mehr mit automatischer IP-Sperre

Warum Fail2ban? Reicht eine Firewall nicht?

Eine Firewall (wie nftables oder iptables) blockiert nur bekannte Ports und IPs. Sie ist wie ein Türsteher, der nur guckt, wer durch die Tür will. Fail2ban ist wie ein Sicherheitsmitarbeiter, der mitbekommt, wenn jemand wiederholt die Tür aufbrechen will – und dann die Tür für diesen Angreifer dichtmacht.

Praktisches Beispiel: Dein SSH-Port (50022) wird ständig von Bots aus aller Welt angegriffen. Jeder einzelne Angriff wird von der Firewall zugelassen (weil Port 50022 offen sein muss). Aber nach 4 fehlgeschlagenen Passwortversuchen erkennt Fail2ban das Muster, sperrt die IP des Angreifers per nftables – und der Angreifer kommt nicht mehr durch, egal wie oft er es versucht.

Ohne Fail2ban kann ein Angreifer eine Million Passwörter in einer Nacht ausprobieren. Mit Fail2ban hat er nach 4 Versuchen keine Chance mehr. Das reduziert die Angriffsfläche von „unendlich“ auf „4 Versuche“.

Wie funktioniert Fail2ban technisch?

Fail2ban überwacht Logdateien in Echtzeit (via inotify oder Polling). Jedes Mal, wenn eine neue Zeile in eine Logdatei geschrieben wird (z.B. /var/log/auth.log bei einem SSH-Login), vergleicht Fail2ban diese Zeile mit einem regulären Ausdruck (dem Filter).

Wenn der Filter matcht (z.B. „Failed password for root from 192.168.1.100“), zählt Fail2ban das als einen Fehlversuch für diese IP. Erreicht die IP innerhalb des findtime-Fensters (z.B. 10 Minuten) die maxretry-Grenze (z.B. 3), wird die IP für die bantime (z.B. 1 Tag) gesperrt.

Die Sperre setzt Fail2ban nicht selbst durch – es übergibt die IP an eine Action. Standardmäßig ist das nftables. Fail2ban erzeugt dann einen nftables-Regelsatz, der die IP blockiert. Nach Ablauf der bantime entfernt Fail2ban die Regel wieder.

Der Clou: Fail2ban kann beliebig viele Logdateien, Filter und Actions kombinieren. Du definierst ein „Jail“: Logdatei + Filter + Action = fertig.

Was ist Fail2ban?

Fail2ban scannt Logdateien auf Angriffsmuster (z.B. fehlgeschlagene SSH-Logins, WordPress-Brute-Force, Nginx-404-Flood) und sperrt die angreifenden IPs automatisch per nftables. Ein unverzichtbares Tool für jeden Server – simpel, effektiv, leistungsschonend.

Architektur

  Logdatei (auth.log, mail.log, access.log ...)
       │
       ▼
  Fail2ban überwacht auf Angriffsmuster
       │
       ▼
  Bei Treffer → IP wird per nftables geblockt
       │
       ▼
  Nach Ablauf der Bantime → IP wird automatisch freigegeben

1. Installation

apt-get update
apt-get install -y fail2ban nftables
systemctl enable --now fail2ban nftables

2. Grundkonfiguration (jail.local)

[DEFAULT]
bantime = 86400           # 1 Tag Sperre
findtime = 600            # 10 Minuten Zeitfenster
maxretry = 3              # Nach 3 Fehlversuchen sperren
ignoreip = 127.0.0.1/8 ::1 DEINE_IP
usedns = no
banaction = nftables
banaction_allports = nftables[type=allports]

# Bantime steigern (Rückfalltäter härter bestrafen)
bantime.increment = true
bantime.rndtime = 30m
bantime.maxtime = 604800   # Maximal 7 Tage
bantime.factor = 2
bantime.overalljails = true

Alle 11 Jails im Detail

pure-ftpd (FTP)

[pure-ftpd]
enabled = true
port = ftp,ftps
filter = pure-ftpd
logpath = /var/log/syslog
maxretry = 3
bantime = 86400

dovecot (IMAP/POP3)

[dovecot]
enabled = true
port = pop3,pop3s,imap,imaps,submission,smtps,465,587,993,995
filter = dovecot
logpath = /var/log/mail.log
maxretry = 3
bantime = 86400

postfix-sasl (SMTP-Auth)

[postfix-sasl]
enabled = true
port = smtp,smtps,submission,465,587
filter = postfix[mode=auth]
logpath = /var/log/mail.log
maxretry = 3
bantime = 86400

SSH (angepasster Port)

[sshd]
enabled = true
port = 50022             # Dein SSH-Port
filter = sshd[mode=aggressive]
logpath = /var/log/auth.log
maxretry = 4
findtime = 600
bantime = 604800          # 7 Tage für SSH

Recidive (Dauer-Rückfalltäter)

Sperrt IPs, die wiederholt in anderen Jails auffallen:

[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime = 2592000         # 30 Tage
findtime = 30d
maxretry = 5

Nginx-HTTP-Auth

[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 86400

Nginx-Limit-Req (Rate Limiting)

Sperrt IPs, die den Nginx-Rate-Limiter auslösen (z.B. zu viele Requests pro Sekunde):

[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 600
bantime = 3600

Nginx-Bad-Bots

Sperrt bekannte Bots und Crawler aus der Apache-Badbots-Liste:

[nginx-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /var/log/nginx/access.log
maxretry = 2
findtime = 86400
bantime = 86400

Nginx-Bot-Search

Sperrt IPs, die nach verwundbaren Pfaden suchen:

[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400

Nginx-Bad-Request

Sperrt IPs mit fehlerhaften HTTP-Requests:

[nginx-bad-request]
enabled = true
port = http,https
filter = nginx-bad-request
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 86400

WordPress (Login + XML-RPC)

Eigener Filter für WordPress-Login-Brute-Force und XML-RPC-Angriffe:

/etc/fail2ban/filter.d/wordpress.conf:

[Definition]
failregex = ^<HOST> .* "POST /wp-login.php HTTP.*" (200|302)
            ^<HOST> .* "POST /xmlrpc.php HTTP.*" (200|302)
ignoreregex =

Jail-Konfiguration:

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime = 86400

3. Bantime-Steigerung (Rückfalltäter)

Fail2ban kann die Sperrdauer automatisch erhöhen, wenn eine IP wiederholt auffällt:

Parameter Wert Erklärung
bantime.increment true Aktiviert progressive Bantime
bantime.factor 2 Verdoppelt die Zeit pro Treffer
bantime.maxtime 604800 Maximal 7 Tage
bantime.overalljails true Zählt Treffer über alle Jails

Beispiel: 1. Treffer → 1 Tag, 2. Treffer → 2 Tage, 3. Treffer → 4 Tage … maximal 7 Tage.

4. Alle Logdateien im Überblick

Logdatei Überwacht durch
/var/log/auth.log sshd
/var/log/mail.log dovecot, postfix-sasl
/var/log/nginx/access.log nginx-badbots, nginx-botsearch, nginx-bad-request, wordpress
/var/log/nginx/error.log nginx-http-auth, nginx-limit-req
/var/log/syslog pure-ftpd
/var/log/fail2ban.log recidive

5. Alle Befehle für den täglichen Betrieb

# Status aller Jails
fail2ban-client status

# Status eines einzelnen Jails
fail2ban-client status nginx-badbots

# Liste aller gesperrten IPs
fail2ban-client banned

# IP manuell entsperren
fail2ban-client set nginx-http-auth unbanip 192.168.1.100

# IP manuell sperren
fail2ban-client set nginx-http-auth banip 192.168.1.100

# Konfiguration neu laden
fail2ban-client reload

# Konfiguration neu laden (alle Jails)
systemctl reload fail2ban

# Fail2ban Logs live verfolgen
tail -f /var/log/fail2ban.log

# Alle aktuell gesperrten IPs in nftables
nft list set inet f2b-table addr-set-nginx-badbots

6. Nach der Installation – Quickstart

# 1. Konfiguration erstellen
nano /etc/fail2ban/jail.local

# 2. Syntax prüfen
fail2ban-client -t

# 3. Fail2ban neustarten
systemctl restart fail2ban

# 4. Status prüfen
fail2ban-client status

# 5. Testen: SSH-Fehlversuche auslösen
ssh falscher-benutzer@dein-server
# fail2ban-client status sshd

7. Wartung

# Logrotation prüfen
tail -f /var/log/fail2ban.log

# Statistiken
fail2ban-client status | grep "Jail list"

# Banned IPs aus allen Jails
for jail in $(fail2ban-client status | grep "Jail list:" | cut -f2); do
    echo "$jail: $(fail2ban-client status $jail | grep "Banned IP list")"
done

Fazit

11 Jails schützen deinen Server vor Brute-Force, Bots, Scan-Angriffen und WordPress-Exploits. Fail2ban ist einfach, zuverlässig und verbraucht kaum Ressourcen – auf jedem Server Pflicht!

X

Basti

Entwickler und Smart-Home-Enthusiast aus Deutschland. Ich entwickle Open-Source-Integrationen für Home Assistant (IDM Wärmepumpe, Violet Pool Controller), Modbus-Tools (ModBridge) und betreibe verschiedene Server-Dienste (Matrix, Seafile, SOGo).

GitHub →

Schreibe einen Kommentar