J’avais une machine de laboratoire qui acceptait un tunnel depuis un site distant et composait aussi vers un réseau fournisseur. Le profil sortant fonctionnait depuis des semaines. Après l’ajout du serveur entrant, celui sortant s’est connecté puis a cessé de transmettre du trafic en quelques secondes, ou a refusé de démarrer avec une erreur d’adresse déjà utilisée. Les fichiers de configuration n’avaient pas changé ; l’hôte avait simplement acquis un second processus OpenVPN avec son propre avis sur les ports et les routes.

La panne n’est pas aléatoire, et ce n’est pas un problème d’authentification. Deux démons sur une même machine se disputent le même socket local et la même table de routage, et celui qui démarre ou se reconnecte en dernier gagne généralement. Savoir laquelle de ces deux collisions vous avez décide où regarder d’abord.

Lisez le symptôme à l’envers

Commencez par le moment où le tunnel meurt. Une erreur de bind au démarrage pointe vers le côté qui écoute : quelque chose possède déjà ce port, et OpenVPN refuse de démarrer plutôt que de le partager. Un tunnel qui monte puis se tait pointe vers le routage, car une route installée par l’autre instance peut sortir les paquets de la connexion extérieure de leur chemin.

Les deux cas produisent la même plainte de l’utilisateur, c’est pourquoi les boucles de réessai et les scripts de surveillance ne réparent rien. Ils reconnectent le client dans le même conflit. La première question utile est de savoir si le processus tourne encore lorsque le trafic s’arrête.

Un socket et un appareil par instance

Un serveur qui écoute lie son port ; un client sortant a aussi besoin d’un port local pour son trafic encapsulé. Lorsque les deux vivent sur le même hôte, le comportement par défaut du client peut entrer en collision avec le port du serveur. Le port local du client peut être fixé, et la liaison peut être ignorée là où le pair n’a pas besoin d’un port source fixe :

lport 1195
nobind
dev tun1

Ces nombres sont des exemples, pas une exigence. L’important est que le client cesse de se disputer le port du serveur et que chaque instance obtienne un appareil tunnel distinct. Deux démons qui partagent tun0 écrasent l’état d’appareil l’un de l’autre même lorsque leurs ports diffèrent, donc un appareil par tunnel n’est pas facultatif.

nobind appartient au côté client. Un serveur doit toujours se lier et écouter, alors ne copiez pas la ligne dans la configuration du serveur, et ne désactivez pas la liaison sur un client dont le pair filtre sur un port source fixe.

Choisissez un seul propriétaire pour la route par défaut

Une seule connexion peut installer une route par défaut. Si les deux profils redirigent tout le trafic, la seconde connexion remplace silencieusement la première, et la première semble se casser. Soit vous gardez le tunnel sortant scindé et ne poussez que les préfixes du fournisseur, soit vous lui donnez une table de routage distincte.

ip rule add from 10.9.0.2 table 120
ip route add default dev tun1 table 120
ip route get 10.9.0.2

Les adresses et le numéro de table ci-dessus sont des espaces réservés. Immédiatement après avoir ajouté la règle, confirmez que l’adresse du serveur VPN lui-même se résout toujours via la table normale ; une table qui capture le transport extérieur casse le tunnel qu’elle était censée protéger, et la boucle de reconnexion qui suit ressemble à un fournisseur peu fiable.

Pour une configuration qui doit survivre aux reconnexions et aux redémarrages, un espace de noms réseau est la frontière la plus solide. Le second client s’exécute dans son propre espace de noms avec ses propres interfaces et routes, et seuls les services qui doivent traverser sont exposés. L’hôte conserve une route par défaut, et une reconnexion de l’espace de noms ne peut pas la réécrire.

Vérifiez avec la table, pas avec la ligne d’état

Un client qui signale être connecté ne prouve que son canal de contrôle. Capturez l’état de routage avant et après chaque connexion, puis demandez au noyau quel appareil une destination réelle utiliserait :

ip route show
ip route get 10.40.0.20
ss -lunp | grep 1194

Si l’appareil choisi pour l’adresse du fournisseur change lorsque le second tunnel démarre, vous avez la collision de routes. Si les deux processus apparaissent sur le même port local, vous avez la collision de sockets. Corriger la première sans la seconde ne fait que déplacer la panne vers la reconnexion suivante.

Écrivez les ports, appareils, tables et propriétaire de route dans le runbook de l’hôte. Sinon, la prochaine personne qui ajoutera un troisième tunnel redécouvrira la même collision, et la seule preuve visible sera une connexion qui fonctionne jusqu’à ce que le démon de quelqu’un d’autre redémarre.

Articles similaires