Gérer les flags TCP et l’ICMP avec NFtables
Nous avons vu précédemment comment gérer l'autorisation ou l'interdiction au niveau des ports et des adresses IP, en source et en destination, avec nftables.
Nous allons maintenant voir des cas plus précis en nous penchant sur la prise en charge de l'ICMP ou des flags TCP. Nous passerons par un rapide rappel de ces deux notions en réseau afin de mieux gérer ces contextes dans nftables. En réseau, et surtout en sécurité, il est primordial de comprendre le fonctionnement des choses avant de vouloir agir dessus.
I. Gérer l'ICMP
Comment traiter le cas de l'ICMP avec nftables ? Il est en effet courant de vouloir bloquer l'ICMP en entrée, par exemple pour se protéger des scans réseau qui peuvent utiliser l'ICMP. Dans d'autres cas, nous allons vouloir que la machine ne puisse pas pinguer, mais puisse être pinguée. Différents contextes auxquels vous saurez répondre après ces quelques lignes :).
Partons du principe le plus courant, je souhaite que ma machine puisse pinguer d'autres machines, mais ne puisse pas être pinguée. Dans le langage du filtrage, cela signifie :
- ICMP en entrée (INPUT) : non autorisé
- ICMP en sortie (OUTPUT) : autorisé
Plus précisément, avec nftables, nous devons spécifier le type de paquets ICMP que l'on traite. Il faut savoir que les ping émis par la machine ping sont des echo-request (demande d'echo) et les réponses sont des echo-reply (réponse d'echo). Cela est important dans la gestion de l'ICMP dans nftables.
On va donc vouloir autoriser les echo-request à sortir et les echo-reply à rentrer, c'est parti !
Comme à notre habitude, on commence par créer notre table, que nous appellerons mon_filtreICMP et deux chaines, une liée au hook INPUT et l'autre au hook OUTPUT :
root@debian:~# nft add table ip mon_filtreICMP root@debian:~# nft add chain ip mon_filtreICMP input { type filter hook input priority 0 \; } root@debian:~# nft add chain ip mon_filtreICMP output { type filter hook output priority 0 \; }
On passe ensuite à l'autorisation des paquets ICMP de type echo-request en sortie, puis on refuse le reste :
root@debian:~# nft add rule mon_filtreICMP output icmp type echo-request accept
root@debian:~# nft add rule mon_filtreICMP output drop
Enfin, on positionne nos règles pour le chemin de retour :
root@debian:~# nft add rule mon_filtreICMP input icmp type echo-reply accept
root@debian:~# nft add rule mon_filtreICMP input drop
Plutôt simple non ? 🙂 Pour tester que cela fonctionne, essayez de pinguer une autre machine que vous savez joignable sur le réseau, cela devrait fonctionner, puis tester de vous pinger depuis cette machine, cela ne fonctionnera pas, car les paquets ICMP echo-request sont bloqués en entrée par nftables. Exemple :
II. Gestion des flags TCP
Lorsque l'on aborde le filtrage de paquets, il peut arriver que l'on veuille aller plus loin que le simple port ou l'IP. Ici, nous allons voir comment gérer les flags TCP.
Pour rappel, le protocole TCP (Transmission Control Protocol), est un protocole de transport dit "à état". Ceci dans le sens où il gère des communications qui peuvent avoir différents états qui sont désignés en fonction de l'état des flags.
- flag SYN pour demander l'établissement d'une session;
- flag SYN/ACK pour confirmer la demande;
- flag ACK pour acquitter la bonne réception de la confirmation;
- flag FIN pour mettre fin à la session.
Pour information, d'autres types de paquets TCP peuvent avoir des combinaisons de flag qui ne sont pas prévues dans une communication normale. Par exemple, les paquets XMAS possèdent les flags FIN, PSH et URG actifs, les paquets NULL ne possèdent aucun flag actif. Ces paquets sont cependant utilisés dans le cadre de scan de port pour voir si des ports/services sont actifs, il est donc bon de savoir les bloquer.
Pour plus de détails sur le fonctionnement des flags TCP pour les scans réseau, je vous oriente vers les deux
Après ce petit rappel sur TCP, voyons comment gérer cela dans nftables. Pour compter tous les paquets TCP qui ont un flag autre que SYN d'actif, le tout en entrée :
root@debian:~# nft add rule mon_filtre input tcp flags != syn counter
Parmi tous les flags TCP, voici leur dénomination (en général, et dans nftables) :
- Fin
- Syn
- Rst
- Psh
- Ack
- Urg
Si l'on souhaite journaliser tous les paquets TCP qui ont leurs flags SYN et ACK d'actifs, le tout en sortie :
root@debian:~# nft add rule mon_filtre output tcp flags \& \(syn \| ack\) == \(syn \| ack\) counter log
Houla, qu'est-ce que c'est que cette ligne de commande bien compliquée ?
Je vous dois quelques explications ici, la présence des nombreux "\" dans la ligne de commande est une spécificité de l'utilisation de la ligne de commande nft. En effet, pour ne pas que notre commande et les caractères spéciaux qu'elle comprend (comme "&" ou "(") entrent en conflit avec le système de commande de Linux, on doit les échapper avec un "\". L'échappement consiste à dire à Linux "ce caractère spécial fait partie de ma commande nft, ne l'interprète pas pour toi". J'en conviens, ce n'est pas très pratique, mais nous verrons dans le prochain module d'autres méthodes de configuration sous nftables;).
Pour des raisons de sécurité comme je l'ai expliqué plus haut, il peut être intéressant de bloquer les paquets TCP XMAS et NULL, ceux-ci se caractérisent par des paquets avec les flags FIN,PSH et URG actifs pour XMAS et aucun flag actif pour NULL. La syntaxe dans ces cas n'est pas simple à deviner. Voici une règle qui va compter tous les paquets TCP NULL, c’est-à-dire qui n'ont aucun flag actif :
root@debian:~# nft add rule mon_filtre output tcp flags \& \(fin\|syn\|rst\|psh\|ack\|urg\) \< fin counter
Voici une règle qui va compter tous les paquets TCP XMAS, c’est-à-dire qui ont les flags FIN, PSH et USH d'actif :
root@debian:~# nft add rule mon_filtre input tcp flags \& \(fin\|syn\|rst\|psh\|ack\|urg\) \> urg counter
En plus de les compter, on pourrait très bien les journaliser par exemple, pour pouvoir récupérer l'IP des émetteurs de ces paquets TCP. Egalement, il est possible d'explicitement autoriser ou de bloquer à partir des flags TCP.
C'est la fin de ce troisième module, nous avons été plus technique dans celui-ci. Cela vous permet dès à présent d'être plus à l'aise dans un contexte réel. Dans le prochain module, nous verrons ensemble différentes configurations plus avancées. Nous verrons par exemple la mise en place du NAT sous nftables (source et destination) ainsi que le fait de compter les paquets correspondant à une règle ou encore produire des logs.
Nous verrons également des méthodes qui vous permettront d'être plus efficace dans la configuration des règles nftables, via les fichiers préconfigurés, la sauvegarde des règles nftableset leur restauration.
Rendez-vous dans le prochain module ! 🙂