Bei fail2ban handelt es sich um einen hilfreichen Serverdienst, der ständig diverse Log-Dateien analysieren und auf Basis der Logs Aktionen ausführen können.

Ich sehe meinen privaten Server schon seit geraumer Weile "leichten Angriffen" ausgesetzt, wo jeden Tag zig Requests auf die URLs http://meinheimserver.apfel-z.net/phpMyAdmin/, http://meinheimserver.apfel-z.net/wp-admin/, http://meinheimserver.apfel-z.net/pma/ etc rein kommen.
Hier ist jemand auf der Suche nach phpMyAdmin, WordPress & Co, um Sicherheitslücken auszunutzen und sich Zugriff auf das System zu verschaffen.
Abgesehen davon, dass phpMyAdmin unter ganz anderer URL zu finden und per .htaccess abgesichert ist, ist die ganze Geschichte doch leicht beunruhigend.

Zu finden sind diese Anfragen übrigens direkt in der Log-Datei /var/log/apache2/error_log oder in der gleichnamigen Log-Datei über das Log-Auswertungsprogramm "Konsole".
In meinem Fall waren hier täglich Einträge á la

[error] [client 186.204.131.116] File does not exist: /Library/WebServer/Documents/meinheimserver.apfel-z.net/cgi

zu finden. Jeden Tag natürlich mit anderer IP.

fail2ban behält diese und andere Log-Dateien im Auge und lässt sich dazu verwenden, Abwehr-Aktionen auszuführen, falls eine oder mehrere Einträge dieser Art im Log auftauchen.

Man darf allerdings nicht vergessen, dass zwischen "Feststellen, dass sich etwas im Log geändert hat", "schauen, was es für neue Einträge im Log gibt", Auswerten und Aktionen ausführen, etwas Zeit ins Lande gehen kann.
Nach meinen ersten Tests zwar etwas weniger, als eine Sekunde, aber in der Zeit können natürlich viele Anfragen über den Server hereinbrechen. Zum Beispiel gingen bei der ersten Attacke nach Installation von fail2ban ganze 3 Requests vom Angreifer durch, bis seine IP vom Server gesperrt wurde. Besser, als gar kein Schutz!

Installation & Erstkonfiguration

Ich hatte via macports installiert, aber per HomeBrew oder manuell geht natürlich auch.

Im Folgenden alle Beispiele mit einer MacPorts-Installation. Bei HomeBrew oder manueller Installation werden die Pfade und Befehle zum starten/stoppen abweichen!

sudo port install fail2ban

Falls nun in /opt/local/etc/fail2ban/ noch keine Datei jail.local vorhanden ist, die jail.conf duplizieren:

sudo cp jail.conf jail.local

Bei einem Update würde jail.conf überschrieben werden, deshalb arbeiten wir mit jail.local

Nun sicher gehen, dass für die Pfad-Variablen osx-Pfade geladen werden:

[INCLUDES]
before = paths-osx.conf

Unter DEFAULT können noch weitere Konfigurationen vorgenommen werden. Welche IP-Adressen nie gebannt werden sollen (empfohlen: Alles aus dem lokalen Netzwerk) und wie lange die Bann-Dauer sein soll oder ab wie vielen Fehlversuchen überhaupt gebannt werden soll:

[DEFAULT]
ignoreip  = 127.0.0.1/8 192.168.178.0/24 # 192.168.178er-Netz ignorieren
bantime   = 3600 # für 1 Stunde bannen
findtime  = 600
maxretry  = 5 # Falls innerhalb von 600 Sekunden 5 Fehlversuche

Am Ende der Datei werden bereits viele Jails vorhanden sein, die allerdings nicht aktiv sind. Für den Anfang löschen wir mal alle raus und behalten nur jenen in jail.local, der dafür verantwortlich ist, dass Anfragen an nicht existierende Dateien/PHP-Skripte zukünftig geblockt werden. Das ist der apache-noscript-Jail:

[apache-noscript]
enabled  = true       # Wichtig, damit der Jail verwendet wird
port     = http,https
action   = pf         # Wichtig, damit pf statt ipfw verwendet wird
logpath  = %(apache_error_log)s # Prüfen, ob der Pfad in paths-osx.conf mit der Realität übereinstimmt

Wichtig ist, wenn man aus der Vorlage Jails übernimmt, noch das enabled = true hinzuzufügen, damit der Jail auch tatsächlich verwendet wird.
Wie ein Jail wie etwa apache-noscript ausgelöst wird, ist übrigens in der Datei filter.d/apache-noscript.conf zu sehen. Der Name in eckigen Klammern ist der Verweis zu dieser .conf-Datei.
Kurz gesagt wird in der Log-Datei geschaut, ob es Einträge mit "File does not exist" oder "script not found or unable to stat" gibt und falls der Fall die action.d/pf.conf getrigert.

Starten wir fail2ban nun:

sudo port load fail2ban

Noch eine kleine Anpassung bei der pf -Firewall des Macs: fail2ban erstellt eine Bann-Table namens fail2ban, die pf nicht kennt und nicht weiß, was es damit anfangen soll.

sudo nano /etc/pf.conf

Am Ende hinzufügen:

table <fail2ban> persist
block drop log quick from <fail2ban> to any

Und pf neu starten:

sudo pfctl -d # (disable)
sudo pfctl -f /etc/pf.conf
sudo pfctl -e # (enable)

Jails testen

Ich öffne im Browser die nicht existierende Seite meinheimserver.apfel-z.net/info.php und lade mehrmals neu (was zu mehreren Anfragen an den Webserver führt).
Im Apache-Log sollten dann mehrere Zeilen wie etwa diese hier auftauchen:

[php:error] [pid 87518] [client 129.249.170.132:51355] script '/var/www/info.php' not found or unable to stat

...und das sollte fail2ban triggern und die IP 129.249.170.132 bannen. Prüfen wir, ob dem so ist:

sudo fail2ban-client status apache-noscript

Status for the jail: apache-noscript
|- Filter
|  |- Currently failed: 1
|  |- Total failed:     51
|  `- File list:        /opt/local/var/log/apache2/error_log
`- Actions
   |- Currently banned: 1
   |- Total banned:     5
   `- Banned IP list:   129.249.170.132

Tatsächlich. Die IP 129.249.170.132 wird gebannt!

Noch kurz geprüft, ob die Info auch bei der pf -Firewall angekommen ist:

sudo pfctl -t fail2ban -T show

Hier sollte in der Ausgabe ebenfalls die gebannte IP-Adresse auftauchen.
Falls nicht:

  • Wurde /etc/pf.conf angepasst und pf neu gestartet?
  • Ist in der Jail action = pf vorhanden?
  • Zeigt der Befehl sudo pfctl -s Tables eine Table fail2ban an?
  • Enthält /opt/local/etc/fail2ban/action.d/pf.conf den korrekten Bann-Befehl actionban = /sbin/pfctl -t <tablename> -T add <ip>/32 ?
  • Oder verwendet der Mac eine andere Firewall als pf?

Ruft man im Browser die nicht vorhandene Seite ein weiteres Mal auf, sollte keine Antwort mehr vom Server kommen und der Browser nach einiger Zeit einen Netzwerk-Zeitüberschreitungs-Fehler anzeigen.

Die IP wieder freigeben (wenn man nicht 1 Stunde warten möchte, bis sie wieder automatisch freigegeben wird):

sudo fail2ban-client set apache-noscript unbanip 129.249.170.132

Wenn dies funktioniert, ist es Zeit, noch weitere Jails, wie etwa apache-badbots oder php-url-fopen zu aktivieren.

fail2ban neustarten

Nach einer Änderung der jail.local sollte fail2ban neu gestartet werden – Befehle weichen bei Homebrew-Installation ab!
sudo port unload fail2ban
sudo port load fail2ban