Vom Terminal-Skript zum übersichtlichen HTML-Report
Wie ich in meinem letzten Artikel über Fail2ban bereits beschrieben habe, ist das Tool sehr hilfreich und so eine Art digitaler Türsteher für Linux-Systeme. Es scannt Logdateien nach böswilligen Mustern und sperrt IP-Adressen, die zu oft an die falsche Tür klopfen.
Damals hatte ich ein kleines Bash-Skript erstellt, das den Status der Jails übersichtlich auf der Kommandozeile ausgibt. Aber: Wer loggt sich schon jeden Morgen manuell ein, nur um den Status zu prüfen? Heute gehen wir etwas weiter und automatisieren das Monitoring.
Viele Wege führen zum Status
Es gibt verschiedene Möglichkeiten, über Fail2ban-Aktivitäten informiert zu bleiben. Jede hat ihre Vor- und Nachteile:
1. Fail2ban-interne Benachrichtigungen
Fail2ban kann von Haus aus E-Mails verschicken (z. B. via sendmail oder mail), sobald eine IP gesperrt wird.
- Vorteil: Man wird sofort alarmiert.
- Nachteil: Bei einem Brute-Force-Angriff quillt das Postfach innerhalb von Minuten über. Man verliert schnell den Überblick.
2. Logwatch
Logwatch ist das Schweizer Taschenmesser für Log-Analysen. Es fasst alle Systemereignisse eines Tages zusammen.
- Vorteil: Extrem umfassend, deckt auch SSH, Apache, Disk-Usage etc. ab.
- Nachteil: Die Berichte sind oft sehr lang und „trocken“. Die Fail2ban-Sektion ist funktional, aber nicht unbedingt intuitiv aufbereitet.
3. Das CLI-Skript
Mein altes Skript lieferte eine farbige Übersicht direkt im Terminal.
- Vorteil: Perfekt, wenn man gerade aktiv am Server arbeitet.
- Nachteil: Null Automatisierung. Keine Historie, wenn man nicht eingeloggt ist.
4. Das neue HTML-Skript per E-Mail
Die „Goldene Mitte“. Einmal täglich kommt eine formatierte Zusammenfassung.
- Vorteil: Dank HTML-Formatierung extrem übersichtlich. Man sieht sofort, welche Jails „aktuell“ sind.
Das Upgrade: Der tägliche HTML-Statusbericht
Warum HTML? Reine Text-Mails stoßen bei langen Listen von IP-Adressen schnell an ihre Grenzen. Die Darstellung wird unübersichtlich, Zeilen brechen hässlich um. Mit HTML können wir Farben (z. B. für aktuell gesperrte IPs) und Badges nutzen. Jede gesperrte IP bekommt einen eigenen kleinen Kasten, was die visuelle Trennung enorm erleichtert.
Das Skript
f2b-email-status.sh
Man trägt noch Absender und Empfänger E-Mail-Adressen ein:
#!/bin/bash
# --- KONFIGURATION ---
RECIPIENT="admin@deine-domain.de"
SUBJECT="Fail2Ban Report: $(hostname) - $(date +'%d.%m.%Y')"
SENDER="fail2ban@$(hostname -f)"
# --- HTML HEADER & STYLES ---
HTML="<html><head><style>
body { font-family: 'Segoe UI', sans-serif; background-color: #f8f9fa; padding: 20px; }
.container { max-width: 800px; margin: auto; background-color: #fff; padding: 25px; border-radius: 10px; border: 1px solid #e1e4e8; }
h2 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th { background-color: #f1f3f5; text-align: left; padding: 12px; border-bottom: 2px solid #dee2e6; }
td { padding: 12px; border-bottom: 1px solid #eee; }
.badge { display: inline-block; background-color: #ebf5fb; color: #2980b9; padding: 2px 8px; margin: 2px; border-radius: 4px; border: 1px solid #d6eaf8; font-family: monospace; font-size: 0.85em; }
</style></head>
<body>
<div class='container'>
<h2>Fail2Ban Sicherheitsbericht</h2>
<table>
<tr><th>Jail</th><th>Aktiv-Fail</th><th>Gesamt-Fail</th><th>Aktuell Gebannt</th><th>Gesamt Gebannt</th></tr>"
# --- DATEN EXTRAHIEREN ---
jails=$(fail2ban-client status | grep "Jail list:" | sed 's/.*Jail list://; s/,//g')
for j in $jails; do
stats=$(fail2ban-client status "$j")
cur_fail=$(echo "$stats" | grep "Currently failed:" | grep -oE '[0-9]+')
tot_fail=$(echo "$stats" | grep "Total failed:" | grep -oE '[0-9]+')
cur_ban=$(echo "$stats" | grep "Currently banned:" | grep -oE '[0-9]+')
tot_ban=$(echo "$stats" | grep "Total banned:" | grep -oE '[0-9]+')
banned_ips=$(echo "$stats" | grep "Banned IP list:" | sed 's/.*Banned IP list://' | sed 's/^[ \t]*//')
html_badges=""
for ip in $banned_ips; do html_badges+="<span class='badge'>$ip</span> "; done
HTML+="<tr><td><strong>$j</strong></td><td>$cur_fail</td><td>$tot_fail</td>
<td><span style='color: #e74c3c; font-weight: bold;'>$cur_ban</span></td><td>$tot_ban</td></tr>"
if [ -n "$html_badges" ]; then
HTML+="<tr><td colspan='5' style='padding: 5px 12px 15px 12px;'>$html_badges</td></tr>"
fi
done
HTML+="</table></div></body></html>"
# --- VERSAND ---
echo "$HTML" | mail -a "Content-Type: text/html; charset=UTF-8" -a "From: $SENDER" -s "$SUBJECT" "$RECIPIENT"
Einrichtung via cron.daily
Damit das Skript jeden Morgen automatisch läuft, nutzen wir den System-Ordner /etc/cron.daily/.
- Verschieben & Umbenennen: Kopiere das Skript dorthin, aber entferne die Dateiendung. Das Tool
run-parts(welches diese Ordner verwaltet) ignoriert Dateien mit Punkten im Namen oft komplett.cp ~/Scripts/f2b-email-status.sh /etc/cron.daily/f2b-email-status - Rechte vergeben:
chmod +x /etc/cron.daily/f2b-email-status
Vertrauen ist gut, Kontrolle ist besser
Bevor ihr euch entspannt zurücklehnt, solltet ihr zwei Dinge prüfen:
1. Funktioniert der Cronjob?
Ihr müsst nicht bis morgen warten. Testet mit run-parts, ob das System euer Skript im Daily-Ordner akzeptiert:
run-parts --test /etc/cron.daily
Erscheint f2b-email-status in der Liste? Dann ist alles bereit.
2. Funktioniert Fail2ban (und das Skript) mit echten Daten?
Um zu sehen, wie gesperrte IPs im Bericht aussehen, kann man manuell eine (eigene, sichere!) IP in eine Jail werfen:
fail2ban-client set sshd banip 1.2.3.4
Danach führt man das Skript manuell aus und schaut ins Postfach. Die IP sollte in einem blauen Badge unter dem „sshd“-Abschnitt erscheinen. (Danach mit unbanip wieder zu befreien!)
Weitere Beiträge
Überblick bei Fail2ban
Wer einen eigenen Server mit SSH-Zugang oder Maildiensten betreibt, kennt das Phänomen: Ein Blick in die Logfiles zeigt hunderte von Anmeldeversuchen aus der ganzen Welt. Hier schlägt die Stunde von Fail2Ban. Doch wie behält man den Überblick, wer gerade „vor der Tür“ steht? Was ist Fail2Ban eigentlich? Fail2Ban ist ein Tool, das Logdateien (z. B.…

