Configurer le NAT sous NFtables

Chapitre Progression:

Nous allons maintenant apprendre à mettre en place et gérer du NAT dans NFtables, cela peut être particulièrement utile dans le cas ou votre machine Linux utilisant NFtables est un routeur pour d'autres machines par exemple.

En effet, le principe du NAT est de modifier les IP sources des paquets qui passent au travers notre routeur.

Note : Dans le cadre d'un NAT, il faut bien sûr que votre machine Linux soit un routeur. Pour cela, pensez à activer l'IP forwarding qui permet d'autoriser le fait de faire passer des paquets réseaux d'une interface vers une autre avec la commande "echo 1 > /proc/sys/net/ipv4/ip_forward"

I. NAT MASQUERADE

Pour gérer correctement le NAT, il va falloir créer une chaine, dans une table déjà existante par exemple qui se nommera "mon_filtreIPv4". Ces chaines s'appliqueront sur les Hook PREROUTING et POSTROUTING.

Note : cette fonctionnalité de NFtables n'est disponible que depuis la version 3.18 du kernel Linux

Si vous avez du mal à comprendre ce dernier paragraphe, je vous propose de retourner voir le chapitre 1 du module 2 qui présente le fonctionnement de NetFilter et de NFtables.

nft add table mon_filtreIPv4
nft add chain mon_filtreIPv4 prerouting { type nat hook prerouting priority 0 \; }
nft add chain mon_filtreIPv4 postrouting { type nat hook postrouting priority 0 \; }

Bien entendu, cela peut se faire en plus des règles que nous avons mises en place dans les cours précédents. Pour rappel, une table contient des chaines qui s'appliquent chacune d'elles à un Hook spécifique.

Nous allons commencer par faire le cas le plus basique de NAT, le NAT Source. Le fonctionnement est très simple. Pour chaque paquet qui va sortir d'une interface (qui passe donc par le Hook POSTROUTING ;)), nous allons remplacer l'adresse IP source de ces paquets par l'adresse IP de l'interface par laquelle il sort.

Exemple pratique :

nftables-linux-nat-01

Dans cet exemple. Si le client A communique avec le client B, l'IP source des paquets arrivant sur le client B sera 192.168.1.100 (l'IP du client A). Le problème que l'on rencontre souvent lorsque l'on aborde le routage est le fait que la route retour n'est pas opérationnelle.

Autrement dit, le client B ne connait pas obligatoirement la route à prendre pour répondre à cette plage IP (192.168.1.0/24) et peut donc envoyer ses réponses à la mauvaise passerelle. Un des buts du NAT est de contourner ce problème en faisant en sorte qu'à chaque fois que le client A enverra un paquet vers l'extérieur (un paquet qui sortira de l'interface 192.168.2.1 de notre routeur), celui-ci remplacera l'IP source des paquets par l'IP de l'interface de sortie (192.168.1.100 sera donc remplacé par 192.168.2.1). Ainsi, le client B saura répondre à ces paquets, car l'IP 192.168.2.1 est dans son LAN, sur ce que l'on appelle une route directe.

Quand les paquets reviendrons, notre routeur effectuera l'opération inverse et retrouvera, grâce à un système de port, à qui est destiné ce paquet, c’est-à-dire au client A.

Il faut, pour comprendre cette partie, avoir déjà quelques connaissances au niveau du routage et de la façon dont transitent les paquets sur un réseau.

Pour mettre en place du source NAT, rien de plus simple. Nous allons commencer par créer une chaine "postrouting" que l'on attachera au Hook et une chaine "prerouting" du même nom dans notre bien aimée table "mon_filtreIPv4" :

nft add table mon_filtreIPv4
nft add chain mon_filtreIPv4 prerouting { type nat hook prerouting priority 0 \; }
nft add chain mon_filtreIPv4 postrouting { type nat hook postrouting priority 0 \; }

Nous allons ensuite "simplement" ajouter une règle qui permettra de faire du masquerade :

nft add rule mon_filtreIPv4 postrouting masquerade

À ce stade, votre client A et votre client B pourront se pinguer dans les deux sens. Et je le précise bien, car ce n'est pas un NAT comme tout le monde pourrait s'y attendre. En effet, la source NAT que nous venons de faire marche dans les deux sens et ne protège en aucun cas un réseau d'en voir un autre.

Pour que le réseau du client A soit totalement injoignable depuis le réseau du client B, il faut que nous mettions en place un autre type de source NAT, qui sera, lui, unidirectionnel. Les clients B ne pourront communiquer avec les clients A que si ces derniers les ont sollicités. Cela apporte de la sécurité, car le réseau A est "caché". Même si ce n'est pas pour cela que le NAT a été créé à la base ;).

II. Source NAT unidirectionnel

Pour effectuer un source NAT qui ne fonctionne que dans un sens, il faut de nouveau créer notre structure avec une chaine liée au hook prerouting et une chaine liée au hook postrouting.

Ensuite, nous allons faire en sorte que, tous les paquets qui viennent de la plage IP du réseau de notre client A (192.168.1.0/24 et sortant par l'interface eth1 (celle qui se trouve du côté du réseau B) auront leur adresse IP source réécrite en 192.168.2.1, l'adresse IP de l'interface du réseau B :

nft add rule mon_filtreIPv4 postrouting ip saddr 192.168.1.0/24 oif eth1 snat 192.168.2.1

Ici, nous précisons donc bien dans la chaine "postrouting" que tous les paquets ayant comme adresse IP source une adresse dans la plage IP 192.168.1.0/24 et qui sorte par l'interface eth1 "oif" pour "output interface" en opposition a "iif" pour "input interface" verront leur IP source remplacée par 192.168.2.1.

 Note : Vous avez peut être remarqué que nous avons créé la chaine "prerouting" liée au hook "PREROUTING" mais que nous n'avons rien mis dedans. Cependant, il ne faut pas la supprimer et son existence est importante pour le bon fonctionnement du NAT. En effet, si la chaine "postrouting" est utilisée pour les paquets sortants, la chaine "prerouting" est utile pour effectuer l'opération inverse quand les paquets reviennent, et cela de façon implicite.

III. Destination NAT

Maintenant que nous avons vu comment faire du NAT, nous allons voir comment créer une exception dans ce NAT. En effet, il arrive que l'on ait besoin de faire du "destination NAT". Plus clairement, dans un contexte de NAT comme actuellement ou dans certains autres contextes, on veut créer des exceptions et dire que si l'adresse IP externe de notre routeur reçoit des paquets sur le port 21 par exemple, il faudra les rediriger vers une machine qui est dans le LAN ("caché" derrière le NAT). C'est ce qui est appelé le destination NAT.

C'est en fin de compte l'opération inverse de ce que nous venons de faire. Ici, on remplace l'adresse IP de destination des paquets qui arrivent.

Un exemple pratique :

Dans ce schéma, le Client B veut se rendre sur le serveur FTP qui est dans le réseau "naté". Il va donc communiquer avec le "représentant" de ce réseau qui est le routeur Linux, sur son port 21 :

nftables-linux-nat-02

Grâce au destination NAT, les paquets arrivant sur le routeur Linux avec pour port destination le port 21 auront l'IP de destination 192.168.2.1. Nous allons donc créer une règle qui dit que quand l'IP de destination est 192.168.2.1 et que le port visé est le port 21, nous allons rediriger ces paquets vers l'IP 192.168.1.102, toujours sur le port 21.

Ainsi, le client B parviendra à joindre le serveur FTP dans le réseau "naté" (car nous l'avons décidé ;)). Pour mettre en place un destination NAT, nous avons toujours besoin de notre chaine "prerouting" et "postrouting"

nft add table mon_filtreIPv4
nft add chain mon_filtreIPv4 prerouting { type nat hook prerouting priority 0 \; }
nft add chain mon_filtreIPv4 postrouting { type nat hook postrouting priority 0 \; }

Sur la chaine "prerouting" cette fois, nous allons appliquer notre règle de destination NAT :

nft add rule nat prerouting iif eth1 tcp dport 21 dnat 192.168.1.102

On précise donc bien que, tous les paquets arrivant sur l'interface eth1 et avec pour port de destination le port 21 seront modifiés pour que leur adresse IP de destination devienne 192.168.1.102.

Encore une fois, nous créons la chaine postrouting sans ajouter de règle à l'intérieur, mais sa création est une condition du bon fonctionnement du DNAT, car elle permet de traiter les paquets durant leur retour (à inverser le processus de NAT donc ;)).

Avez-vous noté la différence dans le paramétrage du DNAT et du SNAT ? Dans le DNAT, on configure la chaine prerouting, liée au Hook "PREROUTING", car on souhaite réécrire les paquets avant qu'ils ne soient traités par les systèmes de filtrages. En revanche dans le SNAT, on réécrit les paquets après qu'ils soient passés dans le système de filtrage. Nous n'utilisons d'ailleurs pas les Hooks OUTPUT et INPUT, car les paquets ne sont, notamment dans le cadre du SNAT, pas destiné à la machine "Linux Routeur" par laquelle ils transitent. On utilise donc la chaine "postrouting" liée au Hook " POSTROUTING"

Et si je veux rediriger ce qui arrive sur le port 2121 du routeur vers le port 21 de mon serveur LAN, c'est possible ?

Eh bien oui, voici la syntaxe à utiliser :

nft add rule mon_filtreIPv4 prerouting iif eth0 tcp dport 2121 dnat 192.168.240.131:21

Ici, on rajoute simplement le port de destination en plus de l'IP pour le serveur LAN.

Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Partager sur Google+ Envoyer par mail

    Mickael Dorigny

    Co-fondateur d'IT-Connect.fr. Auditeur en sécurité des systèmes d'information chez Amossys

      mickael has 502 posts and counting.See all posts by mickael