Pourquoi votre LAN n’atteint pas un service sur un client VPN
Un client VPN peut héberger un service que le LAN ne peut pas ouvrir. Ce qui manque, c’est généralement le chemin de retour : une route, une paire DNAT ou la ligne SNAT que personne n’ajoute.
Votre tunnel est monté, le service écoute, et le LAN du bureau ne reçoit toujours rien en retour. Personne n’a cassé le VPN. Du côté du LAN, l’adresse de tunnel du portable n’existe pas tant que quelque chose n’indique pas au LAN comment l’atteindre, et la réponse doit revenir par le même chemin que la requête. J’ai vu des gens reconstruire trois fois un tunnel parfaitement sain avant que quelqu’un ne regarde le chemin de retour.
Ce n’est pas le tunnel qui a cassé
Les deux extrémités sont sur des plages privées, ce qui est le cas normal et non une mauvaise configuration. Une adresse comme 10.8.0.6 est réelle à l’intérieur du tunnel et inexistante partout ailleurs, donc le LAN n’a aucune raison de lui envoyer quoi que ce soit. Avant de toucher au routage, confirmez que le service est accessible à l’intérieur du tunnel : sur le client, ss -ltn montre si l’écouteur se lie à 127.0.0.1, à l’interface du LAN ou à l’adresse du tunnel. Un démon lié uniquement à loopback ne répond à personne d’autre qu’à lui-même, et aucune route, aucun DNAT ni aucune redirection de port n’y change quoi que ce soit.
Un proxy sur le port 80 ou 443 est un autre outil avec une autre visibilité. Il déplace des requêtes, pas des paquets, c’est donc la mauvaise couche pour une connexion brute à une base de données, et s’y raccrocher est précisément la façon dont ce problème finit trois outils plus loin avant que quiconque mesure quoi que ce soit.
Forme de route : dites au LAN où se trouve le pool
Une route statique sur la passerelle du LAN est la réponse la plus propre quand le LAN et le pool du tunnel ne se recouvrent pas. Pointez le pool vers la machine qui termine le tunnel :
ip route add 10.8.0.0/24 via 192.168.1.12
route add -p 10.8.0.0 mask 255.255.255.0 192.168.1.12 # Windows, persistent
Cela ne corrige qu’un sens, et c’est pourquoi les versions à moitié faites de ce changement ressemblent à un progrès. Le côté tunnel a besoin de la moitié correspondante, sinon la réponse quitte le client par sa propre route par défaut et meurt en chemin :
push "route 192.168.1.0 255.255.255.0"
Pour un sous-réseau qui se trouve derrière un client plutôt que derrière le serveur, le serveur a besoin à la fois d’une route système et d’une entrée iroute dans le fichier de ce client sous client-config-dir. Sans iroute, OpenVPN sait que le préfixe existe et n’a aucune idée du client qui le possède : les paquets arrivent et le démon n’a rien à leur associer.
Voici le mythe qui mérite d’être nommé. Une route rend une adresse joignable ; elle ne rend pas l’autre côté disposé à répondre. Les pairs site à site ajoutent une couche de plus, car la passerelle distante n’accepte que les sources situées dans les préfixes de sa politique, et un portable qui arrive d’un pool domestique n’en fait pas partie.
Forme NAT : DNAT vers l’intérieur et la ligne SNAT que tout le monde omet
Quand vous ne pouvez pas toucher à la passerelle du LAN, ou que vous voulez publier exactement un port, la traduction sur l’hôte VPN fonctionne sans aucune route sur le LAN. Publiez le port, redirigez-le et traduisez la source en chemin vers le tunnel :
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 10.8.0.6:3000
iptables -A FORWARD -i eth0 -o tun0 -p tcp -d 10.8.0.6 --dport 3000 -j ACCEPT
iptables -t nat -A POSTROUTING -o tun0 -d 10.8.0.6 -p tcp --dport 3000 -j SNAT --to-source 10.8.0.1
La troisième ligne est celle qui disparaît. Omettez-la et le client voit l’adresse d’origine du LAN comme source, répond par sa propre route par défaut, et cette réponse part dans le tunnel au lieu de revenir vers le LAN. Que la connexion survive dépend alors d’un routage que vous n’avez jamais planifié. Avec SNAT, le client voit l’adresse de tunnel du serveur, donc la réponse suit le tunnel jusqu’au seul hôte capable d’annuler la traduction.
Le micrologiciel grand public utilise ses propres noms de chaînes et ne génère pas cette traduction pour vous. Sur Tomato, une règle entrante atterrit dans WANPREROUTING puis dans une chaîne de filtrage comme wanin, et un jeu de règles qui semble complet a encore besoin d’une ligne POSTROUTING manuelle. Ce n’est pas un bug du micrologiciel ; c’est un jeu de règles écrit uniquement pour le trafic entrant.
Pourquoi une règle qui semble correcte jette quand même le paquet
La plupart de ces échecs ne sont pas dans la règle que vous fixez. Vérifiez quatre choses dans cet ordre et arrêtez-vous à la première qui ne tient pas :
- Ordre des chaînes.
iptables -Iinsère en haut et-Aajoute en bas, donc une règle permissive ou bloquante antérieure décide d’abord. - Mauvaise chaîne. Le trafic adressé au routeur lui-même traverse INPUT, et le trafic transféré ne la touche jamais. Publier un seul service peut nécessiter des règles dans les deux.
- Drapeaux de direction.
-i tun0correspond au trafic venant des clients et-o tun0au trafic partant vers eux. Un REJECT avec le mauvais drapeau bloque quelque chose que vous ne vouliez pas. - Restriction de source. Une redirection qui accepte une adresse de client fonctionne depuis ce client et rejette toute autre source sans un mot.
Une règle dont le compteur de paquets est à zéro n’est pas du tout sur le chemin, et lire les compteurs est le moyen le plus rapide de distinguer un problème de mauvaise chaîne d’un problème de mauvaise règle.
La redirection locale, quand rien sur le LAN ne peut changer
Une redirection SSH locale contourne toute la question. Elle n’a besoin d’aucune route sur le LAN, d’aucune coopération du pare-feu du client et d’aucun port publié nulle part :
ssh -N -f -L 3000:10.8.0.6:3000 user@vpn-host
Le service apparaît alors sur localhost:3000 de la machine qui porte le tunnel, et nulle part ailleurs. C’est la limite : un poste de travail, un port, et la redirection meurt avec la session sauf si quelque chose la redémarre. Pour un administrateur qui vérifie une base de données de préproduction, c’est le bon outil. Pour une caméra ou un scanner que d’autres personnes doivent atteindre, non, car chaque utilisateur aurait besoin de sa propre redirection.
Vérifiez les deux sens avant d’ajouter une autre règle
La traduction laisse des traces, et les lire vaut mieux que deviner. Sur l’hôte VPN, conntrack -L montre si la traduction a eu lieu, iptables -t nat -L -n -v montre si les compteurs ont bougé et tcpdump -ni any port 3000 montre quelle adresse source est réellement arrivée. Sur le client, ss -ltn confirme que l’écouteur est sur une adresse que le tunnel peut atteindre.
Choisissez ensuite la forme que vous gardez. Un port publié, une route pour tout le pool et une redirection pour un seul administrateur sont trois engagements différents, et les mélanger est la façon dont une installation qui marche devient une installation que personne ne saura expliquer six mois plus tard. Écrivez quelle adresse est joignable d’où, et la prochaine personne qui débogue cela part de la réponse plutôt que du tunnel.