Accesso a Cisco Secure Client da una shell Linux, senza interfaccia grafica
Un here-document non è un protocollo di accesso. Annota l’ordine reale dei prompt, usa expect quando varia e tieni la password fuori da argv e dalla cronologia.
La convinzione è che un here-document di quattro righe sia un accesso non interattivo completo, e regge finché il gateway non offre due gruppi, non stampa un banner o non chiede un token dopo la password. Allora lo stesso script digita la password in un menu che si aspettava un numero. Il client da riga di comando su Linux è scriptabile, ma solo se gli si dà ciò che sta davvero aspettando e non ciò che il tutorial ha dato per scontato.
L’here-document fisso è un mito
Il client Linux di Cisco installa un piccolo programma in /opt/cisco/anyconnect/bin/vpn, e Secure Client 5 lo fornisce ancora. Con il servizio vpnagentd in esecuzione, il flag -s legge le risposte dallo standard input nell’ordine in cui il client le chiede. Quest’ordine non è fisso tra server.
Un menu di gruppi aggiunge una riga. Un banner di accesso ne aggiunge un’altra. Una richiesta di token dopo la password spezza del tutto uno script di quattro righe, perché la quinta riga non doveva mai essere il token. Il guasto è silenzioso: il client riceve la stringa sbagliata, il tentativo di connessione finisce e lo script non riporta nulla di utile.
Esegui il client a mano una volta contro lo stesso gateway e la stessa versione, e annota i prompt nell’ordine in cui compaiono. Quella trascrizione è la specifica che il tuo script deve soddisfare.
Che cosa aspetta il client
Nel caso comune a gruppo singolo la sequenza è nome utente, password e talvolta una conferma del banner. La prima riga di un here-document diventa un indice di menu solo quando il server presenta davvero un menu, ed è per questo che lo stesso script funziona in un sito e fallisce nel successivo.
/opt/cisco/anyconnect/bin/vpn -s connect vpn.example.net <<EOF
0
alice
$VPN_PASSWORD
y
EOF
Leggilo come quattro risposte a quattro domande possibili, non come un protocollo fisso. Lo zero è una selezione di menu, non una password, e la y finale accetta un banner che molti gateway non inviano mai.
Usa expect quando l’ordine non è prevedibile
Quando l’ordine dei prompt varia, smetti di contare le righe e aspetta il prompt. Uno script expect avvia il comando connect, attende il prompt del nome utente, invia, attende il prompt della password, invia e poi attende lo stato connesso. Ogni attesa ha il proprio timeout.
Tratta un timeout come un guasto ed esci. Uno script che continua a inviare input dopo un prompt inatteso digiterà volentieri la password in una shell, in un menu o in qualunque altra cosa stia leggendo. È così che uno script di accesso diventa un incidente.
expect ti offre anche una trascrizione che puoi registrare senza il segreto, e vale più del codice di uscita quando un gateway cambia i suoi prompt dopo un aggiornamento.
Il segreto deve vivere da qualche parte
Ogni versione di questo problema condivide una debolezza: la password deve esistere in una forma che il client possa leggere. Passarla come argomento la espone nella tabella dei processi. Farla passare attraverso una pipe spesso la mette nella cronologia della shell. Entrambe sono leggibili da altri utenti locali su un host di salto condiviso.
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 file con modo 600 di proprietà dell’account è il minimo, e resta un segreto in chiaro sul disco. secret-tool lookup legge dal portachiavi di Linux, e su macOS lo stesso lavoro lo fa security find-generic-password -w. Dove l’organizzazione supporta l’autenticazione con certificato o SAML, preferiscila, perché una password memorizzata più MFA non basta ancora a completare un accesso senza una persona.
Conferma il tunnel, poi occupati della chiusura
Non fidarti dell’assenza di testo di errore. Chiedi al client il suo stato e controlla l’interfaccia separatamente:
/opt/cisco/anyconnect/bin/vpn state
ip -brief address
Lo stato dovrebbe dire Connected, e un’interfaccia di tunnel dovrebbe avere un indirizzo. Poi richiedi una risorsa che il tunnel dovrebbe raggiungere, perché uno stato connesso senza rotta è un esito reale e facile da trascurare.
Disconnetti con vpn disconnect e lascia che lo script che ha avviato il tunnel si occupi della chiusura. Un lavoro fallito che lascia una sessione aperta consuma un posto di licenza e sembra un problema di autenticazione alla persona successiva che ci prova.
Ordine di lavoro: conferma vpnagentd, cattura l’ordine reale dei prompt, scegli here-document o expect, tieni il segreto fuori da argv e dalla cronologia, verifica stato e una risorsa, poi disconnetti nello stesso script.