La cible DNAT est
utilisée pour la Traduction d'Adresse Réseau de Destination, ce qui
veut dire qu'elle sert à réécrire l'adresse IP
de Destination
du paquet. Si un paquet est sélectionné, et
qu'il est la cible de la règle, ce paquet et tous les paquets
suivants du même flux seront traduits, et ensuite routés vers le
matériel, l'hôte ou le réseau appropriés. Cette cible peut être
extrêmement utile, par exemple, quand vous avez un hôte avec un
serveur web dans un LAN,
mais pas d'IP réelle routable sur l'Internet. Vous pouvez alors
indiquer au pare-feu de transférer tous les paquets allant vers son
propre port HTTP, vers le serveur web réel dans le LAN. Vous pouvez aussi spécifier une
plage d'adresses IP de destination, et le mécanisme DNAT choisira l'adresse IP de
destination au hasard pour chaque flux. Nous pourrons donc réaliser
une sorte d'équilibrage de charge en faisant ça.
Notez que la cible DNAT est disponible uniquement
dans les chaînes PREROUTING
et
OUTPUT
de la table nat. Les chaînes
contenant des cibles DNAT ne peuvent pas être
utilisées depuis d'autres chaînes, comme la chaîne POSTROUTING
.
Tableau 11.5. Options de la cible DNAT
Option | --to-destination |
Exemple | iptables -t nat -A PREROUTING -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10 |
Explication | L'option --to-destination indique au
mécanisme DNAT quelle Destination IP placer dans l'en-tête IP, et où
sont envoyés les paquets qui sont sélectionnés. L'exemple ci-dessus
enverra tous les paquets destinés à l'adresse IP 15.45.23.67 dans
une plage IP de réseau local comprise entre 192.168.1.1 jusqu'à
192.168.1.10. Notez que, comme décrit précédemment, un simple flux
utilisera toujours le même hôte, et chaque flux aura une adresse IP
attribuée au hasard, et qui sera toujours en direction de quelque
part, dans ce flux. Nous pouvons aussi avoir à spécifier une seule
adresse IP, dans ce cas nous serons toujours connectés au même
hôte. Notez aussi que nous pouvons ajouter un port ou une plage de
ports vers lequel le trafic sera redirigé. Ceci se fait en
ajoutant, par exemple, un :80 à l'adresse IP pour laquelle nous
voulons traduire les paquets. Une règle peut alors ressembler à
--to-destination
192.168.1.1:80 par exemple, ou --to-destination
192.168.1.1:80-100 si nous voulons spécifier une
plage de ports. Comme vous pouvez le voir, la syntaxe est à peu
près la même que la cible SNAT, même si elles font deux
choses totalement différentes. Les spécifications de port sont
valides uniquement pour les règles qui précisent les protocoles TCP
ou UDP avec l'option --protocol. |
Comme DNAT nécessite pas mal de travail pour fonctionner correctement, j'ai décidé d'ajouter une explication plus complète sur ce sujet. Prenons un bref exemple pour comprendre comment les choses se passent normalement. Nous voulons publier notre site web via notre connexion Internet. Nous ne possédons qu'une seule adresse IP, et le serveur HTTP est situé dans notre réseau interne. Notre pare-feu possède l'adresse IP externe $INET_IP, et notre serveur HTTP a l'adresse IP interne $HTTP_IP et enfin le pare-feu a l'adresse IP interne $LAN_IP. La première chose à faire est d'ajouter la simple règle suivante à la chaîne PREROUTING dans la table nat :
iptables -t nat -A PREROUTING --dst $INET_IP -p tcp --dport 80 -j DNAT \
--to-destination $HTTP_IP
Maintenant, tous les paquets provenant de l'Internet et allant vers le port 80 sur notre pare-feu, sont redirigés (ou DNATés) vers notre serveur HTTP interne. Si vous testez ceci depuis L'Internet, tout devrait fonctionner parfaitement. mais, que se passe-t-il si vous essayez de vous connecter depuis un hôte sur le même réseau local que le serveur HTTP ? Il ne fonctionnera tout simplement pas. C'est un réel problème avec le routage. Commençons par voir ce qui se passe dans un cas normal. La machine externe possède une adresse IP $EXT_BOX, pour conserver la lisibilité.
-
Le paquet quitte l'hôte connecté allant vers $INET_IP et la source $EXT_BOX.
-
Le paquet atteint le pare-feu.
-
Le pare-feu DNAT le paquet et envoie celui-ci à travers les différentes chaînes, etc.
-
Le paquet quitte la pare-feu pour aller vers le $HTTP_IP.
-
Le paquet atteint le serveur
HTTP
, et la machine HTTP répond en retour à travers le pare-feu, si c'est cette machine que la base de routage a entré comme passerelle pour $EXT_BOX. Normalement, ça devrait être la passerelle par défaut du serveur HTTP. -
Le pare-feu Un-DNAT le paquet de nouveau, ainsi le paquet semble provenir du pare-feu lui-même.
-
Le paquet en réponse transite vers le client $EXT_BOX.
Maintenant, voyons ce qui se passe si le paquet est généré par un client sur le même réseau que le serveur HTTP lui-même. Le client possède l'adresse IP $LAN_BOX, tandis que les autres machines ont les mêmes réglages.
-
Le paquet quitte la $LAN_BOX vers $INET_IP.
-
Le paquet atteint le pare-feu.
-
Le paquet est DNATé, et toutes les autres actions requises sont prises, cependant, le paquet n'est pas SNATé, ainsi la même adresse source IP est utilisée pour le paquet.
-
Le paquet quitte le pare-feu et atteint le serveur HTTP.
-
Le serveur HTTP essaie de répondre au paquet, et voit dans les tables de routage que le paquet provient d'une machine locale sur le même réseau, et donc tente d'envoyer le paquet directement à l'adresse source IP d'origine (qui devient alors l'adresse IP de destination).
-
Le paquet atteint le client, et le client est dans la confusion car le paquet en retour ne provient pas de l'hôte qui a envoyé la requête d'origine. Donc, le client supprime le paquet, et attend une réponse "réelle".
La solution la plus simple à ce problème est de SNATer tous les paquets entrants dans le pare-feu sortant vers un hôte ou une IP sur lequel nous faisons du DNAT. Exemple, regardons la règle ci-dessus. Nous SNATons les paquets entrants dans notre pare-feu qui sont destinés à $HTTP_IP port 80 et ainsi il est vu que des paquets proviennent d'une $LAN_IP. Ceci force le serveur HTTP à envoyer ces paquets vers notre pare-feu, lequel Un-DNAT ceux-ci et les envoie au client. La règle ressemble à ceci :
iptables -t nat -A POSTROUTING -p tcp --dst $HTTP_IP --dport 80 -j SNAT \
--to-source $LAN_IP
Souvenez vous que la chaîne POSTROUTING
est exécutée en dernier, et donc le
paquet sera déjà DNATé une fois qu'il joint cette
chaîne spécifique. C'est la raison pour laquelle nous sélectionnons
les paquets basés sur une adresse interne.
Avertissement | |
---|---|
Cette dernière règle nuira sérieusement à votre journalisation, ainsi il n'est pas recommandé d'utiliser cette méthode, mais l'ensemble de l'exemple est valide. Que se passe-t-il alors, le paquet provient de l'Internet, est SNATé et DNATé et finalement atteint le serveur HTTP (par exemple). Le serveur HTTP voit maintenant les requêtes comme si elles provenaient du pare-feu, et donc journalisera toutes ces requêtes provenant de l'Internet comme si elles provenaient du pare-feu. Ceci peut avoir également d'autres implications plus graves. Prenons un serveur SMTP sur un LAN, qui autorise les requêtes depuis le réseau interne, et vous avez un pare-feu paramétré pour transférer le trafic SMTP vers ce serveur. Vous avez donc créé un serveur SMTP en relais ouvert, avec une journalisation horrible ! Une solution à ce problème est de rendre la règle SNAT plus spécifique dans sa partie sélection, et de travailler seulement sur les paquets qui proviennent du LAN. En d'autres termes, ajoutez un -i $LAN_IFACE à l'ensemble de la commande. Ceci fera que la règle ne fonctionnera que sur les flux provenant du LAN, et donc n'affectera pas la source IP, ainsi les journaux seront corrects, sauf pour les flux venant du LAN. Vous auriez mieux fait, en d'autres termes, de résoudre ces problèmes soit en paramétrant un serveur DNS (serveur de nom) séparé pour votre LAN, soit en paramétrant une DMZ séparée, la dernière étant préférable si vous en avez les moyens. |
Vous pouvez penser que c'est suffisant, et c'est vrai, sauf à
considérer un dernier aspect du scénario. Que se passe-t-il si le
pare-feu lui-même essaie d'accéder au serveur HTTP, où va-t-il ? Il
tentera malheureusement d'accéder à son propre serveur HTTP, et pas
au serveur situé sur $HTTP_IP. Pour parer à ça, nous
devons rajouter une règle DNAT à la chaîne OUTPUT
. Suivant l'exemple ci-dessus, ça
ressemblerait à quelque chose comme :
iptables -t nat -A OUTPUT --dst $INET_IP -p tcp --dport 80 -j DNAT \
--to-destination $HTTP_IP
Tous les réseaux séparés qui ne sont pas situés sur le même réseau que le serveur HTTP fonctionneront sans soucis, tous les hôtes sur le même réseau que le serveur HTTP pourront s'y connecter et enfin, le pare-feu pourra exécuter ses connexions correctement. Maintenant, tout fonctionne et aucun problème ne devrait survenir.
Note | |
---|---|
Tout le monde devrait réaliser que ces règles affectent seulement la façon dont le paquet est DNATé et SNATé. En plus de ces règles, nous avons aussi besoin de règles supplémentaires dans la table filter (chaîne FORWARD) pour permettre aux paquets de traverser ces chaînes. N'oubliez pas que tous les paquets sont déjà passés par la chaîne PREROUTING, et donc ont vu leur adresse de destination réécrite par DNAT. |
Note | |
---|---|
Fonctionne avec les noyaux Linux 2.3, 2.4, 2.5 et 2.6. |