fail2ban mit xt_recent reloaded 1


Hier nun die Ergänzung zu fail2ban mit xt_recent.

Durch fail2ban (ob nun über xt_recent oder kompletten Eintrag in die Firewall) werden IP immer nur geblockt, bis der Server neu gestartet wird.

Daher trage ich die Bans nicht nur in die Firewall, sondern auch in eine mysql-Datenbank ein.

Grundsätzliches
Ich habe mir dazu die Datenbank systemlog erstellt, die zwei Tabellen enthält – eine für die Configs und eine für die Bans. Die Config-Tabelle muss nicht zwingend vorhanden sein, ich habe aber darüber leicht die Möglichkeit, Ban-Zeiten zu verändern, muss nicht ein oder mehrere Scripts anpassen und kann so alle Jails mit einem Rutsch auslesen und in die Firewall eintragen.
Im folgenden lasse ich die Tabelle Config außen vor – für die Interessierte steht der Teil morgen am Ende dieses Posts.

Die Tabelle systemlog.fail2ban enthält mehrere Einträge:
source
port
jail
hits
last_hit

Durch diese Einträge kann ich nicht nur bei einem Neustart alles passend initialisieren, sondern kann auch problemlos Statistiken erstellen lassen.

Setup
mysql einrichten
login into mysql as root and run:

CREATE DATABASE systemlog;
CREATE USER 'systemlog'@'localhost' IDENTIFIED BY 'MYPASSWORD';
GRANT ALL ON systemlog.* TO 'systemlog'@'localhost' IDENTIFIED BY 'MYPASSWORD';
FLUSH PRIVILEGES;
QUIT;

Importiere die Tablen-Struktur:
mysql systemlog < fail2ban.sql

Fail2ban anpassen
Damit jeder Ban nicht nur in xt_recent landet, sondern auch in der entsprechenden Datenbank wird das action-File (‘actionban’) erweitert. Ich nehme als Beispiel iptables.conf.

/etc/fail2ban/action.d/iptables.conf:

actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP

wird zu

actionban = echo +<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "INSERT INTO fail2ban VALUES(INET_ATON('<ip>'),<port>,'fail2ban-<name>',1,now()) ON DUPLICATE KEY UPDATE hits=hits+1;"
actionunban = echo -<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "DELETE FROM fail2ban WHERE source=INET_ATON('<ip>') AND jail='fail2ban-<name>;"

Damit sieht /etc/fail2ban/action.d/iptables.conf jetzt so aus (als Download am Ende verfügbar):


#
# Author: Cyril Jaquier
#
# $Revision: 658 $
#

[Definition]

# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart =
actionstart = sleep `echo ${RANDOM:0:1}`
if [ -z `iptables -L fail2ban-<name> | grep "^Chain fail2ban-<name> "` ]; then /usr/local/sbin/iptables -N fail2ban-<name>; fi
if [ -z `iptables -L INPUT | grep "^fail2ban-<name> "` ]; then /usr/local/sbin/iptables -I INPUT -p <protocol> --dport <port> -j fail2ban-<name>; fi
if [ -z `iptables -L fail2ban-<name> | grep "^DROP .* recent: UPDATE"` ]; then /usr/local/sbin/iptables -I fail2ban-<name> -m recent --name fail2ban-<name> --update --seconds <bantime> -j DROP; fi

# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop =

# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck =

# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionban = echo +<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "INSERT INTO fail2ban VALUES(INET_ATON('<ip>'),<port>,'fail2ban-<name>',1,now()) ON DUPLICATE KEY UPDATE hits=hits+1;"

# Option: actionunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <time> unix timestamp of the ban time
# Values: CMD
#
actionunban = echo -<ip> > /proc/net/xt_recent/fail2ban-<name>
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "DELETE FROM fail2ban WHERE source=INET_ATON('<ip>') AND jail='fail2ban-<name>;"

[Init]

# Defaut name of the chain
#
name = default

# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh

# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

bantime = 14400


(Die Werte für ‘actionunban’ können auch entfallen, da die Freigabe der IP durch xt_recent erfolgt.)

Damit landen alle Bans in der Datenbank und der Firewall. Was jetzt noch fehlt, ist der Import der Bans nach einem Neustart (oder ggf. auch manuell) per Script. Alle Informationen sind in der Datenbank enthalten: Name, IP und letzter Treffer.


#!/bin/bash
/usr/bin/mysql -usystemlog -pMYPASSWORD systemlog -e "SELECT INET_NTOA(source) FROM fail2ban WHERE (DATE_SUB(NOW(),INTERVAL $1 hour) <= last_hit) AND jail = '$2';"|grep -v source|while read IP; do echo +$IP > /proc/net/xt_recent/$2
done

Das Script muss für jeden Jail einzeln aufgerufen werden. Als Parameter werden Jail und Ban-Dauer in Stunden übergeben.

also ./script.sh fail2ban-pure-ftpd 2

iptables.conf
fail2ban.sql


Kommentar erstellen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

Ein Gedanke zu “fail2ban mit xt_recent reloaded