On croit qu’un here-document de quatre lignes est une connexion non interactive complète, et cette croyance tient jusqu’au moment où la passerelle propose deux groupes, imprime une bannière ou demande un jeton après le mot de passe. Alors le même script tape le mot de passe dans un menu qui attendait un nombre. Le client en ligne de commande sous Linux est scriptable, mais seulement si vous lui fournissez ce qu’il attend réellement, et non ce que le tutoriel supposait.

Le here-document figé est un mythe

Le client Linux de Cisco installe un petit programme dans /opt/cisco/anyconnect/bin/vpn, et Secure Client 5 le fournit toujours. Avec le service vpnagentd en cours d’exécution, l’option -s lit les réponses sur l’entrée standard dans l’ordre où le client les demande. Cet ordre n’est pas fixe d’un serveur à l’autre.

Un menu de groupes ajoute une ligne. Une bannière de connexion en ajoute une autre. Une demande de jeton après le mot de passe casse net un script de quatre lignes, car la cinquième ligne n’était pas censée être le jeton. L’échec est silencieux : le client reçoit la mauvaise chaîne, la tentative de connexion se termine et le script ne signale rien d’utile.

Lancez le client à la main une fois contre la même passerelle et la même version, et notez les invites dans l’ordre où elles apparaissent. Cette transcription est la spécification que votre script doit satisfaire.

Ce que le client attend

Dans le cas courant à groupe unique, la séquence est nom d’utilisateur, mot de passe et parfois une confirmation de bannière. La première ligne d’un here-document ne devient un index de menu que lorsque le serveur présente réellement un menu, et c’est pourquoi le même script fonctionne sur un site et échoue sur le suivant.

/opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net <<EOF
0
alice
$VPN_PASSWORD
y
EOF

Lisez cela comme quatre réponses à quatre questions possibles, non comme un protocole figé. Le zéro est une sélection de menu, pas un mot de passe, et le y final accepte une bannière que beaucoup de passerelles n’envoient jamais.

Utilisez expect lorsque l’ordre n’est pas prévisible

Quand l’ordre des invites varie, cessez de compter les lignes et attendez l’invite. Un script expect lance la commande connect, attend l’invite du nom d’utilisateur, envoie, attend l’invite du mot de passe, envoie, puis attend l’état connecté. Chaque attente a son propre délai.

Traitez un dépassement de délai comme un échec et quittez. Un script qui continue d’envoyer des entrées après une invite inattendue tapera volontiers le mot de passe dans un shell, un menu ou tout autre programme en train de lire. C’est ainsi qu’un script de connexion devient un incident.

expect vous donne aussi une transcription que vous pouvez journaliser sans le secret, et elle vaut plus que le code de sortie lorsqu’une passerelle change ses invites après une mise à jour.

Le secret doit vivre quelque part

Chaque version de ce problème partage une faiblesse : le mot de passe doit exister sous une forme que le client peut lire. Le passer en argument l’expose dans la table des processus. L’afficher via un tube le met souvent dans l’historique du shell. Les deux sont lisibles par d’autres utilisateurs locaux sur un hôte de rebond partagé.

install -m 600 /dev/null ~/.vpn-secret
umask 077; VPN_PASSWORD=$(cat ~/.vpn-secret) /opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net

Un fichier en mode 600 appartenant au compte est le minimum, et il reste un secret en clair sur le disque. secret-tool lookup lit dans le trousseau Linux, et sous macOS security find-generic-password -w fait le même travail. Là où l’organisation prend en charge l’authentification par certificat ou SAML, préférez-la, car un mot de passe stocké et un MFA ne suffisent toujours pas à terminer une connexion sans un humain.

Confirmez le tunnel, puis prenez en charge la fermeture

Ne vous fiez pas à l’absence de texte d’erreur. Demandez son état au client et vérifiez l’interface séparément :

/opt/cisco/anyconnect/bin/vpn state
ip -brief address

L’état devrait indiquer Connected, et une interface de tunnel devrait avoir une adresse. Demandez ensuite une ressource que le tunnel est censé atteindre, car un état connecté sans route est un résultat réel et facile à manquer.

Déconnectez avec vpn disconnect, et laissez le script qui a lancé le tunnel prendre en charge la fermeture. Une tâche échouée qui laisse une session ouverte consomme une place de licence et ressemble à un problème d’authentification pour la personne suivante qui essaie.

Ordre du travail : confirmez vpnagentd, capturez l’ordre réel des invites, choisissez here-document ou expect, gardez le secret hors d’argv et de l’historique, vérifiez l’état et une ressource, puis déconnectez dans le même script.

Articles similaires