Vous ajoutez une règle pour le trafic VPN dans la chaîne FORWARD, lancez la requête depuis la même machine Linux, et le compteur reste à zéro. La règle est probablement correcte. Le paquet n’a jamais emprunté ce chemin, car une requête générée sur la machine elle-même n’est pas réacheminée par elle. Suivre la vie du paquet du socket au câble explique pourquoi, et où la règle doit plutôt se trouver.

Trouvez où le paquet est né

L’ordre des hooks de Netfilter sépare trois cas, et un seul d’entre eux implique FORWARD :

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

Une application locale commence dans le chemin OUTPUT, car le noyau a déjà établi que le paquet prend naissance ici et n’est jamais candidat au réacheminement. Créer un tunnel ne change pas cette classification ; le tunnel est un périphérique par lequel le paquet peut sortir, pas une étape qui transforme la sortie locale en transit.

Deux paquets, une histoire

Une fois le tunnel monté, le paquet interne de l’application et le paquet externe chiffré sont des objets différents. Le paquet interne porte la destination et la charge utile choisies par l’application. Le paquet externe porte du texte chiffré vers l’adresse et le port du pair, et c’est lui qui traverse réellement l’interface physique.

Votre politique concerne l’un des deux, et choisir le mauvais est une cause fréquente de règle qui semble ne rien faire. Une règle qui correspond à l’adresse externe du pair voit chaque paquet du tunnel de la même façon, quoi que fasse l’application à l’intérieur. Une règle qui correspond à une destination interne voit le trafic qui vous intéresse, et elle ne se déclenchera que si ce paquet atteint le hook sur lequel vous avez installé la règle.

Les espaces de noms déplacent la frontière

Un conteneur complique les choses sans changer le principe. La requête de l’application est une sortie locale à l’intérieur de l’espace de noms réseau du conteneur. L’hôte reçoit ce trafic sur une interface Ethernet virtuelle et peut le réacheminer, donc une règle FORWARD sur l’hôte peut avoir du sens même si le processus qui a généré la requête n’a jamais touché la chaîne OUTPUT de l’hôte.

Avant de choisir un hook, établissez où vivent réellement le jeu de règles et le tunnel. Un tunnel dans le conteneur, un tunnel sur l’hôte avec le conteneur routé à travers lui, et un tunnel dans un espace de noms séparé sont trois topologies différentes avec trois emplacements de règles différents. Lisez les règles dans l’espace de noms qui possède le périphérique, pas seulement dans celui par défaut.

Demandez-vous si une marque est vraiment nécessaire

Si l’objectif est d’envoyer un préfixe de destination dans le tunnel, une route pour ce préfixe peut suffire. Vérifiez d’abord les routes effectives, y compris tout ce que le serveur a poussé : une route par défaut redirigée envoie bien plus de trafic par le VPN que la politique étroite que vous aviez en tête, et aucun marquage ne fera correspondre le résultat à l’intention.

La classification est nécessaire quand la décision dépend de quelque chose qu’une route ne peut pas exprimer, comme la source, l’utilisateur ou le processus. Pour le trafic reçu, le marquage dans PREROUTING fonctionne. Pour le trafic local, le marquage doit se faire dans une étape de sortie capable de déclencher une nouvelle recherche de route une fois la marque posée. Avec nftables, c’est une chaîne de type route sur le hook de sortie ; une chaîne de filtre de sortie ordinaire posera la valeur et laissera la route inchangée.

Avec iptables, l’équivalent vit dans l’agencement mangle OUTPUT, et la même exigence s’applique : la décision de routage doit être revue après l’existence de la marque. Ensuite, une règle de politique doit consommer la marque et pointer vers une table contenant une route utilisable. Poser une marque conntrack est une troisième opération, distincte ; elle stocke une valeur sur le flux et ne place pas d’elle-même cette valeur sur le paquet courant pour que le routage la lise.

Vérifiez la recherche et le compteur ensemble

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

L’adresse et la marque sont illustratives, et les deux requêtes de route répondent à des questions différentes. La seconde demande ce que ferait le noyau si un paquet portait cette marque ; elle ne montre pas que votre jeu de règles en attribue une. Traitez-la comme un test d’hypothèse, pas comme la preuve que la politique fonctionne.

Lancez ensuite une requête inoffensive et observez deux choses à la fois : le compteur du hook choisi et la sortie que le paquet a réellement prise. Si le compteur bouge et que le paquet sort ailleurs, la marque ou la table est fausse. Si aucun des deux ne bouge, le paquet n’atteint pas du tout ce hook, et l’espace de noms ou le chemin est la question suivante.

Enfin, limitez le test à ce que le mécanisme peut exprimer. Une route pour une adresse ne devient pas une politique permanente pour un service dont les adresses tournent. Décidez d’abord la portée des paquets, puis vérifiez que la conception de routage et de marquage peut tenir cette portée après une reconnexion.

Articles similaires