Scripts de client VPN : choisissez la couche avant le mot de passe
La CLI du fournisseur, rasdial, une intention d’application ou l’automatisation d’interface échouent chacun différemment. Choisissez la couche, gardez le secret hors d’argv et attendez l’état, pas les codes de sortie.
Les scripts démarrent des clients VPN à la couche que l’auteur a choisie, et cette couche est rarement celle dont la tâche avait besoin. La ligne de commande du fournisseur, le composeur du système d’exploitation et une intention d’application mobile reviennent tous à des moments différents de la vie de la connexion. Ils traitent aussi le secret différemment, et cette différence décide si le mot de passe est visible par chaque utilisateur de la machine. Choisissez la couche avant d’écrire la première ligne du script.
Couche 1 : la ligne de commande du fournisseur
La plupart des clients de bureau livrent une ligne de commande qui prend un nom de profil et, trop souvent, un mot de passe. L’ancien client de Cisco acceptait un verbe connect avec des arguments d’utilisateur et de mot de passe ; macOS expose le service intégré via networksetup ; NetworkManager répond à nmcli. Ces appels reviennent quand la commande est terminée, ce qui n’est pas le même moment que celui où le tunnel devient utilisable. Lisez la documentation du fournisseur pour la version que vous déployez, car ces interfaces changent et certaines sont entièrement supprimées.
nmcli connection up "Work VPN"
networksetup -connectpppoeservice "Work VPN"
L’avantage est que le fournisseur connaît son propre magasin de profils, donc l’appel utilise la même configuration que l’interface graphique. L’inconvénient est que chaque fournisseur invente ses propres verbes, et un script écrit pour un client ne se transpose pas à un autre. Considérez cette couche comme le chemin le plus court quand le client est fixé et la version épinglée.
Couche 2 : le service propre au système d’exploitation
Sous Windows, le composeur fait partie du système d’exploitation et il travaille sur une entrée de carnet de téléphone plutôt que sur le magasin de profils du fournisseur. Cela le rend plus portable d’un client à l’autre et plus facile à scripter depuis un compte de service. Cela signifie aussi que la connexion peut exister à un endroit et pas à l’autre, ce qui perturbe les personnes qui regardent la mauvaise liste.
rasdial "Work VPN" user pass
Get-VpnConnection -Name "Work VPN" | Select-Object ConnectionStatus
Utilisez la surface PowerShell quand vous devez créer ou supprimer l’entrée plutôt que la composer. Les couches WMI et cmdlet exposent les mêmes objets sous des noms différents, et la suppression est une opération distincte de la déconnexion. Un script qui se contente de composer laissera des entrées obsolètes après une migration. Vérifiez vers quel magasin votre automatisation écrit avant de promettre que le nettoyage aura lieu.
Remove-VpnConnection -Name "Old VPN" -Force
Get-VpnConnection
Sous macOS, l’équivalent est la liste des services réseau, où un service existant est connecté par son nom plutôt que créé à la volée.
Les identifiants fuient à chaque couche, alors choisissez le canal
Tout ce que vous passez sur la ligne de commande apparaît dans la table des processus pour chaque utilisateur local, et cela survit généralement aussi dans l’historique du shell. L’alternative prise en charge d’OpenVPN consiste à lire le secret depuis un fichier avec --askpass, et le fichier lui-même a besoin de permissions qui correspondent à la confiance que vous lui accordez. Un tube nommé évite d’écrire le secret sur le disque mais laisse tout processus capable de l’ouvrir y écrire. Sous Windows, stockez le secret dans le gestionnaire d’identifiants, ou dans un fichier que seul le compte de service peut lire, et jamais comme littéral dans un fichier batch.
openvpn --config /etc/openvpn/work.conf --askpass /etc/openvpn/work.secret --auth-nocache --daemon
ls -l /etc/openvpn/work.secret
La même règle s’applique aux jetons et aux codes à usage unique : si l’automatisation en a besoin, l’automatisation a besoin d’un canal qui n’est pas un argument de ligne de commande. Faites tourner le secret quand vous changez le mécanisme, car l’ancienne valeur a séjourné dans un journal quelque part. Un script qui fonctionne et qui fuit n’est pas un script qui marche.
Attendez l’état, puis supervisez un seul propriétaire
Chacun de ces appels revient avant que le tunnel soit prêt, alors interrogez l’état que le client expose ou testez une destination à l’intérieur avec un délai. Copier des fichiers ou ouvrir une connexion de base de données immédiatement après l’appel de connexion est une course, et cela échoue par intermittence d’une manière qui ressemble à une panne réseau.
ip link show tun0
nmcli -t -f GENERAL.STATE connection show "Work VPN"
curl -sS --max-time 5 https://app.internal.example/health -o /dev/null
La déconnexion a le même problème à l’envers : le processus peut se terminer avant que les routes aient disparu. Utilisez les hooks du client là où ils existent, comme les scripts up et down fournis par OpenVPN ou l’ExecStartPost d’une unité systemd, car ils s’exécutent au moment qui vous intéresse réellement. Les hooks s’exécutent avec les privilèges de ce qui les a invoqués, donc un hook qui redémarre le réseau a besoin d’une règle explicite plutôt que d’une supposition. Gardez exactement un propriétaire pendant la durée de vie de la connexion.
Quand deux superviseurs démarrent et arrêtent ce profil, le résultat est une boucle de reconnexion qui se lit comme une panne du fournisseur. Le runbook se termine quand la couche est documentée, que le secret dispose d’un canal qui n’est pas argv, que la condition d’attente est une vérification d’état avec délai, et qu’un seul processus possède le cycle de vie.