15/11/2024

NetFilter, NFtables, ça fonctionne comment ?

Pour rappel, NetFilter est le pare-feu Linux. nftables n'est qu'un intermédiaire qui permet de configurer NetFilter.

Ce qu'il faut retenir lorsque l'on travaille avec nftables et NetFilter, c'est la notion de hook (ou "crochet") que NetFilter positionne dans le système.

I. Crochets/hooks

Un hook va être un point précis dans le chemin que prennent les flux réseau qui arrivent et sortent du système. Les hooks sont les endroits sur lesquels s'appliquent les règles et qui permettent donc de changer le comportement des paquets en entrée ou sortie de l'interface en fonction des règles configurées.

Voyons cela simplement, lorsqu'un paquet arrive ou sort du système, on peut penser qu'il n'effectue que le chemin suivant entre l'interface réseau (en haut) et les applications (en bas) :

schema-nftables-netfilter-hooks-02
Schéma simpliste du flux réseau au sein d'un système

En réalité, et lorsque NetFilter est installé, il positionne différents points d'accroche dans le chemin qu'empruntent les paquets dans le système pour y effectuer des vérifications du type "je laisse passer" ou "je ne laisser pas passer" en fonction des règles que nous lui avons donné. Nous trouvons alors 5 Hooks appliqués par NetFilter :

schema-nftables-netfilter-hooks-01
Flux réseau avec les contrôles de NetFilter

Comme nous pouvons le voir sur le schéma ci-dessus, on peut trouver différents hooks (ou crochets) à différents endroit au fur et à mesure de l'avancement du paquet dans son traitement par le système. Pour chaque crochet positionné par NetFilter, nous pourrons:

  • modifier le paquet, puis le rendre ou non au système ;
  • imposer au système de supprimer le paquet, cela correspond alors à un rejet du paquet ;
  • indiquer au système que le paquet est accepté pour ce hook, jusqu'au prochain.

II. Quelles relations entre les hooks et nftables?

La réponse est simple, chaque crochet (ou Hook) est relié à une chaine que nous pouvons configurer dans nftables :

  • Hook NF_IP_PRE_ROUTING qui correspond à la chaine PREROUTING dans nftables

Dans ce crochet, les paquets sont analysés dans leur forme brute, sans traitement préalable du système. On peut alors déterminer si on autorise le paquet à entrer plus loin dans le système ou non.

  • Hook NF_IP_LOCAL_IN qui correspond à la chaine INPUT dans nftables

Ici, les paquets sont prêt à être envoyés à la couche applicative, c’est-à-dire aux applications qui les traiteront (exemple : un serveur web ou un service FTP).

  • Hook NF_IP_FOWARD qui correspond à la chaine FORWARD dans nftables

Lorsque ce hook est utilisé, c'est que les paquets n'iront pas vers la couche applicative, mais seront redirigés vers une autre interface réseau. Par exemple dans le cas où le système est un routeur.

  • Hook NF_IP_LOCAL_OUT qui correspond à la chaine OUTPUT dans nftables

Il s'agit ici du même fonctionnement que la chaine INPUT, mais en sortie de la couche applicative. On va donc autoriser ou non un paquet à sortir vers l'interface réseau.

  • Hook NF_IP_POSTROUTING qui correspond à la chaine "POSTROUTING" dans nftables

On retrouve ici le même principe que la chaine PREROUTING" mais pour la sortie des paquets. Les paquets analysés sont ici de nouveau dans leur forme brute.

La différence entre INPUT et PREROUTING, OUTPUT et POSTROUTING ?

Il y a surement un point sur lequel vous avez bloqué si vous n'avez pas l'habitude de traiter le routage via Linux et NetFilter. Quelle est la différence, dans le traitement des paquets, entre INPUT et PREROUTING, également entre OUTPUT et POSTROUTING.

La différence entre INPUT et OUPUT est facile à saisir, entre les deux, il y a le traitement des paquets par la couche applicative (exemple : votre serveur web qui reçoit une donnée, qui en renvoie une autre).

Il manque en fait une information dans mon dernier schéma, il s'agit des décisions de routage, et c'est sur ce point que l'on peut comprendre aisément la différence entre INPUT et PREROUTING par exemple. Voyons un schéma un peu plus complet :

schema-nftables-netfilter-hooks-04

On voit donc que, entre les hooks PREROUTING et INPUT, il y a une décision de routage, c’est-à-dire que le système va analyser si le paquet traité est pour lui ou non. Si c'est le cas, il va l'envoyer vers la couche applicative où il croise le hook INPUT. Si ce n'est pas le cas, il va l'envoyer vers la sortie de l'interface réseau où il croisera le hook FORWARD et ne passera pas par les hooks INPUT et OUTPUT. On saisit alors mieux le sens de ces hooks. Ils sont là pour appliquer un filtre ou une action (dans le cadre du NAT par exemple) quand les paquets réseaux ne passent pas nécessairement par la couche applicative.

Si vous vous demandez dans quel contexte on peut avoir une arrivée de paquet qui ne nous est pas destinée sans que nous ayons à le jeter directement, la réponse la plus courante est le cas où votre système est un routeur. Lorsque l'on fait du NAT par exemple, les paquets qui traversent votre routeur, mais qui ne sont pas en destination de votre couche applicative sont traités par les chaines PREROUTING, FORWARD puis POSTROUTING. Nous verrons un peu plus loin dans le cours comment faire du NAT avec nftables. Dans d'autres cas, la chaine PREROUTING permet de modifier les paquets en leur état brut avant qu'ils soient traités par les décisions de routage.

Dans le prochain chapitre, nous allons voir de plus près les notions de tables, chaines et règles. Cela vous permettra de faire le lien avec les hooks.

author avatar
Mickael Dorigny Co-founder
Co-fondateur d'IT-Connect.fr. Auditeur/Pentester chez Orange Cyberdéfense.
Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Envoyer par mail