Atteindre un /24 distant par un tunnel : NETMAP, DNAT ou route ?
Mappez tout un préfixe avec NETMAP, ajoutez des règles DNAT par hôte ou routez la plage réelle, et décidez selon ce que le côté distant doit voir et qui peut initier le trafic.
Vous pouvez atteindre un sous-réseau derrière une extrémité de tunnel de trois façons, et une minute de collecte de faits en écarte généralement deux. Les faits sont : les serveurs là-bas doivent-ils distinguer les utilisateurs, quelqu’un là-bas appellera-t-il un jour vers votre plage, et qui peut modifier le routeur de l’extrémité distante. Répondez à ces trois questions et la conception se choisit d’elle-même. Le reste suppose que vous exploitez l’extrémité et pouvez modifier son pare-feu.
Trois options, et ce que chacune change réellement
Le mappage de préfixe, le DNAT par hôte et un préfixe routé déplacent tous des paquets entre les mêmes deux plages, mais changent des choses différentes. Le mappage invente une plage d’alias et réécrit les adresses arithmétiquement en vol. Les règles par hôte réécrivent aussi, sauf que chaque destination est nommée à la main. Un préfixe routé ne réécrit rien : les paquets gardent les adresses réelles et les deux extrémités s’accordent sur l’endroit où vivent ces adresses.
| What the far side needs | Prefix mapping | Per-host DNAT | Routed prefix |
|---|---|---|---|
| Users visible to its logs | Only without source NAT | Same condition | Yes, unchanged |
| To start a connection toward you | No, alias is local | No, same reason | Yes, both ends route |
| To absorb a new host | Yes, arithmetic only | No, one rule per address | Yes, it simply routes |
| To require no config change | Yes, with source NAT | Yes, same condition | No, it needs a route back |
Commencez l’élimination par le côté distant, où les contraintes sont les plus difficiles à changer. Si un serveur là-bas écrit les adresses des clients dans des journaux, les vérifie contre une liste d’autorisation ou les remet à un autre système, traduire la source détruit son seul identifiant. Si le côté distant doit aussi appeler, la traduction est totalement exclue, car personne là-bas ne sait que l’alias existe. Ce n’est que lorsque le côté distant se contente de répondre aux requêtes que les options moins chères deviennent sûres.
Paires de préfixes, et pourquoi les tailles doivent correspondre
NETMAP est une cible de la table nat qui travaille sur une paire de préfixes de longueur identique. Il n’a pas de table par adresse à l’intérieur : il retire le préfixe, garde les bits d’hôte et les rattache au nouveau préfixe, ce qui explique qu’un /24 se mappe sur un /24 et jamais sur un /25. La position décide du sens : une correspondance de destination dans PREROUTING réécrit où va un paquet, et une correspondance de source dans POSTROUTING réécrit d’où il vient.
Un hôte à 192.168.2.17 apparaît à vos clients comme 10.50.1.17, et le dernier octet n’est pas décoratif — c’est le même nombre des deux côtés. Ajoutez demain un hôte à 192.168.2.40 et son alias sera 10.50.1.40, sans aucune règle à modifier.
Les clients ont toujours besoin d’une route pour la plage d’alias pointant vers votre machine, sauf si l’alias tombe dans un sous-réseau qu’ils atteignent déjà. La passerelle n’a pas besoin de route pour l’alias, car la traduction de destination s’exécute dans PREROUTING, avant la recherche de route. Le transfert doit aussi être actif, sinon le noyau jette le paquet après la réécriture. Les trois commandes ci-dessous sont toute la configuration sur une passerelle de style Debian avec les clients sur br0, l’alias sur 10.50.1.0/24 et le tunnel sur tun0.
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -i br0 -d 10.50.1.0/24 -j NETMAP --to 192.168.2.0/24
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADELa réponse doit trouver seule son chemin de retour
Réécrire la destination ne décide que de l’endroit où un paquet est livré. Le serveur du côté distant doit encore répondre à une adresse qu’il peut atteindre, et il y a deux façons de l’organiser. Traduisez la source pour que les réponses reviennent vers votre machine, ou laissez la source tranquille et donnez au côté distant une route pour la plage de clients.
Le masquage à la sortie est le chemin le plus court : une règle dans POSTROUTING et le côté distant voit l’adresse de votre tunnel, il n’a donc pas besoin de sa propre route. Le coût est que tous les utilisateurs se fondent en une seule adresse, et les journaux par utilisateur cessent de signifier quoi que ce soit. Laisser la source intacte conserve cette information, mais le site distant doit alors renvoyer les réponses de la plage de clients par le tunnel. Sur un OpenVPN serveur, c’est un push "route 10.50.9.0 255.255.255.0" poussé, plus une ligne route 192.168.2.0 255.255.255.0.
L’échec coûteux, c’est de faire la moitié de chaque. Si vous masquez une partie du trafic alors que le côté distant porte aussi une route de retour pour un autre trafic, les réponses arrivent sur une interface où l’entrée de suivi de connexion n’a jamais été vue. Le client signale un délai d’attente pour une requête que le serveur a journalisée comme servie. Les deux sens d’un flux doivent traverser la même instance netfilter : une passerelle qui traduit, pas deux pare-feu en série.
conntrack -L -d 10.50.1.17
iptables -t nat -L PREROUTING -v -nLisez l’entrée dans les deux sens : le tuple d’origine garde votre alias en destination, tandis que le tuple de réponse porte l’adresse réelle. Si le tuple de réponse manque, c’est le chemin de retour qui pose problème, pas la règle. Si les compteurs de PREROUTING n’ont jamais bougé, le paquet n’a jamais atteint ce hook.
Collisions et la recherche qui s’exécute en premier
Deux plages différentes peuvent entrer en collision, et les deux pannes ressemblent à un tunnel cassé plutôt qu’à une mauvaise règle. L’alias que vous inventez doit être inutilisé sur tout le chemin, et la plage réelle du côté distant ne doit pas déjà exister sur votre réseau. Un doublon produit un trafic intermittent vers le mauvais hôte, ce qui est plus difficile à diagnostiquer qu’une connexion refusée. Interrogez la table de routage avant d’ajouter une règle.
Sur la passerelle, ip route get 192.168.2.17 devrait nommer le périphérique du tunnel ; un pont local signifie que la plage distante est masquée et aucune règle nat ne la réparera. Si votre propre réseau utilise déjà 192.168.2.0/24, renumérotez le site distant au lieu d’empiler un mappage sur la collision.
Le tester depuis un vrai client, puis le conserver
Testez depuis une machine qui utilisera réellement l’alias, pas depuis la passerelle, car le trafic généré localement ne traverse jamais PREROUTING de la même manière. Ouvrez une connexion vers un hôte aliasé et regardez les compteurs et l’entrée conntrack apparaître ensemble, puis fermez-la et confirmez que l’entrée disparaît. Une entrée périmée indique une connexion à moitié ouverte, ce qui signifie généralement que la réponse n’est jamais revenue.
curl -sv http://10.50.1.17/ -o /dev/null
ss -tn dst 10.50.1.17
conntrack -L -d 10.50.1.17Deux ou trois connexions réussies prouvent l’arithmétique, mais elles ne disent rien de la persistance ni du prochain ingénieur. Enregistrez les règles là où le processus d’amorçage les lit, ce qui sous Debian et Ubuntu signifie iptables-save > /etc/iptables/rules.v4 avec netfilter-persistent activé. Un mappage qui disparaît au redémarrage est pire qu’aucun, car la panne arrive sans changement récent à blâmer.
Laissez une note à côté des règles : la plage d’alias, la plage réelle, la raison de la paire et quel côté peut initier. Cette note sépare une conception d’un tas de règles que personne n’ose supprimer. Elle règle aussi la question ultérieure, quand le site distant ajoute un hôte et qu’une adresse que personne n’a configurée répond déjà. Si la note dit que le côté distant a besoin d’une route de retour, la personne suivante sait que retirer la règle de masquage casse la connectivité. La documentation est bon marché ici ; redécouvrir une dépendance NAT à trois heures du matin ne l’est pas.