De overtuiging is dat een here-document met vier regels een volledige niet-interactieve login is, en die houdt stand tot de gateway twee groepen aanbiedt, een banner afdrukt of na het wachtwoord om een token vraagt. Dan typt hetzelfde script het wachtwoord in een menu dat een getal verwachtte. De commandoregelclient op Linux is scriptbaar, maar alleen als je hem geeft waar hij echt op wacht, niet wat de handleiding aannam.

Het vaste here-document is een mythe

De Linux-client van Cisco installeert een klein programma op /opt/cisco/anyconnect/bin/vpn, en Secure Client 5 levert het nog steeds. Zolang de dienst vpnagentd draait, leest de vlag -s antwoorden van standaardinvoer in de volgorde waarin de client ze vraagt. Die volgorde ligt niet vast tussen servers.

Een groepsmenu voegt één regel toe. Een inlogbanner voegt er nog een toe. Een tokenvraag na het wachtwoord breekt een script van vier regels volledig, want de vijfde regel zou nooit het token zijn. De fout is stil: de client krijgt de verkeerde tekenreeks, de verbindingspoging eindigt en het script meldt niets bruikbaars.

Start de client één keer met de hand tegen dezelfde gateway en versie, en schrijf de prompts op in de volgorde waarin ze verschijnen. Dat transcript is de specificatie waaraan je script moet voldoen.

Waar de client op wacht

In het gangbare geval met één groep is de volgorde gebruikersnaam, wachtwoord en soms een bannerbevestiging. De eerste regel van een here-document wordt pas een menu-index als de server echt een menu toont, en daarom werkt hetzelfde script op de ene locatie en faalt het op de volgende.

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

Lees dat als vier antwoorden op vier mogelijke vragen, niet als een vast protocol. De nul is een menukeuze, geen wachtwoord, en de y aan het einde accepteert een banner die veel gateways nooit sturen.

Gebruik expect wanneer de volgorde niet voorspelbaar is

Wanneer de promptvolgorde wisselt, stop met regels tellen en wacht in plaats daarvan op de prompt. Een expect-script start het commando connect, wacht op de gebruikersnaamprompt, stuurt, wacht op de wachtwoordprompt, stuurt, en wacht dan op de verbonden toestand. Elke wachttijd heeft zijn eigen time-out.

Behandel een time-out als een fout en stop. Een script dat na een onverwachte prompt invoer blijft sturen, typt het wachtwoord graag in een shell, een menu of wat er toevallig ook leest. Zo wordt een inlogscript een incident.

Expect geeft je ook een transcript dat je met het geheim verwijderd kunt loggen, en dat is meer waard dan de exitcode wanneer een gateway na een upgrade zijn prompts wijzigt.

Het geheim moet ergens wonen

Elke versie van dit probleem heeft één zwakte: het wachtwoord moet bestaan in een vorm die de client kan lezen. Het als argument doorgeven legt het bloot in de procestabel. Het via een pijp echoën zet het vaak in de shellgeschiedenis. Beide zijn leesbaar voor andere lokale gebruikers op een gedeelde spronghost.

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

Een bestand met modus 600 dat eigendom is van het account is het minimum, en het is nog steeds een geheim in platte tekst op schijf. secret-tool lookup leest uit de Linux-sleutelring, en op macOS doet security find-generic-password -w hetzelfde werk. Waar de organisatie certificaat- of SAML-authenticatie ondersteunt, geef daar de voorkeur aan, want een opgeslagen wachtwoord plus MFA kan een login nog steeds niet voltooien zonder mens.

Bevestig de tunnel en neem dan de afsluiting over

Vertrouw niet op de afwezigheid van fouttekst. Vraag de client naar zijn toestand en controleer de interface onafhankelijk:

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

De toestand hoort Connected te lezen, en een tunnelinterface hoort een adres te hebben. Vraag dan één resource op die de tunnel hoort te bereiken, want een verbonden toestand zonder route is een echte uitkomst en makkelijk te missen.

Verbreek de verbinding met vpn disconnect, en laat het script dat de tunnel startte de afsluiting overnemen. Een mislukte taak die een sessie open laat, verbruikt een licentiestoel en ziet er voor de volgende persoon die het probeert uit als een authenticatieprobleem.

Werkvolgorde: bevestig vpnagentd, leg de werkelijke promptvolgorde vast, kies here-document of expect, houd het geheim buiten argv en geschiedenis, verifieer toestand en één resource, en verbreek dan de verbinding in hetzelfde script.

Gerelateerde artikelen