65 votes

Faire une boucle vers l'adresse IP publique transférée depuis le réseau local - NAT en boucle

Il s'agit d'une Question Canonique sur le Hairpin NAT (NAT en boucle).

La forme générique de cette question est :

Nous avons un réseau avec des clients, un serveur et un routeur NAT. Il y a une redirection de port sur le routeur vers le serveur pour que certains de ses services soient disponibles de l'extérieur. Nous avons un DNS pointant vers l'IP externe. Les clients du réseau local ne parviennent pas à se connecter, mais les externes le peuvent.

  • Pourquoi cela échoue-t-il ?
  • Comment puis-je créer un système de nommage unifié (noms DNS qui fonctionnent à la fois localement et de l'extérieur) ?

Cette question contient des réponses fusionnées de plusieurs autres questions. Elles faisaient initialement référence à FreeBSD, D-Link, Microtik et d'autres équipements. Cependant, elles essaient toutes de résoudre le même problème.

1 votes

Si votre objectif est de tester l'accès depuis internet, il est inutile de manipuler les routes du routeur et/ou les paramètres DNS de toute façon, car au mieux, de l'intérieur, vous vérifieriez que la partie intérieure du routeur fonctionne. Je vous suggère d'utiliser un serveur proxy quelque part à l'extérieur.

75voto

MadHatter Points 77602

Étant donné que cette question a été élevée au statut de question canonique sur le NAT en épingle à cheveux, j'ai pensé qu'elle devrait probablement avoir une réponse plus généralement valable que celle actuellement acceptée, qui (bien qu'excellente) se rapporte spécifiquement à FreeBSD.

Cette question s'applique aux services fournis par des serveurs sur des réseaux IPv4 adressés en RFC1918, qui sont rendus disponibles aux utilisateurs externes en introduisant un NAT de destination (DNAT) au niveau de la passerelle. Les utilisateurs internes essaient ensuite d'accéder à ces services via l'adresse externe. Leur paquet sort alors du client vers le dispositif de passerelle, qui réécrit l'adresse de destination et l'injecte immédiatement de nouveau dans le réseau interne. C'est ce virage brusque que fait le paquet à la passerelle qui donne lieu au nom de NAT en épingle à cheveux, par analogie avec le virage en épingle à cheveux.

Le problème survient lorsque le dispositif de passerelle réécrit l'adresse de destination, mais pas l'adresse source. Le serveur reçoit alors un paquet avec une adresse de destination interne (la sienne) et une adresse source interne (celle du client); il sait qu'il peut répondre directement à une telle adresse, alors il le fait. Comme cette réponse est directe, elle ne passe pas par la passerelle, qui n'a donc jamais la possibilité d'équilibrer l'effet du NAT de destination entrant sur le paquet initial en réécrivant l'adresse source du paquet de retour.

Le client envoie donc un paquet à une adresse IP externe, mais reçoit une réponse d'une adresse IP interne. Il n'a aucune idée que les deux paquets font partie de la même conversation, donc aucune conversation ne se produit.

La solution est que pour les paquets nécessitant un tel NAT de destination et qui atteignent la passerelle depuis le réseau interne, effectuer également un NAT de source (SNAT) sur le paquet entrant, généralement en réécrivant l'adresse source pour qu'elle corresponde à celle de la passerelle. Le serveur pense alors que le client est la passerelle elle-même, et lui répond directement. Cela donne à la passerelle l'occasion d'équilibrer les effets à la fois du DNAT et du SNAT sur le paquet entrant en réécrivant à la fois les adresses source et destination du paquet de retour.

Le client pense qu'il communique avec un serveur externe. Le serveur pense qu'il communique avec le dispositif de passerelle. Toutes les parties sont satisfaites. Un diagramme peut être utile à ce stade :

entrer la description de l'image ici

Certains dispositifs de passerelle grand public sont assez malins pour reconnaître les paquets pour lesquels la deuxième étape du NAT est nécessaire, et ceux-ci fonctionneront probablement sans problème dans un scénario de NAT en épingle à cheveux. D'autres ne le sont pas et ne le feront donc pas, et il est peu probable qu'ils puissent être configurés pour fonctionner. Une discussion sur quels dispositifs grand public sont de telle nature est hors-sujet pour le site Server Fault.

Les dispositifs réseau appropriés peuvent généralement être configurés pour fonctionner, mais - parce qu'ils ne sont pas là pour deviner ce que veulent leurs administrateurs - ils doivent se voir dire de le faire. Linux utilise iptables pour réaliser le DNAT comme ceci :

iptables -t nat -A PREROUTING  -p tcp --dport 80 -j DNAT --to-destination 192.168.3.11

ce qui permettra un DNAT simple pour le port HTTP, vers un serveur interne sur 192.168.3.11. Mais pour activer un NAT en épingle à cheveux, il faudrait également une règle telle que :

iptables -t nat -A POSTROUTING -d 192.168.3.11 -p tcp --dport 80 -j MASQUERADE

Il est à noter que de telles règles doivent être placées correctement dans les chaînes pertinentes pour fonctionner correctement, et selon les paramètres de la chaîne filter, des règles supplémentaires peuvent être nécessaires pour permettre au trafic NAT de circuler. Toute discussion de ce genre est hors du périmètre de cette réponse.

Mais comme d'autres l'ont dit, activer correctement le NAT en épingle à cheveux n'est pas la meilleure façon de gérer le problème. La meilleure est le DNS à zones séparées, où votre organisation fournit des réponses différentes pour la recherche initiale en fonction de l'emplacement du client demandeur, soit en ayant des serveurs physiques différents pour les utilisateurs internes et externes, soit en configurant le serveur DNS pour répondre différemment en fonction de l'adresse du client demandeur.

0 votes

Je me demande un peu sur les adresses des paquets échangés entre la passerelle et le serveur. Ne serait-il pas plus cohérent que le serveur voie l'adresse IP publique du routeur comme l'IP du client? Techniquement, les deux peuvent fonctionner, mais pour rester cohérent avec la façon dont les autres serveurs voient les clients, il faudrait utiliser l'IP publique.

2 votes

Je suppose que vous faites référence au dernier cas, "NAT de pince à cheveux approprié". La chose cruciale est de réécrire l'adresse source sur le paquet entrant de manière à ce qu'il revienne au routeur, qui peut alors inverser à la fois le DNAT et le SNAT et ainsi éviter le problème. Le choix de l'adresse parmi ses nombreuses adresses que le routeur utilise pour faire cela est plutôt une question de préférence, et si vous le faites avec iptables, c'est certainement quelque chose que vous pouvez configurer si vous le souhaitez.

1 votes

De nombreux administrateurs, moi inclus, considèrent le DNS à double vue comme un remède pire que le mal. Si on peut considérer un SNAT supplémentaire comme un mal. Un DNS à double vue confond les humains tout en facilitant la vie des routeurs. Ce sujet serait mieux traité par une question / réponse séparée sur ServerFault.

22voto

Evan Anderson Points 140581

Ce que vous recherchez s'appelle "hairpin NAT". Les demandes provenant de l'interface interne pour une adresse IP assignée à l'interface externe doivent être NAT'tées comme si elles provenaient de l'interface côté externe.

Je n'ai aucune connaissance de FreeBSD, mais en lisant le manuel "pf" pour OpenBSD (http://www.openbsd.org/faq/pf/rdr.html) les solutions proposées de DNS à double horizon, d'utilisation d'un réseau DMZ ou de proxy TCP me laissent penser que "pf" ne prend pas en charge le hairpin NAT.

Je considérerais d'adopter la solution du DNS à double horizon et de ne pas utiliser les adresses IP dans les URL en interne, mais plutôt d'utiliser des noms.

0 votes

Je suis tombé sur ce fil en essayant de résoudre le même problème, et même s'il est vrai que FreeBSD ne prend pas en charge le NAT de type hairpin par défaut, il existe des moyens de rediriger le trafic interne -> externe -> interne avec le NAT.

0 votes

Par exemple: pas de nat sur $int_if proto tcp de $int_if à $int_net, nat sur $int_if proto tcp de $int_net à $hairpin_int port $hairpin_ports -> $int_if, rdr sur $int_if proto tcp de $int_net à $ext_if port $hairpin_ports -> $hairpin_int

13voto

liangzan Points 1733

Le problème ici est que votre routeur ne traduit pas l'adresse IP interne de votre client. Ainsi, le handshake TCP échoue.

Supposons les adresses IP suivantes

  • Client : 192.168.1.3
  • Serveur : 192.168.1.2
  • Routeur interne : 192.168.1
  • Routeur externe : 123.123.123.1

Voici ce qui se passe :

  1. Le client (192.168.1.3) envoie un TCP-SYN à votre IP externe, Port 80 (123.123.123.1:80)
  2. Le routeur voit la règle de redirection de port et transfère le paquet au serveur (192.168.1.2:80) sans changer l'IP source (192.168.1.3)
  3. Le client attend un SYN-ACK de l'IP externe
  4. Le serveur renvoie sa réponse directement au client, car il est sur le même sous-réseau. Il n'envoie pas le paquet au routeur, qui inverserait la NAT.
  5. Le client reçoit un SYN-ACK de 192.168.1.2 au lieu de 123.123.123.1. Et le rejette.
  6. Le client attend toujours un SYN-ACK de 123.123.123.1 et finit par expirer.

4voto

jeremcc Points 3720

Pourquoi ne pas utiliser le DNS à horizon partagé au lieu de coder en dur des adresses IP partout? Vous auriez ext.votredomaine pointant vers 217.x.x.x à l'extérieur, et ensuite 192.x.x.x à l'intérieur.

1 votes

Si vous avez un moment, pourriez-vous développer sur ce qu'est le DNS à double horizon, comment cela fonctionne et les principaux inconvénients. C'est maintenant une question canonique et ce serait bien d'avoir une réponse plus complète.

3voto

Sergio Points 164

Récemment répondu à une question similaire : Cisco static NAT not working on LAN side et je viens de réaliser qu'il s'agit d'une Question Canonique. Permettez-moi donc de résumer la solution ici.

Tout d'abord : oubliez le NAT (si vous le pouvez) - la question ne concerne pas du tout la configuration du NAT. Il s'agit d'accéder à un serveur placé derrière un NAT à la fois depuis Internet et depuis le LAN. L'utilisation de deux zones DNS est une solution viable, mais pas toujours la solution. Cependant, la solution existe et est incroyablement simple (bien que pas parfaite, probablement) :

(1) sur le serveur : ajoutez l'adresse IP publique en tant qu'adresse IP secondaire sur l'interface réseau du serveur avec le masque 255.255.255.255 (le service web ou tout autre service sur le serveur doit également écouter cette adresse IP) ; tous les systèmes d'exploitation modernes vous permettront de le faire (ou une interface de bouclage avec l'adresse IP publique attribuée peut être utilisée à la place d'ajouter une IP secondaire à l'interface principale).

(2) sur les hôtes du LAN : ajoutez une route hôte pour l'adresse IP publique, par exemple, pour les hôtes Windows utilisez la commande suivante : route -p add 203.0.113.130 mask 255.255.255.255 192.168.1.11 (vous pouvez également utiliser l'option "route statique" DHCP pour distribuer la route). Ou, s'il y a des commutateurs/routeurs L3 entre les clients et le routeur faisant face à Internet, configurez cette route hôte sur ces commutateurs/routeurs intermédiaires, pas sur les clients.

Pour ceux qui se préoccupent de l'établissement de connexion TCP en trois phases : cela fonctionnera correctement dans la configuration proposée.

Veuillez fournir des retours (au moins, voter).

1 votes

La exigence n°2 fait que cela ne fonctionne pas bien sur les réseaux BYOD...

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X