IPSET une nouvelle arme contre les méchants ?

Note 2020 : depuis tous ce temps, (début 2013) j'utilise un pare-feu à base d'IPSET car  les règles iptables utilisant des IPSET sont très performantes. Un set rempli d'adresses "douteuses" n'est pas une cause de latence, c'est d'autre part beaucoup plus facile à maintenir, enlever ou ajouter une adresse est quasiment instantané et cela évite surtout un empilage de règles difficiles à maintenir et qui finissent par être une cause importante de latence. Il est par exemple très facile et performant créer un "set" d'adresses de pays que l'on ne désire pas voir accéder à un système.

Dès qu'une machine est reliée à Internet elle subit de nombreuses tentatives d'entrée ou de test. Un bon Firewall permet de contrôler en partie ces tentatives mais les services offerts par chaque machine ne peuvent que moins facilement être protégés des « méchants ». Si par exemple vous avez un serveur de mails vous recevrez de nombreux essais d'envoi de mail bien que votre serveur ne soit pas configuré en mode « open ». Un serveur HTTP entrainera un tas de tests sur des bugs de beaucoup de logiciels. C' est énervant, cela remplit bêtement les logs d'enregistrements inutiles et alourdit leur lecture, toute cette brume de tentatives indiscrètes peut finir par cacher certains messages utiles.

Note 2017 : Ipset est en version 6.30 et tout fonctionne toujours correctement avec un noyau 4.13.7.

Le site « emerging threats » fournit des listes d'adresses IP, voire de réseaux entiers, qui hébergent ces vilains pollueurs de logs qui peuvent quand même planter des services ou même réussir à faire pire encore. Ces listes sont régulièrement mises à jour.

On peut récupérer (ou créer) de longues listes de règles « iptables » qui ralentissent évidemment le fonctionnement de votre firewall et fait d'un simple « iptables -vnL » une liste infinie.

Et alors IPSET est arrivé …. en fait la fonctionnalité existe depuis longtemps mais était assez difficile à maîtriser. Aujourd'hui avec les noyaux récents et la dernière version du protocole (version 6) cela semble très stable et parfaitement maîtrisable avec des performances qui semblent excellentes.

Un simple "apt-get install ipset" est OK, mais votre noyau doit être compilé avec les options adéquates :

make menuconfig

Networking support / Networking options / Network packet filtering framework / Ipset support.

Vérifier aussi la version de protocole de "ipset" :

ipset --version 
ipset v6.12.1, protocol version: 6 
 

Les versions de "ipset" et du noyau doivent être "en phase" pour fonctionner, ce qui peut parfois poser quelques problèmes de compatibilité.

IPSET 6.19 fonctionne avec tous les noyaux de 3.2 à 3.11, IPSET 6.12 avec ceux de 3.2 à 3.10. 

Je n'ai pas essayé de noyaux < 3.2.

Mes tests ont été réalisés avec des noyaux 3.9, 3.10 et 3.11-rc2 afin d'avoir les fonctionnalités les plus récentes. Le programme "ipset" 6.19) a été chargé depuis la version "unstable" de Debian afin de disposer là aussi des éléments les plus récents compatibles avec ces noyaux.

L'ensemble est simple à utiliser :

  • coté « iptables » une simple règle permet d'éliminer d'un seul coup toutes les adresses contenues dans un « set »
  • coté gestion des « sets » la commande « ipset » permet de gérer assez simplement les choses.

Cette commande possède un paramètre permettant de remplacer d'un seul coup un « set » par un autre et ce sans stopper le firewall ni supprimer la règle. La commande « swap » réalise cette opération instantanément sans interruption de la sécurité. Vous pouvez donc préparer tranquillement un nouveau « set » puis le « swapper » instantanément avec un set existant.

Il existe différentes catégories de « sets » selon que l'on veut traiter :

  • des adresses IP
  • des réseaux en notation CIDR
  • des adresses/port
  • ….

Le tout en deux modes principaux : HASH et BITMAP.

N'ayant ici que besoin de traiter des adresses et des réseaux je ne me suis intéressé qu'aux deux types « iphash » et « nethash » qui semblent adaptés à mon besoin et sont d'une très grande rapidité.

J'utilise en entrée trois listes d'adresses sources :

  • une petite liste personnelle en notation CIDR
  • un fichier de « emerging threats » nommé « compromised-ips.txt » contenant des adresses IP et des adresses en notation CIDR
  • un autre fichier « emerging threats » nomme « rbn-malvertisers-ips.txt »

Un traitement simple des listes d'adresses élimine les commentaires et les ligne vides puis sépare les adresses simples des adresses CIDR. Chaque groupe d'adresses est ensuite trié avec élimination des doubles (la présence de doubles provoque un arrêt d'urgence des chargements de sets) et remplit les deux sets adresses IP et adresses CIDR.

Les règles iptables se limitent à deux (en PREROUTING pour stopper le plus tôt possible les paquets vicieux) :

iptables -t raw -I PREROUTING -m set --match-set BLACK_IP src -j DROP

iptables -t raw -I PREROUTING -m set --match-set BLACK_NET src -j DROP

On peut aussi créer une chaîne perso ici "NOUVIN" sur laquelle on redirige les connections "nouvelles". Par exemple :

iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
iptables -A INPUT -m state --state NEW -j NOUVIN 
On insérera les règles "SET" dans cette chaîne "NOUVIN" :

iptables I NOUVIN -m set --match-set BLACK_IP  src     -j DROP 
iptables I NOUVIN -m set --match-set BLACK_NET src     -j DROP

Après un rechargement des deux sets nommés chez moi « BLACK_IP » et « BLACK_NET » il suffit, après récupération des fichiers et traitement préparatoire de créer et remplir deux nouveaux sets de travail. Remarque la commande « ipset » peut aussi être installée dans /usr/sbin.

SET=W_BLACK_IP

/sbin/ipset --create $SET iphash --hashsize 50000

puis de remplir le set par une boucle sur la lecture de la liste préparée sur la commande

/sbin/ipset --add $SET $ADDR

SET=W_BLACK_NET

/sbin/ipset --create $SET nethash --hashsize 4096

suivre le même process en utilisant :

/sbin/ipset –add $SET $ADDR $MASK

Une fois nos deux sets « W » prêts il suffit de les « swapper » avec les sets permanents :

/sbin/ipset swap W_BLACK_IP BLACK_IP

/sbin/ipset swap W_BLACK_NET BLACK_NET

puis de détruire les sets « W » de travail :

/sbin/ipset --destroy W_BLACK_IP

/sbin/ipset --destroy W_BLACK_NET


Et le tour sera joué ... et les méchants joués.