J’utilise habituellement les bans dynamiques de shorewall en association avec fail2ban.
Cependant, il devient rapidement pénible de recevoir les mails d’avertissement associés à répétition lorsque l’attaquant ne se décourage pas.
C’est pourquoi je me suis inspiré de cet article afin d’utiliser le module recent d’iptables.
Le module recent
Ce module d’iptables permet de conserver un historique des derniers paquets d’une IP correspondants à certains critères. Il est ainsi possible de bloquer une IP avec une fenêtre glissante, qui se réinitialise à chaque tentative (elle-même bloquée).
Cela permet par exemple de bloquer une attaque brute force SSH tant que l’attaquant persiste.
On utilise généralement une association de deux règles pour profiter du module recent :
iptables -N to-ban
iptables -A to-ban -m recent --name recent-list --update --seconds 3600 -j DROP
iptables -A to-ban -m recent --name recent-list --set -j DROP
La première va rejeter (silencieusement) le paquet si l’IP source fait partie de la liste « recent-list » et qu’elle a émis un paquet il y a moins de 3600 secondes (1 heure donc). Si le paquet vérifie ces conditions, le module recent va en plus mettre à jour sa table avec le timestamp courant, réinitialisant alors le timer.
La seconde règle permet d’ajouter une IP dans la liste « recent-list » (afin qu’elle rentre en correspondance avec la première règle lors du prochain paquet).
Création de l’action fail2ban
Il est alors simple de créer un nouveau type d’action fail2ban, basé sur iptables-allports.conf :
# cat /etc/fail2ban/action.d/iptables-recent.conf
# Fail2Ban configuration file
#
# Author: Cyril Jaquier
# Modified: Yaroslav O. Halchenko
# made active on all ports from original iptables.conf
#
# $Revision: 658 $
#
[Definition]
# Option: actionstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD
#
actionstart = iptables -N fail2ban-
iptables -A fail2ban- -m recent --name recent- --update --seconds 3600 -j DROP
iptables -A fail2ban- -m recent --name recent- --remove -j RETURN
iptables -A fail2ban- -j RETURN
iptables -I INPUT -p -j fail2ban-
# Option: actionstop
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD
#
actionstop = iptables -D INPUT -p -j fail2ban-
iptables -F fail2ban-
iptables -X fail2ban-
# Option: actioncheck
# Notes.: command executed once before each actionban command
# Values: CMD
#
actioncheck = iptables -n -L INPUT | grep -q fail2ban-
# Option: actionban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: IP address
# number of failures
#
L’action start crée une chaîne fail2ban-
Cette chaîne ne fait par défaut que rejeter les paquets faisant partie de la liste recent-
L’action ban ajoute une règle spécifique à l’IP à bannir, afin de l’ajouter à la liste du module recent. Elle entrera alors automatiquement dans la fenêtre de ban glissante.
L’action stop supprime cette dernière règle. L’IP pourra voir son trafic reprendre dès que le module recent l’aura « oubliée », c’est à dire dès qu’elle aura eu un délais d’inactivité de plus d’une heure.
Elle correspondra alors à la règle « remove », qui la supprimera de la liste recent-
Nettoyage des listes du module recent
On peut voir le contenu des listes du module recent à partir des fichiers contenus dans /proc/net/xt_recent/ :
vilo _TV_ # cat /proc/net/xt_recent/recent-shorewall
src=82.234.245.47 ttl: 45 last_seen: 4304285107 oldest_pkt: 2 4304284706, 4304285107
src=89.72.204.102 ttl: 115 last_seen: 4300884873 oldest_pkt: 3 4300883971, 4300884269, 4300884873
src=87.244.66.115 ttl: 48 last_seen: 4303585869 oldest_pkt: 2 4303585477, 4303585869
src=77.205.31.17 ttl: 117 last_seen: 4311366646 oldest_pkt: 8 4311343362, 4311343998, 4311356076, 4311356271, 4311356904, 4311365737, 4311366043, 4311366646, 4311301283, 4311301646, 4311309439, 4311309741, 4311310339, 4311317676, 4311318269, 4311327004, 4311327387, 4311327945, 4311335224, 4311343121
src=87.244.104.236 ttl: 48 last_seen: 4296186058 oldest_pkt: 2 4296185657, 4296186058
La taille de ces listes étant limitées, je me suis intéressé à leur nettoyage. Leur taille est en effet limitée (100 IP par défaut), et le module ne retire pas automatiquement les IPs expirées.
Cependant, il est capable de faire automatiquement de la place en supprimant les entrées les plus anciennes lorsqu’il doit ajouter une nouvelle entrée dans une table déjà pleine.
Une alternative pourrait être l’option « reap », mais celle-ci ne semble pas encore officiellement supportée par l’utilitaire iptables (bien que certaines distributions appliquent le patch nécessaire).