Une journée de travail plus tard, j'ai enfin trouvé comment limiter le nombre de connexion par IP avec iptable sur le port 80. Pour se faire j'utilise l'extension match recent d'iptables qui permet de créer et de gérer des règles en fonction d'une liste d'adresses IP.
Limitation
Comme ces règles sont basées sur les adresses IP elles ne peuvent pas vous protéger contre des attaques DDOS (Distributed Denial Of Service).
Blocage simple
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name BLACKLIST --set
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name BLACKLIST --update --seconds 10 --hitcount 10 --rttl -j DROP
Avec les deux règles précédentes je refuse (DROP) les nouvelles (-m state --state NEW) connexions entrantes (-A INPUT) au port http (--dport 80) qui atteignent le taux de 10 connexions (--hitcount 10) sur une période de 10 secondes (--seconds 10) et qui utilisent le protocol tcp (-p tcp).
La première règle sert à mettre à jour l'adresse IP dans la liste BLACKLIST et la seconde règle permet de limiter les connexions.
Bloquer les attaquants sur une période plus grande que le taux
Le problème des règles précédentes est que l'adresse IP attaquante est bloquée sur une période glissante qui n'est que de 10 secondes.
Pour bloquer sur une période différentes que celle qui définit par le taux limite j'ai mis en place les règles suivantes :
Création d'une nouvelle chaine BLACKLIST :
iptables -N BLACKLIST
Lorsqu'un paquet arrive dans la chaine BLACKLIST on le drop et on ajoute son IP dans la liste BLACKLIST :
iptables -A BLACKLIST -m recent --name BLACKLIST --set -j DROP
On bloque les paquets pour une période de 60 secondes :
iptables -A INPUT -m recent --update --name BLACKLIST --seconds 60 --rttl -j DROP
Quand un paquet arrive en entrée sur le port 80 on met son IP dans la liste COUNTER :
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name COUNTER --set
Si un paquet arrive en entrée et qu'il dépasse le taux on le redirige dans la chaine BLACKLIST :
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -m recent --name COUNTER --update --seconds
10 --hitcount 10 --rttl -j BLACKLIST
Tuning de l'extension recent
Par défaut l'extension recent d'iptables garde 100 adresses IP différentes dans les listes et garde 20 paquets par IP. En faisant quelques tests je me suis rendu compte que ce n'était pas suffisant donc je vous donne les commandes qui vont bien.
Changer le nombre d'ip du mode recent
chmod u+w /sys/module/xt_recent/parameters/ip_list_tot
echo 200 > /sys/module/xt_recent/parameters/ip_list_tot
chmod u-w /sys/module/xt_recent/parameters/ip_list_tot
Changer le nombre de paquet par ip du mode recent
chmod u+w /sys/module/xt_recent/parameters/ip_pkt_list_tot
echo 200 > /sys/module/xt_recent/parameters/ip_pkt_list_tot
chmod u-w /sys/module/xt_recent/parameters/ip_pkt_list_tot
Surveiller les listes d'ip
Pour informations les listes d'IP de l'extension recent sont disponibles dans /proc/net/xt_recent/
root@home:~# ls /proc/net/xt_recent/* -alh
-rw-r--r-- 1 root root 0 4 juin 09:17 /proc/net/xt_recent/BLACKLIST
-rw-r--r-- 1 root root 0 4 juin 09:17 /proc/net/xt_recent/COUNTER
Un petit extrait du contenu de ma liste COUNTER :
src=81.245.XX.XXX ttl: 56 last_seen: 634716668 oldest_pkt: 7 634716652, 634716665, 634716666, 634716667, 634716667, 634716668, 634716668
src=67.xx.115.XXX ttl: 55 last_seen: 634719164 oldest_pkt: 1 634719164
src=2XX.46.X9X.XX ttl: 120 last_seen: 634831058 oldest_pkt: 1 634831058
src=6X.2XX.1XX.1X6 ttl: 60 last_seen: 634821958 oldest_pkt: 1 634821958
src=81.XX.143.3X ttl: 56 last_seen: 634806578 oldest_pkt: 1 634806578
Le format des listes est composé d'une ligne par adresse IP. Sur chaque ligne, en plus de l'adresse IP on trouve dans l'ordre :
- Le time to live (ttl)
- Le timestamp qui correspond au dernier paquet de cette adresse (last_seen)
- Le nombre de paquets (oldest_pkt)
- La liste des timestamps des derniers paquets
Pour aller plus loin
Voici une liste d'articles qui présentent d'autres types de protection contre les attaques DoS :
- Armes anti DDOS à base de TARPIT
- Preventing brute force attacks using iptables recent matching
- Iptables Limits Connections Per IP
- Using iptables to rate-limit incoming connections
Image : Mourner