Un profil vpnc se reconnecte proprement après une itinérance ; trois d’entre eux finissent tour à tour par casser les sockets, les routes et l’état du résolveur des autres. Le script de reconnexion fourni est écrit pour un seul tunnel, il redémarre donc chaque profil dès que l’un d’eux est tombé. Corriger cela demande trois choses : des ports locaux séparés, une sonde qui teste un vrai service par profil et une chaîne ordonnée qui ne lance jamais deux connexions en même temps.

Donnez à chaque profil son propre port local

Un profil vpnc laissé sur le port local par défaut entre en concurrence avec le profil déjà lancé. La seconde connexion échoue pendant que la première tient le port, et la ligne de journal ressemble à un problème de passerelle plutôt qu’à un conflit local. Mettez plutôt une ligne par fichier de profil :

Local Port 0

Zéro laisse le noyau choisir un port éphémère, deux profils peuvent donc être établis en même temps. Nommez chaque fichier d’après la passerelle et le groupe qu’il sert, gardez-le lisible par root uniquement, et connectez-vous toujours avec le profil correspondant plutôt qu’avec un défaut partagé. Un fichier par défaut partagé est la façon dont un script reconnecte le mauvais tunnel après que quelqu’un a renommé un profil.

Les fichiers de profil portent des identifiants, les permissions font donc partie de la conception et non du rangement. Un fichier lisible par tous sous /etc/vpnc livre le secret de groupe à chaque utilisateur local. Gardez le mode à 0600 avec root comme propriétaire, et laissez les scripts lire le fichier en root au lieu de copier des secrets dans des arguments. C’est aussi pourquoi un script de sonde ne devrait jamais recopier le contenu du fichier dans un journal.

Sondez un service par profil, pas l’adresse du tunnel

Une requête d’écho vers l’adresse du tunnel lui-même prouve surtout que l’interface existe. Elle ne dit rien de la capacité de l’hôte derrière elle à joindre encore l’application qui justifie le tunnel. L’interface peut être active alors que la route au-delà a déjà disparu.

Sondez un service par profil avec un court délai TCP et ne reconnectez que le profil dont la sonde a échoué. Deux secondes séparent un chemin mort d’un chemin lent, et une sonde TCP ne dépend pas de l’autorisation d’ICMP quelque part sur le trajet. Ne changez que la cible et le nom de configuration entre les profils :

#!/bin/bash
set -eu
if ! nc -z -w 2 10.63.7.20 8443; then
  /usr/sbin/vpnc-connect ops.conf
fi

Enregistrez cela sous /usr/local/bin/ensure-vpn-ops.sh, rendez-le exécutable et répétez pour chaque profil en ne changeant que la cible de la sonde et le nom de configuration. Une sonde qui répond à une question de protocole survit aux passerelles qui jettent l’écho tout en continuant à transmettre les services qui importent aux utilisateurs.

Enchaînez les sondes pour qu’elles ne se disputent jamais

Le script de reconnexion fourni peut appeler vos sondes en séquence, et la séquence est tout l’enjeu. Deux appels à vpnc-connect lancés ensemble réécrivent la table de routage dans un ordre que personne ne contrôle, et c’est ainsi qu’un profil sain perd sa route.

Gardez les appels au premier plan, ajoutez un court délai de stabilisation pour l’interface sous-jacente et planifiez la chaîne depuis la table cron de root, car seul root peut réécrire les routes du tunnel :

#!/bin/bash
sleep 20
/usr/local/bin/ensure-vpn-ops.sh
/usr/local/bin/ensure-vpn-lab.sh

Gardez l’ordre identique entre le script de démarrage et l’entrée cron, car une chaîne qui s’exécute dans un autre ordre au démarrage est en pratique un autre programme. Quand un profil dépend des routes d’un autre, placez la dépendance en premier et laissez la sonde suivante échouer sans dommage pendant que le tunnel précédent monte encore.

Surveillez le journal, puis cassez-en un exprès

Journalisez une ligne par exécution avec le profil, la cible de la sonde, le résultat et l’action menée. Sans cela, un tunnel qui oscille chaque minute ressemble exactement à un tunnel qui n’est jamais tombé, et un bug de sonde est indissociable d’une panne de passerelle. Le journal prouve aussi que la chaîne n’a touché que le profil en échec. Écrivez-le quelque part qui survit à un redémarrage, sinon les preuves partent avec le processus.

Cassez ensuite un tunnel délibérément et regardez ce qui se passe. Arrêtez un seul profil et vérifiez quels processus et quelles routes sont encore présents :

pgrep -a vpnc
ip -4 route show | grep -E '10[.]63|10[.]90'
tail -n 5 /var/log/ensure-vpn.log

Seul le profil arrêté devrait être reconnecté, et les autres sessions devraient conserver à la fois leurs processus et leurs routes. Si deux profils redémarrent, votre chaîne s’exécute en parallèle quelque part que vous n’attendiez pas.

Ce que le chien de garde ne doit pas faire

Un chien de garde qui redémarre tout dès que quelque chose échoue paraît sain en test et provoque une panne lors d’une fenêtre de maintenance. Redémarrez par profil, jamais globalement.

Préférez un client maintenu quand la passerelle en propose un pour le même protocole, et ne codez jamais un mot de passe en dur dans le script ni ne le passez sur une ligne de commande, car le fichier de profil détient déjà le secret. Si une tâche doit tourner en utilisateur ordinaire une fois le tunnel monté, réduisez les privilèges depuis l’intérieur du script au lieu de faire tourner toute la chaîne sous ce compte. Enfin, relisez les routes après une reconnexion, car un profil peut revenir avec une adresse attribuée différente et laisser une route obsolète qu’aucune sonde visant l’adresse du tunnel ne remarquera jamais.

Articles similaires