Wer einen Mailserver betreibt, kennt das Problem, dass man neben den normalen E-Mails auch irgendwann höhere Mengen an Spam erhält. Bei dem von mir verwalteten Webserver mit Kerio Connect sind es so ungefähr 98% aller SMTP-Anfragen, die mit Spam zu tun haben.
Natürlich bietet Kerio Connect hier schon eine Auswahl an Antispam-Mechanismen an. So greift ein Spamassassin ein sowie verschiedene individuell zu gestaltende Spamfilter und Blacklist-Abfragen. Diese Möglichkeiten sollte man auf jeden Fall auch nutzen.
Das ändert aber nichts daran, dass der Mailserver immer wieder die gleichen Anfragen von den denselben Spam-Servern annehmen und verarbeiten muss. Hinzu kommen noch Script-Kiddies, die irgendwann auf den Webmailer aufmerksam werden und dort mit Exploit-Scripts versuchen, irgendwie Zugriff zu erlangen.
An dieser Stelle kommt dann das Tool fail2ban ins Spiel. Jedenfalls wenn man den Kerio Connect Server nicht unter Windows, sondern unter einem Linux laufen lässt.
Vorbereitung
Zunächst sollte man Kerio Connect darauf vorbereiten, mit fail2ban zu arbeiten. Denn das Auslesen der Standard-Logs von Kerio Connect führt zu Fehlern. Die Logs müssen also auf SYSLOG
umgeleitet werden. Als Facility habe ich hier das Mail System ausgewählt. Die Logs landen dann kumuliert in /var/log/maillog
.
Welche Log-Dateien alle ausgewertet werden, ist natürlich jedem selbst überlassen. Für mich sind nur das Security-Log und natürlich das Spam-Log von Interesse.
Damit SYSLOG auch die Daten von Kerio annimmt, war folgende Änderung in /etc/rsyslog.conf
nötig:
# Provides UDP syslog reception
$ModLoad imudp.so
$UDPServerRun 514
fail2ban installieren
fail2ban wird über den Paketmanager mit yum install fail2ban
bzw. apt-get install fail2ban
installiert. Die Konfiguration findet man anschließend wie gewohnt unter /etc/fail2ban
.
fail2ban konfigurieren
Da die vorinstallierten .conf-Dateien bei einem Dist-Upgrade überschrieben werden können, empfiehlt es sich, eine entsprechende .local-Datei anzulegen. Diese wird nach der .conf-Datei eingelesen und überschreibt konkurrierende Einstellungen. Bspw. würde die Einstellung bantime = 600
in der jail.conf von der Einstellung bantime = 3600
in der jail.local überschrieben werden.
In der Datei /etc/fail2ban/jail.local
sollte unter „ignoreip“ unbedingt die Netzmaske des lokalen Netzes hinzugefügt werden, damit lokale Clients nicht versehentlich gesperrt werden, falls sie eine Aktion von fail2ban auslösen.
Grundsätzlich ist fail2ban damit einsatzbereit. Damit fail2ban aber seinen Dienst aufnehmen kann, müssen Filter eingerichtet werden.
fail2ban Filter
Filter werden als .conf-Datei unter /etc/fail2ban/filter.d/
angelegt. Dabei hat die .conf-Datei denselben Namen wie der Filter. (Also Filter „spam-attack“ = „spam-attack.conf“). Ein Filter hat grundsätzlich folgenden Aufbau:
[Definition] # Beschreibung: failregex = ignoreregex =
Mit der Raute (#) leitet man einen Kommentar ein. Vorhandensein muss auf jeden Fall ein Wert in failregex
zusammen mit der fail2ban-Variable <HOST>
. Anhand dieses Wertes kann fail2ban dann in der Log-Datei nach Übereinstimmungen suchen. Hier kann man komplexe Regex verwenden oder ganz simple Strings. Beispiele folgen weiter unten.
Ist der Filter erstellt, muss er noch in die jail.local eingetragen werden. Hier ein Beispiel:
[spam-attack] # Filter mit true oder false an bzw. ausschalten enabled = true # Filtername filter = spam-attack # was soll passieren, wenn der Filter zutrifft action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] # auf welche Log-Datei wird der Filter angewendet logpath = /var/log/maillog # wie viele Einträge pro Host sind maximal zulässig, bevor der Filter angewendet wird maxretry = 0 # Wie lang soll der Host gebannt werden (in Sekunden) bantime = 3600
Testen
Bevor man die Filter in die freie Wildbahn entlässt, sollte man sie natürlich testen. Das geht recht einfach mit fail2ban-regex [Logdatei] [Filter]
, Beispiel:
fail2ban-regex /var/log/maillog /etc/fail2ban/filter.d/spam-attack.conf
Um auch die Ausnahme (ignoreregex) zu testen, muss diese noch separat angegeben werden. Beispiel:
fail2ban-regex /var/log/maillog /etc/fail2ban/filter.d/spam-attack.conf /etc/fail2ban/filter.d/spam-attack.conf
Alternativ kann auch direkt die Regexpression getestet werden. Beispiel:
fail2ban-regex /var/log/maillog '<HOST> rejected: directory harvest attack'
Host entsperren
Hat man versehentlich einen Host mit fail2ban geblockt, was insbesondere in der Anfangsphase noch passieren kann, wenn man die Filter auf seine Bedürfnisse einstellt, besteht natürlich das Bedürfnis, den Host wieder freizugeben. Ein iptables -D INPUT -s 1.2.3.4 -j DROP
funktioniert leider nicht mit den Regeln, die fail2ban in iptables eingetragen hat. Deshalb ist man zunächst darauf angewiesen, den fail2ban Jail herauszufinden, der mit dem entsprechenden Filter für den DROP (oder REJECT) der betroffenen IP sorgt. In einem Blog habe ich den Befehl fail2ban-client status
gefunden, der mir aber nur die vorhandenen aktiven Jails anzeigt, nicht jedoch, welcher Jail eine bestimmte IP geblockt hat. Das ist also nutzlos.
Stattdessen müssen wir wissen, dass fail2ban standardmäßig seine eigenen Logs nach /var/log/messages
schreibt. Mit einem less /var/log/messages | grep 1.2.3.4
kann ich herausfinden, welcher Jail für das Blocken der IP 1.2.3.4 verantwortlich ist. Je nach dem wie das Logrotate für messages eingestellt ist und wie weit man in die Vergangenheit zurück muss, ist ersatzweise zless /var/log/messages* | grep 1.2.3.4
nötig.
Hat man nun den verantwortlichen Jail gefunden, hilft folgender Befehl: fail2ban-client set [Jail] unbanip 1.2.3.4
. Ersetze hier das [Jail]
mit dem Namen des Jails. Zum Beispiel: fail2ban-client set spam-attack unbanip 1.2.3.4
.
Probleme von fail2ban
Es gibt zum Zeitpunkt dieses Artikels leider keine Möglichkeit, fail2ban neu zu starten, ohne dass alle geblockten IP-Adressen aus iptables gelöscht werden. Es gibt behelfsmäßige Workarounds, die aber auch nicht wie gewünscht funktionieren (ein automatischer Unban ist dann nicht mehr möglich), weshalb ich davon absehe, darauf einzugehen.
Beispiele
Im Folgenden stelle ich meine ungefähre Konfiguration vor. Sie sollten soweit eigentlich selbsterklärend sein. Man kann natürlich alle fail2ban-Filter in einen einzigen Filter packen, aber wer es lieber etwas aufgeräumt mag, kann für jeden Verwendungszweck einen eigenen Filter definieren. Dann fällt es später möglicherweise auch leichter, Probleme/Fehler zu finden.
/etc/fail2ban/jail.local
[DEFAULT] ignoreip = 127.0.0.1/8 172.16.0.0/16 [w00tw00t] enabled = true filter = w00tw00t action = iptables-multiport[name=HTTP, port="80,443", protocol=tcp] logpath = /var/log/maillog maxretry = 0 bantime = 86400 [spam-blacklisted] enabled = true filter = spam-blacklisted action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 0 bantime = 604800 [spam-harvest] enabled = true filter = spam-harvest action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 0 bantime = 604800 [spam-missingauth] enabled = true filter = spam-missingauth action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 3 bantime = 86400 [spam-rejected] enabled = true filter = spam-rejected action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 0 bantime = 86400 [spam-relay] enabled = true filter = spam-relay action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 3 bantime = 3600 [spam-smtp] enabled = true filter = spam-smtp action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 0 bantime = 604800 [spam-unknownrcpt] enabled = true filter = spam-unknownrcpt action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 3 bantime = 3600 [spam-detected] enabled = true filter = spam-detected action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] logpath = /var/log/maillog maxretry = 3 bantime = 86400 [kerio-auth] enabled = true filter = kerio-auth action = iptables-multiport[name=SMTP, port="25,465,587", protocol=tcp] iptables-multiport[name=HTTP, port="80,443", protocol=tcp] logpath = /var/log/maillog maxretry = 1 bantime = 86400
Die dazugehörenden Filter sehen wie folgt aus:
/etc/fail2ban/filter.d/spam-blacklisted.conf
[Definition] #Host is on Blacklist failregex = IP address <HOST> found in DNS blacklist NiX Spam IP address <HOST> found in DNS blacklist Barracuda IP address <HOST> found in local blacklist ignoreregex =
/etc/fail2ban/filter.d/spam-detected.conf
[Definition] #Spam detected with value >6 failregex = Message detected as spam.*(6\.[0-9][0-9]|7\.[0-9][0-9]|8\.[0-9][0-9]|9\.[0-9][0-9]).*Sender IP: <HOST> ignoreregex = Message detected .* ,
/etc/fail2ban/filter.d/spam-harvest.conf
[Definition] #Harvest Attacks failregex = <HOST> rejected: directory harvest attack Directory harvest attack from <HOST> detected ignoreregex =
/etc/fail2ban/filter.d/spam-missingauth.conf
[Definition] #Rejected by missing authentification failregex = Message from IP address <HOST> was rejected because of missing authentification for local domain sender ignoreregex =
/etc/fail2ban/filter.d/spam-rejected.conf
[Definition] #Spam rejected hosts - (score >= block score, custom block rule, etc.) failregex = Message rejected .* Sender IP: <HOST>, ignoreregex = Message rejected .* , Sender IP: <HOST>
/etc/fail2ban/filter.d/spam-relay.conf
[Definition] #Hosts trying to relay failregex = Relay attempt from IP address <HOST>, mail from .* rejected ignoreregex =
/etc/fail2ban/filter.d/spam-smtp.conf
[Definition] #SMTP without greeting failregex = SMTP Spam attack detected from <HOST>, ignoreregex =
/etc/fail2ban/filter.d/spam-unknownrcpt.conf
[Definition] #Messages to unknown recipients failregex = Attempt to deliver to unknown recipient <.*(meinedomain\.tld|meine-andere-domain\.tld)>,.*IP address <HOST> ignoreregex =
/etc/fail2ban/filter.d/w00tw00t.conf
[Definition] #Woot woot messages and hacking attempts failregex = HTTP request from <HOST> \(GET .*/(w00tw00t|wootwoot|WootWoot|WooTWooT|tmUnblock|myadmin|PHPMYADMIN|PMA|bbs|cpadmin|mysqlmanager|mysqladminconfig|phpTest|phpMyAdmin|pma|MyAdmin|phpmyadmin|cgi-bin|muieblackcat|scripts/setup.php) <HOST>.*\(\s*\)\s*\{[^"]*\}\s*\;[^"]+ HTTP request from <HOST> \(POST http://.* ignoreregex =
/etc/fail2ban/filter.d/kerio-auth.conf
[Definition] #Failed Login-attempts by unknown users failregex = User .*@meinedomain.de doesn't exist. Attempt from IP address <HOST>. ignoreregex =