A crença é que um here-document com quatro linhas é um login não interativo completo, e ela se sustenta até o gateway oferecer dois grupos, imprimir um banner ou pedir um token depois da senha. Então o mesmo script digita a senha em um menu que esperava um número. O cliente de linha de comando no Linux é scriptável, mas só se você lhe der o que ele realmente espera, e não o que o tutorial supôs.

O here-document fixo é um mito

O cliente Linux da Cisco instala um pequeno programa em /opt/cisco/anyconnect/bin/vpn, e o Secure Client 5 ainda o distribui. Com o serviço vpnagentd em execução, a flag -s lê as respostas da entrada padrão na ordem em que o cliente as pede. Essa ordem não é fixa entre servidores.

Um menu de grupos acrescenta uma linha. Um banner de login acrescenta outra. Um pedido de token depois da senha quebra por completo um script de quatro linhas, porque a quinta linha nunca seria o token. A falha é silenciosa: o cliente recebe a string errada, a tentativa de conexão termina e o script não relata nada útil.

Execute o cliente manualmente uma vez contra o mesmo gateway e versão e anote os prompts na ordem em que aparecem. Esse transcript é a especificação que seu script precisa cumprir.

O que o cliente espera

No caso comum de um único grupo, a sequência é nome de usuário, senha e, às vezes, uma confirmação de banner. A primeira linha de um here-document só vira índice de menu quando o servidor realmente apresenta um menu, e é por isso que o mesmo script funciona em um site e falha no seguinte.

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

Leia isso como quatro respostas para quatro perguntas possíveis, não como um protocolo fixo. O zero é uma seleção de menu, não uma senha, e o y final aceita um banner que muitos gateways nunca enviam.

Use expect quando a ordem não for previsível

Quando a ordem dos prompts varia, pare de contar linhas e espere pelo prompt. Um script expect inicia o comando connect, espera o prompt de nome de usuário, envia, espera o prompt de senha, envia e então espera o estado conectado. Cada espera tem seu próprio tempo limite.

Trate um tempo limite como falha e saia. Um script que continua enviando entrada depois de um prompt inesperado vai digitar alegremente a senha em um shell, em um menu ou em qualquer outra coisa que esteja lendo. É assim que um script de login vira um incidente.

O expect também entrega um transcript que você pode registrar com o segredo removido, e isso vale mais que o código de saída quando um gateway muda seus prompts depois de uma atualização.

O segredo precisa morar em algum lugar

Toda versão deste problema compartilha uma fraqueza: a senha precisa existir em uma forma que o cliente consiga ler. Passá-la como argumento a expõe na tabela de processos. Ecoá-la por um pipe muitas vezes a coloca no histórico do shell. Ambas são legíveis por outros usuários locais em um host de salto compartilhado.

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

Um arquivo com modo 600 pertencente à conta é o mínimo, e ainda é um segredo em texto puro no disco. secret-tool lookup lê do chaveiro do Linux, e no macOS o mesmo trabalho é feito por security find-generic-password -w. Onde a organização oferece autenticação por certificado ou SAML, prefira-a, porque uma senha armazenada mais MFA ainda não consegue concluir um login sem um humano.

Confirme o túnel e depois assuma a desconexão

Não confie na ausência de texto de erro. Pergunte ao cliente o estado dele e verifique a interface de forma independente:

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

O estado deve ler Connected, e uma interface de túnel deve ter um endereço. Então solicite um recurso que o túnel deveria alcançar, porque um estado conectado sem rota é um resultado real e fácil de passar despercebido.

Desconecte com vpn disconnect e deixe o script que iniciou o túnel assumir a desconexão. Um trabalho que falha e deixa uma sessão aberta consome uma licença e parece um problema de autenticação para a próxima pessoa que tentar.

Ordem do trabalho: confirme o vpnagentd, registre a ordem real dos prompts, escolha here-document ou expect, mantenha o segredo fora de argv e do histórico, verifique o estado e um recurso, e então desconecte no mesmo script.

Artigos relacionados