Ein SSH-Port, der offen im Internet steht, sammelt in den ersten Stunden nach dem Provisionieren hunderte Anmeldeversuche von automatisierten Scannern. Jeder Versuch kostet CPU-Zeit, bläht die Logs auf und trifft irgendwann ein schwaches Passwort. fail2ban wertet die Auth-Logs aus und sperrt auffällige IP-Adressen automatisch auf Firewall-Ebene.
Diese Anleitung richtet fail2ban 1.0.2 auf Debian 12 und Ubuntu 24.04 ein, konfiguriert ein eigenes sshd-Jail und zeigt, wie du die Sperren kontrollierst, ohne dich selbst auszusperren.
Was macht fail2ban bei einem SSH-Brute-Force-Angriff?
fail2ban ist ein Log-Parser, der SSH-Logeinträge auf fehlgeschlagene Anmeldungen prüft und eine IP-Adresse nach einer konfigurierten Zahl von Fehlversuchen innerhalb eines Zeitfensters per iptables- oder nftables-Regel für eine definierte Dauer blockiert.
Die Konfiguration besteht aus wenigen Bausteinen. Wer diese fünf Begriffe kennt, kann jedes Jail lesen:
| Begriff | Bedeutung | Default (Debian/Ubuntu) |
|---|---|---|
maxretry |
Fehlversuche bis zur Sperre | 5 |
findtime |
Zeitfenster, in dem gezählt wird | 10m |
bantime |
Dauer der Sperre | 10m |
filter |
Regex-Satz unter /etc/fail2ban/filter.d/ |
sshd.conf |
banaction |
Firewall-Befehl beim Bannen | iptables-multiport |
Der Ablauf vom Logeintrag bis zur Firewall-Regel:
graph TD
A["sshd: Failed password for invalid user"] --> B["systemd-journal oder /var/log/auth.log"]
B --> C["Filter /etc/fail2ban/filter.d/sshd.conf"]
C -->|Regex trifft| D{"maxretry innerhalb findtime erreicht?"}
D -->|nein| E["Zähler erhöhen"]
D -->|ja| F["banaction: nftables/iptables-Regel setzen"]
F --> G["IP für bantime blockiert"]
G --> H{"IP bereits mehrfach gebannt?"}
H -->|ja| I["recidive-Jail: Langzeitsperre"]
Voraussetzungen
- Ein Linux-Server mit Debian 12 oder Ubuntu 24.04, zum Beispiel eine skalierbare Cloud-VPS von centron
- Ein Benutzerkonto mit
sudo-Rechten - Ein zweiter Zugangsweg zum System, etwa die Konsole im Provider-Panel. Ohne diesen Rettungsweg wird jede Fehlkonfiguration von SSH oder fail2ban zum Totalausfall des Zugriffs
- Die aktuelle öffentliche IP-Adresse deines Arbeitsplatzes, ermittelbar mit
curl -4 ifconfig.co
fail2ban installieren
fail2ban liegt in den Standard-Repositories beider Distributionen. Debian 12 und Ubuntu 24.04 liefern Version 1.0.2.
$ sudo apt update
$ sudo apt install fail2ban
$ fail2ban-server --versionAuf Systemen, die ausschließlich ins systemd-Journal loggen, benötigt fail2ban zusätzlich die Python-Bindings:
$ sudo apt install python3-systemdDer Dienst startet nach der Installation automatisch. Prüfe den Zustand, bevor du weiterkonfigurierst:
$ sudo systemctl enable --now fail2ban
$ sudo systemctl status fail2ban --no-pagerPassende Infrastruktur bei centron
Zum Mitmachen braucht es keine eigene Hardware: ccloud³ VMs mit vollem Root-Zugriff, stundengenau abgerechnet und in Sekunden startklar. Cloud-Server mieten →
Das sshd-Jail in jail.local konfigurieren
Bearbeite niemals /etc/fail2ban/jail.conf. Diese Datei gehört dem Paket und wird bei Updates überschrieben. Eigene Werte gehören nach /etc/fail2ban/jail.local oder in eine Datei unter /etc/fail2ban/jail.d/.
$ sudo nano /etc/fail2ban/jail.localInhalt:
[DEFAULT]
# Eigene Netze niemals sperren
ignoreip = 127.0.0.1/8 ::1 <deine-admin-ip>/32
bantime = 4h
findtime = 10m
maxretry = 5
# Log-Quelle: systemd-Journal statt Datei
backend = systemd
[sshd]
enabled = true
port = ssh
maxretry = 4
bantime = 8hErsetze <deine-admin-ip> durch die feste IP-Adresse, von der aus du administrierst. Ohne festen Anschluss lässt du den Eintrag weg und verlässt dich auf die Panel-Konsole als Rettungsweg.
Wichtig zu den Optionen:
port = sshlöst über/etc/servicesauf Port 22 auf. Läuft dein sshd auf einem anderen Port, trage die Nummer direkt ein, etwaport = 2222.enabled = trueist entscheidend. In der ausgeliefertenjail.confist dassshd-Jail auf Debian zwar vorbereitet, aber nicht in jeder Konstellation aktiv.backend = systemdliest das Journal. Das ist die robustere Wahl, weil viele Minimal-Images keinrsyslogund damit kein/var/log/auth.logmehr installieren.
Übernimm die Konfiguration:
$ sudo fail2ban-client reloadLog-Backend richtig wählen
Ob das gewählte Backend Treffer liefert, testest du direkt gegen den Filter. Der Befehl liest das Journal und wendet die sshd-Regexe darauf an:
$ sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.confAm Ende der Ausgabe steht unter Results die Zahl der Lines und der Matched Zeilen. Zeigt Matched dauerhaft 0, obwohl im Journal Fehlversuche stehen, passt das Backend oder der Filter nicht.
Wiederholungstäter mit dem recidive-Jail sperren
Das recidive-Jail liest das fail2ban-eigene Log und sperrt IP-Adressen, die bereits mehrfach gebannt wurden, deutlich länger. Ergänze in /etc/fail2ban/jail.local:
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
backend = auto
findtime = 1d
bantime = 1w
maxretry = 3Wer dreimal innerhalb eines Tages gebannt wurde, ist danach eine Woche draußen. Die Regel greift unabhängig davon, welches Jail die Sperre ausgelöst hat.
Wie lange sollte die bantime sein?
Eine bantime von vier bis acht Stunden bremst automatisierte Scanner wirksam aus, ohne dass ein Kollege nach vier Tippfehlern einen ganzen Arbeitstag ausgesperrt bleibt. Die dauerhafte Sperre bleibt dem recidive-Jail vorbehalten.
Die in vielen Anleitungen empfohlene Einstellung bantime = -1 sperrt permanent. Das klingt gründlich, erzeugt aber über Monate zehntausende Firewall-Regeln und damit messbare Latenz im Paketpfad. Wer trotzdem eskalieren will, nutzt statt der Dauersperre die eingebaute Verlängerung:
[DEFAULT]
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 5wMit bantime.increment verdoppelt fail2ban die Sperrdauer bei jedem erneuten Ban derselben IP-Adresse, gedeckelt durch bantime.maxtime. Diese Option existiert seit fail2ban 0.11 und ist in 1.0.2 verfügbar.
Den SSH-Dienst selbst härten
fail2ban ersetzt keine saubere SSH-Konfiguration, es reduziert nur das Rauschen. Der eigentliche Schutz gegen Brute-Force ist die abgeschaltete Passwort-Anmeldung. Auf Ubuntu 22.10 und neuer sowie auf Debian 12 liest sshd zusätzliche Dateien aus /etc/ssh/sshd_config.d/ ein. Lege dort eine eigene Datei an, statt die Hauptkonfiguration zu verändern:
$ sudo nano /etc/ssh/sshd_config.d/99-hardening.confPasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
MaxAuthTries 3
AllowUsers <dein-benutzername>Bevor du den Dienst neu startest, prüfe die Syntax. Ein Fehler hier kostet dich den Zugang:
$ sudo sshd -t
$ sudo systemctl reload sshHinterlege deinen öffentlichen Schlüssel vorher mit ssh-copy-id und teste die Anmeldung in einer zweiten, parallel geöffneten Sitzung. Erst wenn die neue Sitzung steht, schließt du die alte.
Verifikation
Prüfe zuerst, welche Jails überhaupt laufen:
$ sudo fail2ban-client status
Status
|- Number of jail: 2
`- Jail list: recidive, sshdDann die Details des SSH-Jails:
$ sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 417
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 6
|- Total banned: 58
`- Banned IP list: 203.0.113.24 198.51.100.7Total failed steigt bei einem produktiven Server auf einer öffentlichen IP innerhalb weniger Stunden dreistellig. Bleibt der Wert bei 0, greift der Filter nicht.
Dass die Sperre tatsächlich in der Firewall landet, kontrollierst du auf der Paketfilter-Ebene. Debian 12 und Ubuntu 24.04 nutzen iptables-nft, die Regeln sind also im nftables-Ruleset sichtbar:
$ sudo nft list ruleset | grep -A5 f2b-sshd
$ sudo iptables -S | grep f2bEine einzelne IP-Adresse entsperrst du gezielt:
$ sudo fail2ban-client set sshd unbanip 203.0.113.24Troubleshooting
Das Jail zeigt dauerhaft Total failed: 0. In den meisten Fällen stimmt die Log-Quelle nicht. Auf Systemen ohne rsyslog existiert /var/log/auth.log nicht, das Datei-Backend läuft dann ins Leere. Setze backend = systemd und installiere python3-systemd. Wechselt der Dienst danach in den Fehlerzustand, zeigt journalctl -u fail2ban -n 50 --no-pager die konkrete Ursache.
Der Dienst startet nicht mit Failed to access socket path. Ein abgestürzter Prozess hat die Socket-Datei liegen lassen. Stoppe den Dienst, entferne /var/run/fail2ban/fail2ban.sock und starte neu.
Du hast dich selbst ausgesperrt. Verbinde dich über die Konsole des Provider-Panels und hebe die Sperre mit fail2ban-client set sshd unbanip <deine-ip> auf. Trage die Adresse anschließend in ignoreip ein. Für Server, die du regelmäßig unter wechselnden IP-Adressen administrierst, ist ein zweiter Verwaltungszugang über eine zusätzliche Cloud-VM als Sprungpunkt die stabilere Lösung als eine lange ignoreip-Liste.
Sperren verschwinden nach einem Reboot. fail2ban stellt aktive Bans aus /var/lib/fail2ban/fail2ban.sqlite3 wieder her, sofern dbfile gesetzt und dbpurgeage größer als die bantime ist. Bei sehr langen Sperren aus dem recidive-Jail erhöhst du dbpurgeage in /etc/fail2ban/fail2ban.local entsprechend.
Fazit
Mit einem eigenen sshd-Jail in /etc/fail2ban/jail.local, einer realistischen bantime und dem recidive-Jail für Wiederholungstäter reduzierst du den Brute-Force-Lärm auf deinem Server um Größenordnungen. Kontrolliere nach jeder Konfigurationsänderung mit fail2ban-client status sshd, ob der Filter noch Treffer liefert: ein Jail, das nichts zählt, sperrt auch nichts.
Testen Sie Ihr Setup auf ccloud³
Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.