La réponse sort par le LAN, pas par le tunnel : pourquoi et comment
Une requête qui arrive par le tunnel ne signifie pas que la réponse repartira par le même chemin. Linux cherche la destination, et le sous-réseau local l'emporte le plus souvent.
Un service publié via une passerelle fonctionne depuis la majeure partie d'Internet et échoue depuis un bureau. Quelqu'un vérifie le tunnel, voit la requête arriver et conclut que la réponse doit reprendre le même chemin. Linux ne fonctionne pas ainsi, et aucune inspection du tunnel n'y changera rien. La réponse est routée selon la destination, et cet unique appelant en échec se trouve sur un sous-réseau que l'hôte atteint déjà directement.
Ce qui décide réellement d'un paquet sortant
Le noyau cherche une route pour la destination du paquet, consulte les règles de politique par ordre de priorité, puis la table que sélectionne une règle correspondante. L'interface par laquelle un paquet est arrivé ne joue aucun rôle, sauf si une règle ou une marque a été écrite pour la rendre pertinente. C'est un fait de routage de cet hôte, pas un défaut du tunnel.
Une requête reçue par le tunnel peut donc produire une réponse qui sort par l'interface physique, et le flux devient unidirectionnel sans qu'aucun appareil ne signale d'erreur. Vérifiez les deux directions avant de conclure quoi que ce soit sur le tunnel. Une réponse qui part du mauvais côté disparaît des compteurs du tunnel, ce qui explique que les deux extrémités ne soient pas d'accord sur l'envoi de quoi que ce soit. Repérez quel compteur a bougé avant de toucher à une règle.
Pourquoi le sous-réseau local l'emporte
Un hôte possédant une adresse sur un réseau local détient une route connectée pour ce préfixe dans la table principale, et une route connectée est une correspondance directe. Quand l'appelant vient de ce même sous-réseau, la recherche trouve le lien local avant même que le tunnel soit envisagé.
C'est l'asymétrie qui rend le diagnostic déroutant. Les appelants venus de l'Internet plus large fonctionnent parce qu'ils ne correspondent à aucune route locale, tandis que l'unique appelant qui partage le préfixe du bureau échoue, et c'est précisément celui avec lequel quelqu'un teste.
La couverture des pairs n'est pas la même chose que les routes installées
Côté tunnel, les plages autorisées d'un pair décrivent ce qui peut être envoyé dans le tunnel et quelles sources en sont acceptées. Elles ne disent rien de l'endroit où la table de routage locale enverra un paquet.
Si l'outil de tunnel installe une route par défaut sur l'hôte, il peut entraîner du trafic sans rapport dans le tunnel comme dommage collatéral. Là où une règle de politique devrait au contraire prendre la décision, l'option d'installation de routes de l'outil existe justement pour l'en empêcher, et les adresses, les clés et les réglages du point de terminaison restent exactement tels qu'ils étaient. Une route par défaut ajoutée pour plus de commodité est une façon courante pour un hôte de perdre son propre réseau local.
Choisissez la table d'après l'adresse source
Une règle fondée sur la source envoie les réponses de l'adresse du service dans une table privée dont la valeur par défaut est le tunnel, tandis que tout le reste continue d'utiliser la table principale. Choisissez des numéros de table et de priorité inutilisés localement, et lisez les règles existantes avant d'insérer quoi que ce soit. Lisez les règles actives plutôt qu'un fichier enregistré, car les deux peuvent différer après un redémarrage.
ip -6 route add default dev wg0 table 200
ip -6 rule add priority 32000 from 2001:db8:aa::20/128 lookup 200
ip -6 rule add priority 32001 from 2001:db8:aa::20/128 unreachableLa dernière ligne fait échouer visiblement une route absente plutôt que de retomber sur le lien local. La source doit réellement être attribuée à l'hôte, et les recherches locales et principales ordinaires doivent rester à leurs positions antérieures. La règle choisit une table selon la source ; elle ne compare pas les longueurs de préfixe entre tables.
Confirmez le chemin, puis le service
Demandez au noyau ce qu'il ferait au lieu de déduire d'une capture, en utilisant l'adresse du service comme sélecteur de source. Une mauvaise réponse ici fait économiser toute une trace de paquets.
ip -6 route get 2001:db8:bb::30 from 2001:db8:aa::20La sortie devrait nommer le tunnel. Testez ensuite une source que vous n'avez pas touchée et confirmez qu'elle emprunte toujours le lien local, afin que le changement reste limité à une adresse. Un sélecteur plus large ne prouverait rien sur la plainte d'origine.
Ce que cela ne corrige pas
Laissez le transfert, les règles de pare-feu et le comportement ICMPv6 sur la passerelle tels qu'ils étaient, car une route de source ne remplace rien de tout cela. Un message Packet Too Big manquant casse encore les grandes réponses, quelle que soit la table qui a gagné la recherche. Corrigez cela avant d'ajouter des règles de routage, sinon le symptôme survivra au changement.
Confirmez le modèle de publication avant d'appliquer quoi que ce soit de tout cela. Un proxy inverse qui ouvre sa propre connexion backend présente sa propre source et ne conserve pas l'appelant, donc ce défaut ne peut pas se produire dans ce modèle. Y appliquer la règle ajouterait une exception de routage qui ne résout rien et masque la cause réelle.
Enfin, inscrivez les numéros de règle et la table dans la gestion de configuration de l'hôte. Une règle de politique ajoutée à la main disparaît à la prochaine reconstruction, et l'appelant du bureau revient avec la même plainte.