iptables, ou l'art de décider qui passe
iptables, c'est l'outil en ligne de commande qui te permet d'écrire ces phrases pour le pare-feu du noyau Linux. Il ne filtre rien lui-même. Il parle à netfilter, le framework intégré au noyau, qui place des points d'accroche sur le chemin des paquets. Toi, tu écris des règles. Le noyau, lui, les applique à la vitesse du matériel.
Tu le trouves sur à peu près toutes les distributions. C'est rarement un choix conscient. C'est là, par défaut, et un jour tu dois décider quoi en faire.
La question n'est pas si, mais combien
Avant de toucher à quoi que ce soit, il faut comprendre une chose : iptables ne raisonne pas en « services » ou en « applications ». Il raisonne en paquets, en adresses, en ports, en protocoles.C'est ce qui le rend précis. C'est aussi ce qui le rend pénible.
Une règle typique ressemble à ceci :
``` iptables -A INPUT -p tcp --dport 22 -j ACCEPT ```
Un paquet TCP qui arrive sur le port 22 reçoit un ACCEPT. Tout le reste de la chaîne est ignoré pour ce paquet. Point.
La chaîne, justement. C'est là que tout se joue. iptables range ses règles dans des tables, et ces tables dans des chaînes. La table `filter` décide qui passe. La table `nat` réécrit les adresses. La table `mangle` tripote les en-têtes. La table `raw` sert à contourner le suivi de connexion.
Pour 90 % des usages, tu ne toucheras qu'à `filter`, et à trois chaînes : INPUT pour ce qui entre et te concerne, OUTPUT pour ce qui sort, FORWARD pour ce qui traverse ta machine sans s'y arrêter.
L'ordre est la seule vraie règle
Les règles sont lues de haut en bas. La première qui correspond gagne. Les suivantes n'existent plus.Ça paraît anodin. Ça ne l'est pas.
Si tu acceptes le port 22 en haut de ta chaîne, tu as beau écrire plus bas une règle qui rejette tout le trafic depuis une plage d'adresses précise, elle ne s'appliquera jamais à ce port. La règle permissive a déjà tranché.
D'où la discipline habituelle : les cas particuliers d'abord, la politique générale à la fin. Et cette politique générale, c'est le default policy de la chaîne. Tu la définis une fois :
``` iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT ```
Tu viens de fermer la porte d'entrée. Maintenant il faut rouvrir ce qui doit l'être, une règle à la fois. C'est fastidieux. C'est aussi la seule façon de savoir ce qui passe.
Un conseil qui n'en est pas un : si tu te connectes en SSH à la machine que tu es en train de configurer, ne mets jamais `-P INPUT DROP` avant d'avoir accepté le port 22. Sinon tu découvres la joie de la console de secours de ton hébergeur. Certains l'apprennent une fois. D'autres, deux.
IPv4 et IPv6 ne se parlent pas
iptables gère IPv4. Pour IPv6, c'est un autre outil : `ip6tables`. Même syntaxe, même logique, modules noyau séparés.Sur un serveur en double pile, ça veut dire écrire tes règles deux fois. Une fois pour iptables, une fois pour ip6tables. Si tu oublies la seconde, ton pare-feu IPv4 peut être impeccable pendant qu'IPv6 laisse tout passer.
C'est une erreur classique, et elle est silencieuse. Rien ne t'avertit. Le service répond, tout a l'air normal, sauf que la moitié de ton exposition réseau n'est couverte par rien.
Docker écrit tes règles à ta place
Voilà le point qui fâche.Quand tu démarres un conteneur avec un port publié, Docker ajoute lui-même des règles dans les tables `nat` et `filter`. Il ne te demande pas ton avis. Il les insère souvent avant les tiennes.
Résultat : tu peux avoir écrit une règle qui dit « ce port n'est accessible que depuis le réseau interne », et découvrir que Docker a publié ce même port sur toutes les interfaces. Ta règle est toujours là. Elle est simplement passée en second.
Ce n'est pas un bug. C'est le comportement documenté de Docker, qui a besoin de ces règles pour faire fonctionner le NAT entre conteneurs et hôte. Mais si tu ne le sais pas, tu passes une soirée à te demander pourquoi ton pare-feu ne filtre rien.
Tu peux désactiver cette gestion avec `iptables=false` dans la configuration du démon. C'est possible. C'est aussi le meilleur moyen de casser la résolution DNS des conteneurs et la connectivité réseau. À réserver aux configurations où tu reprends tout à la main, en connaissance de cause.
Le successeur existe, il n'a pas encore gagné
nftables remplace iptables. C'est le framework prévu pour prendre la suite, avec une syntaxe plus lisible, de meilleures performances sur de grosses ensembles de règles, et une validation à l'écriture.Sur le papier, c'est mieux. Sur le terrain, iptables est partout.
Des années de scripts, de tutoriels, d'outils comme fail2ban qui génèrent des règles iptables sans te demander ton avis. Docker ne supporte nftables qu'expérimentalement, via `--firewall-backend=nftables`, et les règles pour les réseaux overlay ne sont pas encore migrées. En mode Swarm, tu restes sur iptables.
Donc tu as deux options. Tu apprends iptables, qui est partout et qui marche. Ou tu apprends nftables, qui est propre et qui arrive. Dans les deux cas, tu finiras par connaître l'autre.
fail2ban, ou la couche au-dessus
fail2ban lit tes journaux. Il repère les tentatives de connexion ratées. Et quand une adresse IP insiste trop, il ajoute une règle iptables pour la bloquer pendant un temps.Tu ne l'écris pas, cette règle. fail2ban l'écrit pour toi, à travers son fichier `jail.conf` et ses actions. iptables sert ici de couche d'exécution : le cerveau est ailleurs, la main qui coupe est iptables.
C'est un bon exemple de la place réelle d'iptables dans une pile. Ce n'est pas la politique de sécurité. C'est le mécanisme qui l'applique.
Ce qui se perd au redémarrage
Par défaut, tes règles ne survivent pas à un reboot. Tu les écris, tu redémarres, elles ont disparu. C'est voulu, et c'est un piège.Pour les garder, il faut les sauvegarder explicitement :
``` iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6 ```
Et les restaurer au démarrage. Sur Debian et Ubuntu, le paquet `iptables-persistent` fait ce travail. Sur d'autres distributions, tu passes par un service systemd ou un script d'init.
Sans cette étape, ta machine redémarre nue. Un pare-feu qui s'évapore au premier reboot n'est pas un pare-feu. C'est une décoration.
Les limites, dites franchement
iptables est vieux. Sa syntaxe est dense, ses règles s'empilent sans vue d'ensemble, et rien ne te prévient quand tu écris une règle qui ne servira jamais parce qu'une autre, plus haut, la rend inutile.Tu peux te retrouver avec trois cents règles dont tu ne sais plus lesquelles comptent. Ça arrive. Ça arrive même souvent, sur les serveurs qu'on configure une fois puis qu'on n'ose plus toucher.
nftables corrige une partie de ça. La migration, elle, prend du temps, parce qu'il faut réécrire des scripts, revoir des workflows, et vérifier que rien ne casse.
Alors, quoi choisir
Si tu administres un serveur unique, avec quelques services et Docker par-dessus, iptables reste le chemin le plus court. Tu trouveras de la documentation pour chaque cas de figure, et les outils que tu installes s'attendront à le trouver là.Si tu pars d'une base propre, sans héritage, et que tu veux des règles lisibles et validées à l'écriture, nftables est le bon pari. À condition d'accepter que certains outils ne suivent pas encore.
Et si tu ne veux toucher ni à l'un ni à l'autre, il existe des surcouches comme ufw ou firewalld qui écrivent les règles à ta place. Elles en couvrent l'usage courant et te laissent tomber dès que tu sors des sentiers battus. C'est un compromis honnête, tant que tu sais où il s'arrête.
La vraie question n'est pas quel outil est le meilleur. C'est combien de temps tu veux passer à comprendre pourquoi un paquet passe alors que tu croyais l'avoir bloqué.