O cliente vpn que vem com o Cisco AnyConnect comporta-se como uma conversa: imprime um pedido, espera por uma linha e imprime a seguinte. Alimente essa conversa a partir de um ficheiro ou de um pipe e o mesmo binário corre sem supervisão. A técnica é um redirecionamento mais uma lista ordenada de respostas, e é a lista, não o redirecionamento, que decide se o script é fiável.

Duas coisas quebram isto na prática. A ordem dos pedidos muda quando um gateway pergunta algo extra, e uma palavra-passe guardada transforma um erro de escrita num bloqueio de conta. Trate a sequência como dados versionados que pode comparar após qualquer alteração no gateway. Falhe em voz alta em vez de tentar de novo, porque o ciclo é exatamente a forma como uma palavra-passe mal escrita se torna numa conta bloqueada.

Uma sequência, pela ordem em que o cliente pergunta

Execute o cliente de forma interativa uma vez e anote cada pedido pela ordem em que aparece. Essa transcrição torna-se no ficheiro de respostas. Quando redireciona o ficheiro para o binário, a primeira linha tem de ser o próprio comando de ligação, e é por isso que a sequência começa por um nome de anfitrião em vez de um nome de utilizador.

connect vpn.example.com
0
<username>
<password>
y
exit

O 0 simples seleciona o primeiro perfil de ligação quando o gateway oferece uma lista; use o índice que o seu gateway imprime. O y aceita um banner de início de sessão, por isso apague essa linha se não houver banner e insira uma onde o seu gateway faça uma pergunta adicional. O exit final é o que permite ao cliente terminar de forma limpa quando a última resposta foi consumida.

/opt/cisco/anyconnect/bin/vpn -s < anyconnect.txt

O modo não interativo não é opcional aqui. Sem -s o cliente pode apoderar-se do terminal e ignorar a entrada redirecionada; com ele, as respostas são lidas do fluxo e o processo devolve. Onde o binário exige privilégios elevados, envolva a chamada em sudo -n para que o script falhe de imediato em vez de bloquear num pedido de palavra-passe.

Onde o ficheiro de respostas fica exposto

Um ficheiro que contém uma palavra-passe é uma credencial, por isso dê-lhe as permissões de uma: modo 600, propriedade da conta que executa a tarefa, e nunca dentro de um diretório partilhado ou sincronizado. Crie-o com o modo já aplicado em vez de o corrigir depois, porque um ficheiro fica brevemente legível por todos entre a escrita e o chmod.

install -m 600 /dev/null ~/.config/anyconnect.txt
chmod 700 ~/.config

A outra metade é o argv. Uma palavra-passe passada como argumento é visível a qualquer utilizador local que liste processos, e também acaba no histórico da shell. Leia-a de um descritor de ficheiro ou de uma variável de ambiente, e ponha a carga entre aspas para que a shell não possa expandir nada lá dentro.

printf '%s\n' 'connect vpn.example.com' '0' "$VPN_USER" "$VPN_PASS" 'y' 'exit' \
  | sudo -n /opt/cisco/anyconnect/bin/vpn -s

Tenha cuidado com as aspas. Dentro de aspas duplas, uma palavra-passe que contenha ! pode ser expandida por uma shell interativa antes de o cliente a ver, e a falha chega como um erro genérico event-not-found que parece um problema de protocolo.

Prove o túnel e depois feche-o

Um estado ligado só prova que o cliente acredita ter uma sessão. Escolha um anfitrião que só responda de dentro da rede corporativa e teste-o uma vez antes de fazer mais alguma coisa. Uma falha aí é um problema de encaminhamento ou de política, e voltar a executar o início de sessão não o mudará.

/opt/cisco/anyconnect/bin/vpn state
curl -sS -o /dev/null -w '%{http_code}\n' --max-time 10 https://<internal-host>/
/opt/cisco/anyconnect/bin/vpn disconnect

Verifique a saída de estado antes e depois da desligação. Um cliente deixado com uma sessão obsoleta pode recusar a ligação seguinte enquanto o script ainda relata sucesso, e esse modo de falha é invisível se olhar apenas para os códigos de saída. Compare as duas leituras em vez de confiar na segunda isoladamente. Os aliases num perfil de shell bastam para uso diário, mas tudo o que é agendado merece a mesma revisão de credenciais e identidade que qualquer outro trabalho sem supervisão.

Quando uma lista fixa deixa de ser segura

Um ficheiro de respostas codifica a ordem de pedidos de hoje. Um banner alterado, uma mudança de palavra-passe forçada ou um desafio de segundo fator transformam-no num ciclo que pode bloquear a conta, e por isso o script tem de sair no primeiro resposta inesperada em vez de reiniciar.

Capture o que o cliente imprimiu, devolva um estado diferente de zero e deixe a decisão para quem chama. Onde o gateway exige um segundo fator, a resposta honesta é que um início de sessão sem supervisão não está disponível para esse perfil, e não que a sequência precise de mais uma linha.

A rotação pertence à mesma revisão. Se a credencial for guardada, decida quem a pode ler, quando muda e o que a remove quando o anfitrião é reconstruído. Um script que funciona durante um ano porque ninguém tocou na palavra-passe não é um desenho, é um acidente à espera de uma política de rotação.

Perfis que não são AnyConnect

Dois estilos de credenciais Cisco mais antigos são confundidos com este. Um perfil vpnc pede um IPSec ID, que na realidade é o nome do grupo, depois um segredo de grupo, depois as suas próprias credenciais, e os três vêm de quem administra o gateway. O Cisco IPsec antigo é um protocolo diferente do AnyConnect, por isso vpnc não consegue chegar a um serviço só de AnyConnect; openconnect --protocol=anyconnect é o cliente aberto para essa tarefa.

Um ficheiro .pcf descreve o perfil do cliente mais antigo. O anfitrião, o nome do grupo e a palavra-passe de grupo que contém podem ser reintroduzidos à mão num cliente que fale Cisco IPsec, embora o ficheiro não seja um import universal e qualquer porta ou modo de tunelização não predefinido geralmente desaparece na transferência.

Comece pelo que o gateway oferece realmente e depois escolha o cliente que fala esse protocolo. Copiar um perfil de outro sítio é a forma como as pessoas acabam a depurar credenciais que nunca foram o problema.

Artigos relacionados