Seit mehr als 20 Jahren betreibe ich nun Wikiserver und ebenso lang ist mein Kampf gegen Bots und Crawler, welche die Verfügbarkeit meines Wikis bedrohen. Die von mir verwendete Wiki-Engine Foswiki ist nicht besonders effizient und so reagiert mein Wikiserver allergisch, wenn zu viele Abfragen gleichzeitig eingehen. Es ist nun ja aber leider nicht so, dass der Inhalt meines Servers so viele Menschen interessieren würde, dass er unter der Last der Anfragen zusammenbrechen würde…
Es sind andere Computer, die maschinell auf meinen armen kleinen Wikiserver einhämmern, bis ihm der Speicher ausgeht: Früher waren es vor allem Suchmaschinen und Hacking-Versuche, heute kommen noch die gierigen Datensammler für Large Language Models dazu, die ohne Erbarmen alle von Menschen geschriebenen Texte einsammeln wollen, bevor das Internet selbst von computergenerierten Texten verseucht ist.
Während sich etablierte Suchmaschinen und brave GMLS-Crawler an den robots.txt-Standard halten (in welchem ich darum bitte, höchstens alle 15 Sekunden eine Seite abzurufen), machen dies wenigere seriöse Anbieter und natürlich Hacker nicht. Da mein Wiki zusammenklappt, wenn zu viele Salven von Seitenanfragen hintereinander kommen, brauche ich dafür Schutzmassnahmen in Form von Filtern.
Ich setze zu diesem Zweck die Filtersoftware Fail2ban ein, die das Definieren verschiedener Filter und sogenannter Gefängnisse erlaubt.
Mit einem Hacking-Filter halte ich mir die üblichen Scanversuche vom Leib (bzw. von Server), die oft in wenigen Sekunden Hunderte von Testabfragen durchführen, ob bestimmte Software auf einem Server installiert ist und diese dann gezielt angegriffen werden könnte. Hier die Sammlung an Mustern, die sich bei mir bewährt hat:
^.* .*"GET /.git.*$ ^.* .*"GET /_phpmyadmin.*$ ^.* .*"GET /admin.*$ ^.* .*"GET /alive.php.*$ ^.* .*"GET /app.*$ ^.* .*"GET /?phpshells.*$ ^.* .*"GET /backend.*$ ^.* .*"GET /backup.*$ ^.* .*"HEAD /backup.*$ ^.* .*"GET /cgi-bin.*$ ^.* .*"GET /core.*$ ^.* .*"GET /credentials.*$ ^.* .*"GET /dev/.*$ ^.* .*"GET /home/.*$ ^.* .*"GET /images.*$ ^.* .*"GET /mysql/.*$ ^.* .*"GET /php.*$ ^.* .*"GET /old.*$ ^.* .*"HEAD /old.*$ ^.* .*"GET /sql.*$ ^.* .*"GET /test/.*$ ^.* .*"GET /wp.*$ ^.* .*"HEAD /wp.*$ ^.* .*"GET /wordpress.*$ ^.* .*"HEAD /wordpress.*$
Aggressive Crawler sind schwieriger zu erkennen, da auch normale Besucher:innen einige Abfragen in kurzer Zeit durchführen, weil sie z.B. bei einer Wikiseite auch noch alle Bilder benötigen. Der Schlüssel liegt darin, dafür nicht das normale Logfile des Webservers zu nutzen, sondern das Eventlog von Foswiki, weil dieses pro Seitenabruf nur eine Zeile enthält (Bilder, CSS und JS-Dateien werden da nicht protokolliert). Somit habe ich jetzt einen eigenen Fail2ban-Filter erstellt:
[Definition] failregex = ^.* guest | view |[^|]+|[^|]+| datepattern = ^| %%Y-%%m-%%dT%%H:%%M:%%SZ ignoreregex =
Mit diesem Filter ist jeder Seitenabruf eines nicht eingeloggten Users ein Ereignis für Fail2ban. Darauf aufbauend kann ich nun ein Fail2ban-Gefängnis definieren:
[wiki-event-log] enabled = true filter = wiki-event-log logpath = /var/www/foswiki/working/logs/events.log maxretry = 5 findtime = 15
Ins Gefängnis kommt, wer ohne sich einzuloggen innerhalb von 15 Sekunden 5 Wikiseiten abruft, für die bei mir eingestellte Standardzeit von 10 Minuten geblockt wird. Ja, das könnten Sie ausprobieren, wenn Sie diese Seite jetzt 5 Mal reloaden…