Les symptômes suivent une même forme : un hôte fonctionne, puis il se connecte à une VPN comme client, et désormais les clients LAN l’atteignent tandis que ses réponses disparaissent. Une capture sur l’hôte montre que les réponses sortent par le périphérique du tunnel au lieu de l’interface LAN. Rien n’est cassé dans le tunnel, et le correctif est une route, pas une reconnexion. Faites les quatre vérifications ci-dessous dans l’ordre et arrêtez-vous à la première qui échoue.

Une réponse est un nouveau paquet, pas un retour en arrière

Il aide de renoncer à l’idée qu’une réponse revient par le chemin qu’a pris une requête. Le routage se décide paquet par paquet, sens par sens, sur l’hôte émetteur. Une requête arrivée de 10.64.0.23 dans le tunnel ne crée aucun chemin de retour ; quand l’hôte répond, cette réponse est comparée à la table comme un paquet neuf et sort par la route qui gagne.

C’est pourquoi un client en tunnel complet sur une machine qui sert aussi un LAN produit une panne aussi déroutante. Le client installe une route par défaut, ou les deux demi-routes par défaut que certains clients préfèrent, et la réponse à un client LAN correspond désormais au tunnel. Elle part vers le fournisseur, qui n’a aucune raison de la transmettre, et le client LAN voit un délai d’attente alors que l’hôte est actif et répond localement. La capture le rend évident, et la table de routage l’explique.

Gardez deux sous-réseaux en tête pendant la lecture de la suite. L’un est le pool d’adresses VPN d’où viennent les clients distants, dans cet exemple 10.64.0.0/24. L’autre est le LAN qui doit continuer à fonctionner, 172.16.24.0/24 avec son routeur à 172.16.24.1. Le bug est que le trafic entre eux est décidé par la route par défaut.

Prouvez-le par la capture et la consultation

Avant de changer quoi que ce soit, confirmez quel périphérique la réponse utilisera. Une consultation est plus rapide qu’une capture et répond exactement à la question à laquelle le noyau répondra quand le paquet sera construit.

ip route get 10.64.0.23 from 172.16.24.10
tcpdump -ni any -c 6 icmp

Lisez la réponse en deux parties. Si elle nomme dev tun0, l’hôte encapsulera la réponse et la remettra au fournisseur, et le client LAN ne la verra jamais. Si elle nomme dev eth0 mais que le client expire encore, la route est déjà correcte et le paquet est abandonné plus tard, ce qui est un autre problème avec un autre correctif.

La capture à la même étape tranche le doute qu’un ping ne peut pas. Un écho de réponse qui atteint le client LAN prouve qu’un chemin fonctionne, pas quelle interface l’a porté, donc lancez la capture sur l’hôte lui-même et regardez par où les trames sortent. Une imprimante sur le même sous-réseau continue de répondre, car sa route directe est plus spécifique que la route par défaut du tunnel. Un port redirigé échoue exactement comme n’importe quel flux, car la table choisit l’interface et la connexion non.

Installez la route la plus spécifique qui surclasse le tunnel

C’est la longueur du préfixe qui décide, pas la métrique, donc une route pour le pool de clients via le routeur LAN l’emporte sur toute route par défaut que le client VPN installe. Aucune chirurgie de métrique n’est nécessaire, et la route par défaut peut rester exactement là où le client l’a mise.

ip route replace 10.64.0.0/24 via 172.16.24.1 dev eth0
ip route get 10.64.0.23 from 172.16.24.10

Utilisez replace plutôt que add, car un client qui se reconnecte aura installé sa propre entrée et un second add échoue avec une erreur de route existante qui se lit comme un problème de permissions. Sur un hôte Windows l’équivalent est route add 10.64.0.0 mask 255.255.255.0 172.16.24.1 -p, où -p conserve l’entrée après les redémarrages, puisque le client peut reconstruire la table quand le tunnel remonte. Sur un hôte Windows actuel l’équivalent pris en charge est New-NetRoute -DestinationPrefix 10.64.0.0/24 -NextHop 172.16.24.1 -InterfaceAlias Ethernet -PolicyStore PersistentStore, l’ancienne commande route étant conservée comme forme héritée.

Un détail décide si c’est correct ou seulement plausible : le prochain saut doit être le routeur qui possède réellement le chemin du retour vers les clients. Pointer la route vers une adresse elle-même atteinte par le tunnel crée une boucle qui se manifeste par des pertes intermittentes plutôt que par une panne nette. Confirmez que le prochain saut est sur le sous-réseau LAN avant de valider la ligne.

Conservez la réponse après une reconnexion

Une route ajoutée à la main survit au mieux jusqu’à la reconnexion suivante. Si le pool de clients est dynamique, épinglez-le dans la configuration du serveur pour que le préfixe que vous avez routé reste le préfixe que les clients reçoivent ; sinon l’entrée pointe vers une plage vide et le symptôme revient des semaines plus tard sans cause évidente. Écrire la route dans le script up du client lui-même est l’autre option fiable, car il s’exécute après que le client a réécrit la table.

Un pare-feu à états peut encore défaire une route correcte. Si la capture montre maintenant que la réponse sort par eth0 et que le client expire encore, vérifiez si l’hôte abandonne le paquet avant de l’envoyer. Le filtrage strict du chemin inverse et net.ipv4.conf.all.rp_filter réglé à 1 écartent les paquets dont la source ne serait pas routée en retour par l’interface par laquelle ils sont arrivés, ce qui est exactement le cas asymétrique que vous venez de créer puis de corriger, et l’état conntrack raconte la même histoire pour les ports redirigés.

La dernière vérification est celle que les gens sautent : répétez la consultation après que le tunnel est tombé puis remonté. Quatre valeurs doivent correspondre à ce que vous avez noté : la destination, le prochain saut, le périphérique et la source choisie. Si l’une d’elles a bougé, le client a réécrit la table et le correctif appartient à ses hooks et non à un historique de shell.

Articles similaires