Wer eine WordPress-Multisite betreibt, kennt das Problem: Das access.log quillt über vor automatisierten Scans nach .env-Dateien, wp-login.php oder exotischen CGI-Schnittstellen. Plugins wie Wordfence leisten tolle Arbeit und blockieren diese Zugriffe mit einem 403 Forbidden.
Doch das Problem bleibt: Jeder dieser Zugriffe startet den PHP-Prozess und belastet die Datenbank. Das Ziel muss also sein, diese Angreifer bereits an der System-Firewall (UFW/Iptables) zu stoppen. Hier kommt Fail2ban ins Spiel.
Die Herausforderung: Das Log-Format bei Multisites
Bei Standard-Installationen steht die IP-Adresse meist am Anfang der Logzeile. Nutzt man jedoch Panels wie Froxlor oder spezielle Apache-VHosts, steht oft der Domainname (VHost) an erster Stelle:
example-site.com 146.193.240.135 - - [10/Apr/2026:11:51:52 +0200] ...
Standard-Filter von Fail2ban scheitern, da sie die IP-Adresse direkt am Zeilenanfang (^<HOST>) erwarten. Man muss den Regulären-Ausdruck also anpassen.
Das „Scanner-Jail“ für 404 und 403 Fehler
Wenn Wordfence einen Bot blockiert (403) oder ein Bot nach Dateien sucht, die es nicht gibt (404), soll die IP komplett gesperrt werden.
Schritt 1: Filter erstellen
Man erstellt eine Datei /etc/fail2ban/filter.d/apache-404-403.conf:
[Definition]
# Der Trick: ^\S+ überspringt den Domainnamen am Anfang
failregex = ^\S+ <HOST> - - \[.*\] "(GET|POST|HEAD) .* HTTP\/.*" (404|403|400)
ignoreregex = .*robots.txt.*|.*favicon.ico.*|.*apple-touch-icon.*
Schritt 2: Jail aktivieren
In /etc/fail2ban/jail.local fügt man das Jail hinzu. Dank Wildcards (*access.log) kann man alle VHosts gleichzeitig überwachen:
[apache-404-403]
enabled = true
port = http,https
filter = apache-404-403
logpath = /var/log/apache2/*access.log
maxretry = 6
findtime = 300
bantime = 86400
banaction = ufw
Bad Bots: Alte Filter modernisieren
Viele Standard-Listen für „Bad Bots“ sind veraltet oder könnten aktualisiert werden. Zudem existiert das selbe VHost-Problem am Zeilenanfang. Ein robuster Regulärer-Ausdruck für solche Logs sieht so aus:
failregex = ^\S+ <HOST> \S+ \S+ \[.*\] "(?:GET|POST|HEAD) \S+ HTTP\/\d\.\d" \d+ (?:-|\d+) "[^"]*" "(?:.*)(?:libwww-perl|Python-urllib|Go-http-client|MJ12bot|AhrefsBot)(?:.*)"$
Der Filter fängt automatisierte Skripte ab, die sich nicht als echte Browser ausgeben.
Vertrauen ist gut, Testen ist besser: fail2ban-regex
Bevor man Fail2ban neu startet, sollte man den Filter immer gegen ein echtes Log testen. Das verhindert, dass man blind konfiguriert:
fail2ban-regex /var/log/apache2/dein-web-access.log /etc/fail2ban/filter.d/apache-404-403.conf
Erhältst man hier „Hits“, weißt man, dass der Reguläre-Ausdruck die IP-Adressen korrekt extrahiert.
Das Problem der langen IP-Listen
Ein wichtiger Aspekt beim Einsatz von Fail2ban (besonders auf älteren Systemen) ist die Performance der Firewall.
- Ressourcenverbrauch: Jede gesperrte IP ist ein Eintrag in der Firewall-Tabelle. Bei tausenden Sperren kann der Netzwerk-Stack langsamer werden.
- Die Lösung – Recidive Jail: Anstatt IPs für immer zu sperren, nutzt man ein „Recidive“ (Wiederholungstäter) Jail. Wer dreimal für 24 Stunden gesperrt wurde, landet automatisch für eine Woche in der Sperre. Das hält die „aktive“ Liste der kurzzeitigen Sperren klein und effizient.
- Ipset: Bei extrem hohem Aufkommen sollte man Fail2ban so konfigurieren, dass es
ipsetnutzt. Das erlaubt es dem Kernel, hunderttausende IPs in Millisekunden zu prüfen.
Die Kombination aus Wordfence (für die Logik innerhalb von WordPress) und Fail2ban (für die harte Blockade auf Netzwerkebene) ist sehr praktisch. Durch die Anpassung der Regulären-Ausdrücke an das eigene Log-Format stellt man sicher, dass Angreifer nicht durch das Raster fallen.