Scrivere uno script per un client VPN: scegliere il livello prima della password
La CLI del fornitore, rasdial, un intent di app o l’automazione dell’interfaccia falliscono ognuno in modo diverso. Scegli il livello, tieni il segreto fuori da argv e attendi lo stato, non i codici di uscita.
Gli script avviano i client VPN al livello scelto dall’autore, e quel livello è raramente quello di cui aveva bisogno il lavoro. La riga di comando del fornitore, il compositore del sistema operativo e un intent di app mobile tornano tutti in momenti diversi della vita della connessione. Gestiscono anche il segreto in modo diverso, e quella differenza decide se la password è visibile a ogni utente della macchina. Scegli il livello prima di scrivere la prima riga dello script.
Livello 1: la riga di comando del fornitore
La maggior parte dei client desktop include una riga di comando che accetta un nome di profilo e, troppo spesso, una password. Il vecchio client di Cisco accettava un verbo connect con argomenti utente e password; macOS espone il servizio integrato tramite networksetup; NetworkManager risponde a nmcli. Queste chiamate tornano quando il comando è finito, che non è lo stesso momento in cui il tunnel diventa utilizzabile. Leggi la documentazione del fornitore per la versione che distribuisci, perché queste interfacce cambiano e alcune vengono rimosse del tutto.
nmcli connection up "Work VPN"
networksetup -connectpppoeservice "Work VPN"
Il vantaggio è che il fornitore conosce il proprio archivio di profili, quindi la chiamata usa la stessa configurazione che userebbe la GUI. Lo svantaggio è che ogni fornitore inventa i propri verbi, e uno script scritto per un client non si trasferisce a un altro. Considera questo livello come la via più breve quando il client è fisso e la versione è bloccata.
Livello 2: il servizio proprio del sistema operativo
Su Windows il compositore fa parte del sistema operativo e lavora su una voce della rubrica telefonica invece che sull’archivio di profili del fornitore. Questo lo rende più portabile tra client e più facile da gestire con uno script da un account di servizio. Significa anche che la connessione può esistere in un posto e non nell’altro, il che confonde chi guarda nell’elenco sbagliato.
rasdial "Work VPN" user pass
Get-VpnConnection -Name "Work VPN" | Select-Object ConnectionStatus
Usa la superficie di PowerShell quando devi creare o rimuovere la voce invece di comporla. I livelli WMI e cmdlet espongono gli stessi oggetti con nomi diversi, e la rimozione è un’operazione separata dalla disconnessione. Uno script che si limita a comporre lascerà voci obsolete dopo una migrazione. Controlla su quale archivio scrive la tua automazione prima di promettere che la pulizia avvenga.
Remove-VpnConnection -Name "Old VPN" -Force
Get-VpnConnection
Su macOS l’equivalente è l’elenco dei servizi di rete, dove un servizio esistente viene connesso per nome invece di essere creato al volo.
Le credenziali trapelano a ogni livello, quindi scegli il canale
Tutto ciò che passi sulla riga di comando compare nella tabella dei processi per ogni utente locale, e di solito sopravvive anche nella cronologia della shell. L’alternativa supportata di OpenVPN è leggere il segreto da un file con --askpass, e il file stesso ha bisogno di permessi che corrispondano alla fiducia che gli accordi. Una pipe con nome evita di scrivere il segreto su disco ma lascia che qualsiasi processo in grado di aprirla vi scriva. Su Windows, conserva il segreto nel gestore delle credenziali, o in un file che solo l’account di servizio può leggere, e mai come letterale in un file batch.
openvpn --config /etc/openvpn/work.conf --askpass /etc/openvpn/work.secret --auth-nocache --daemon
ls -l /etc/openvpn/work.secret
La stessa regola vale per token e codici monouso: se l’automazione ne ha bisogno, l’automazione ha bisogno di un canale che non sia un argomento della riga di comando. Ruota il segreto quando cambi il meccanismo, perché il vecchio valore è rimasto in un registro da qualche parte. Uno script che funziona e trapela non è uno script che funziona.
Attendi lo stato, poi sorveglia un solo proprietario
Ognuna di queste chiamate torna prima che il tunnel sia pronto, quindi interroga lo stato che il client espone o prova una destinazione al suo interno con un timeout. Copiare file o aprire una connessione al database subito dopo la chiamata di connessione è una corsa, e fallisce a intermittenza in un modo che sembra un guasto di rete.
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 disconnessione ha lo stesso problema al contrario: il processo può terminare prima che le rotte siano sparite. Usa gli hook del client dove esistono, come gli script up e down di OpenVPN o l’ExecStartPost di un’unità systemd, perché vengono eseguiti nel punto che ti interessa davvero. Gli hook vengono eseguiti con i privilegi di chi li ha invocati, quindi un hook che riavvia la rete ha bisogno di una regola esplicita invece di un’ipotesi. Mantieni esattamente un proprietario per tutta la vita della connessione.
Quando due supervisori avviano e fermano lo stesso profilo, il risultato è un ciclo di riconnessione che si legge come un guasto del fornitore. Il runbook finisce quando il livello è documentato, il segreto ha un canale che non è argv, la condizione di attesa è un controllo di stato con timeout, e un solo processo possiede il ciclo di vita.