Dans un précédent article, je vous expliquais comment compter et classer les adresses IP bannies par Fail2ban. Quelques semaines après avoir écrit cet article, j’ai refait une analyse sur mon serveur et je me suis rendu compte qu’une adresse IP avait été bannie 530 fois, et d’autres près de 200 fois !
Après avoir analysé mes logs, il s’est avéré que l’adresse IP ayant été bannie 530 fois (d’origine chinoise, donc elle ne venait clairement pas de moi) avait essayé de se connecter en SSH avec l’utilisateur root (= administrateur sur les systèmes Linux) 4540 fois !!! Heureusement j’avais déjà supprimé la possibilité de se connecter en root via SSH, mais cette découverte m’a fait réaliser qu’il fallait que je prenne le problème au sérieux. J’ai donc écrit un script Python qui va analyser la liste des adresses IP bannies par Fail2ban et bloquer définitivement celles qui ont été bannies plus de 10 fois en les enregistrant dans IPtables.
Ban-them, le complément à Fail2ban qui vous débarrasse des IP envahissantes
Pour que vous puissiez aussi profiter de ce script, je l’ai mis à disposition sur Github à l’adresse suivante : https://github.com/egrisel/ban-them.
Ce script va analyser la liste produite par la ligne de code présentée dans mon précédent article, faire un peu de nettoyage pour faciliter l’analyse, enregistrer les adresses IP bannies plus de 10 fois dans une base de données Sqlite afin de pouvoir bloquer à nouveau les adresses IP en cas de redémarrage du serveur (nous n’aimerions tout de même pas que toutes ces adresses soient perdues à cause d’un simple redémarrage du serveur !) et les ajouter à IPTables afin de les bloquer définitivement.
Pour installer ce script, il vous faut tout d’abord avoir Git d’installé sur votre serveur. Pour ce faire, saisissez la commande suivante en tant que root (pour Debian et ses dérivés dont Ubuntu, pour les autres Google est votre ami) :
apt-get install git-core
Rendez-vous ensuite dans le répertoire où vous voulez installer le script. Pour ma part j’ai créé un répertoire scripts dans le répertoire personnel de root (/root/scripts). Saisissez ensuite la commande suivante, toujours en tant que root :
git clone https://github.com/egrisel/ban-them
Un nouveau répertoire nommé ban-them sera créé contenant le script ban-them.py. Pour tester le script, vous pouvez le lancer en mode « bavard » avec l’option -v :
python3 ban-them.py -v
Le script vous indiquera alors les adresses IP qui ont été bannies ou si celles qui auraient dû être bannies l’étaient déjà.
Si vous désirez modifier la limite à partir de laquelle une IP doit être bannie, vous pouvez passer l’option -n X au script, X étant à remplacer par le nombre minimum de bannissement :
python3 ban-them.py -n 15
Si le script vous affiche une erreur indiquant que le fichier de logs de Fail2ban ne peut être trouvé, vous pouvez passer l’option -s /chemin/vers/le/fichier_de_log au script. Par défaut le chemin est /var/log/fail2ban.log. Cette option peut être intéressante si vous voulez bannir les IP envahissantes qui se trouvent dans le log précédent. Pour ce faire :
python3 ban-them.py -s /var/log/fail2ban.log.1
Une fois que vous aurez trouvé le réglage qui vous convient, vous pouvez rendre le script directement exécutable avec la commande suivante :
chmod +x ban-them.py
Pour finir, ajoutez un crontab pour que le script soit exécuté automatiquement par votre serveur :
crontab -e
0 * * * * /chemin/vers/le/script/ban-them.py
J’espère que ce script vous aidera à protéger un peu plus votre serveur.
Et vous, quelle solutions utilisez-vous pour bannir les IP envahissantes ? Que pensez-vous de mon premier script Python ? Avez-vous des questions ou des remarques à propos de ce script ? Les commentaires sont là pour vous !
Excellent script !!!
Merci Martial 🙂
Bonjour,
C’est vraiment bien mais voici ce que j’ai avec Debian 9 stretch :
# ./ban-them.py -v
iptables v1.6.0: host/network `Ban’ not found
Try `iptables -h’ or ‘iptables –help’ for more information.
Traceback (most recent call last):
File « ./ban-them.py », line 170, in
main(sys.argv[1:])
File « ./ban-them.py », line 162, in main
ipt_result = subprocess.check_output([« /sbin/iptables », « -A », « ban-them », « -s », row[1], « -j », « DROP »])
File « /usr/lib/python3.5/subprocess.py », line 316, in check_output
**kwargs).stdout
File « /usr/lib/python3.5/subprocess.py », line 398, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command ‘[‘/sbin/iptables’, ‘-A’, ‘ban-them’, ‘-s’, ‘Ban’, ‘-j’, ‘DROP’]’ returned non-zero exit status 2
Avec Jessie, ça fonctionne bien semble t’il. Où est l’erreur ? Une idée ?
Bonjour Piotr58,
Merci pour ton commentaire.
La ligne qui pose problème est celle qui ajoute les adresses IP à bannir à IPTables. Il semblerait dans ton cas qu’une donnée autre qu’une adresse IP a été transmise à la commande (« Ban » dans l’erreur que tu as fourni).
Peux-tu exécuter la commande suivante depuis le répertoire où tu as installé mon script :
./sort-fail2ban-log.sh /var/log/fail2ban.log
Le résultat devrait être une suite de lignes du genre « 15 [ssh] une_adresse_ip ». Si le résultat n’est pas celui-là, je pense que Debian a modifié les logs de Fail2ban dans Debian 9. Dans ce cas, peux-tu me transmettre un extrait des logs de /var/log/fail2ban.log ? Je verrai ensuite comment il faut adapter mon script.
Bonjour et merci de ta réponse,
Voici le genre de lignes contenue à l’exécution de ta commande :
./sort-fail2ban-log.sh /var/log/fail2ban.log
105 NOTICE Ban
Et voici un exemple de contenu du log :
…
2017-06-22 21:07:01,976 fail2ban.actions [790]: NOTICE [sshd] Ban
2017-06-22 21:07:01,988 fail2ban.filter [790]: INFO [recidive] Found
2017-06-22 21:07:09,227 fail2ban.actions [790]: NOTICE [sshd] Unban
…
2017-06-23 00:46:01,901 fail2ban.actions [790]: NOTICE [recidive] [NNN.NNN.NNN.NNN]
…
2017-06-23 00:46:35,732 fail2ban.actions [766]: NOTICE [recidive] Ban [NNN.NNN.NNN.NNN]
…
Visiblement il y a eu un décalage dans l’ordre du log. J’ai pris les champs 6 et 8 à la place des champs 5 et 7 et tout est rentré dans l’ordre.
Merci
Dommage, ça avait pourtant bien commencé…
Voici la forme des lignes générée par le script « sort-fail2ban-log.sh » avec les champs 6 et 8 :
./sort-fail2ban-log.sh /var/log/fail2ban.log
3 [sshd]
3 [recidive]
2 [ssh-iptables-ipset6]
Je pensais que c’était bon, ben non, voilà ce que ça donne :
# ./ban-them.py -v
iptables v1.6.0: host/network `Ban’ not found
Try `iptables -h’ or ‘iptables –help’ for more information.
Traceback (most recent call last):
File « ./ban-them.py », line 171, in
main(sys.argv[1:])
File « ./ban-them.py », line 163, in main
ipt_result = subprocess.check_output([« /sbin/iptables », « -A », « ban-them », « -s », row[1], « -j », « DROP »])
File « /usr/lib/python3.5/subprocess.py », line 316, in check_output
**kwargs).stdout
File « /usr/lib/python3.5/subprocess.py », line 398, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command ‘[‘/sbin/iptables’, ‘-A’, ‘ban-them’, ‘-s’, ‘Ban’, ‘-j’, ‘DROP’]’ returned non-zero exit status 2
Ola,
Je pense avoir compris ce qui se passe.
Sur mon serveur Stretch, j’ai à la fois des ligne « WARNING » et des lignes « NOTICE » dans les logs fail2ban. Avec les lignes « WARNING » le n° IP des bannissement est le 7ème champ. Par contre, dans les lignes « NOTICE », c’est le 8ème…
Si je pars du principe que tu test les lignes WARNING, je propose de les extraire du log avant de lancer le script :
# grep ‘ WARNING ‘ /var/log/fail2ban > [Fichier temporaire]
# ./ban-them.py -v -s [Fichier temporaire]
Cela permet également de jumeler la recherche des IP bannies dans les 2 derniers fichiers de log. On peut lancer ça dans le cron :
0 * * * * (cat /var/log/fail2ban{,.1} > /chemin/vers/le/script/fail2ban.log && /chemin/vers/le/script/ban-them -s /chemin/vers/le/script/fail2ban.log)
A+