Programar um cliente VPN: escolha a camada antes da palavra-passe
A CLI do fornecedor, o rasdial, uma intenção de aplicação ou a automatização da interface falham cada um de forma diferente. Escolha a camada, mantenha o segredo fora de argv e espere pelo estado, não pelos códigos de saída.
Os scripts arrancam clientes VPN na camada que o autor escolheu, e essa camada raramente é a que a tarefa precisava. A linha de comandos do fornecedor, o marcador do sistema operativo e uma intenção de aplicação móvel voltam todos em momentos diferentes da vida da ligação. Também tratam o segredo de forma diferente, e essa diferença decide se a palavra-passe é visível para cada utilizador da máquina. Escolha a camada antes de escrever a primeira linha do script.
Camada 1: a linha de comandos do fornecedor
A maioria dos clientes de ambiente de trabalho inclui uma linha de comandos que aceita um nome de perfil e, demasiadas vezes, uma palavra-passe. O antigo cliente da Cisco aceitava um verbo connect com argumentos de utilizador e palavra-passe; o macOS expõe o serviço integrado através do networksetup; o NetworkManager responde ao nmcli. Estas chamadas voltam quando o comando termina, o que não é o mesmo momento em que o túnel fica utilizável. Leia a documentação do próprio fornecedor para a versão que instala, porque estas interfaces mudam e algumas são removidas por completo.
nmcli connection up "Work VPN"
networksetup -connectpppoeservice "Work VPN"
A vantagem é que o fornecedor conhece o seu próprio armazém de perfis, pelo que a chamada usa a mesma configuração que a GUI usaria. A desvantagem é que cada fornecedor inventa os seus próprios verbos, e um script escrito para um cliente não se transfere para outro. Considere esta camada como o caminho mais curto quando o cliente é fixo e a versão está fixada.
Camada 2: o serviço próprio do sistema operativo
No Windows, o marcador faz parte do sistema operativo e trabalha contra uma entrada da lista telefónica em vez do armazém de perfis do fornecedor. Isso torna-o mais portátil entre clientes e mais fácil de automatizar a partir de uma conta de serviço. Também significa que a ligação pode existir num sítio e não no outro, o que confunde quem olha para a lista errada.
rasdial "Work VPN" user pass
Get-VpnConnection -Name "Work VPN" | Select-Object ConnectionStatus
Use a superfície do PowerShell quando precisar de criar ou remover a entrada em vez de a marcar. As camadas WMI e cmdlet expõem os mesmos objetos com nomes diferentes, e a remoção é uma operação separada da desligação. Um script que apenas marca deixará entradas obsoletas após uma migração. Verifique para que armazém a sua automatização escreve antes de prometer que a limpeza acontece.
Remove-VpnConnection -Name "Old VPN" -Force
Get-VpnConnection
No macOS, o equivalente é a lista de serviços de rede, onde um serviço existente é ligado pelo nome em vez de ser criado na hora.
As credenciais escapam-se em cada camada, por isso escolha o canal
Tudo o que passa na linha de comandos aparece na tabela de processos para cada utilizador local, e normalmente também sobrevive no histórico da shell. A alternativa suportada do OpenVPN é ler o segredo a partir de um ficheiro com --askpass, e o próprio ficheiro precisa de permissões que correspondam à confiança que nele deposita. Um pipe com nome evita escrever o segredo no disco mas deixa qualquer processo capaz de o abrir escrever ali. No Windows, guarde o segredo no gestor de credenciais, ou num ficheiro que só a conta de serviço possa ler, e nunca como literal num ficheiro batch.
openvpn --config /etc/openvpn/work.conf --askpass /etc/openvpn/work.secret --auth-nocache --daemon
ls -l /etc/openvpn/work.secret
A mesma regra aplica-se a tokens e a códigos de uso único: se a automatização precisa deles, a automatização precisa de um canal que não seja um argumento da linha de comandos. Rode o segredo quando mudar o mecanismo, porque o valor antigo esteve num registo em algum sítio. Um script que funciona e que escapa não é um script que funcione.
Espere pelo estado e depois supervise um único proprietário
Cada uma destas chamadas volta antes de o túnel estar pronto, por isso consulte o estado que o cliente expõe ou teste um destino lá dentro com um tempo limite. Copiar ficheiros ou abrir uma ligação à base de dados logo após a chamada de ligação é uma corrida, e falha de forma intermitente de um modo que parece uma falha de rede.
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
A desligação tem o mesmo problema ao contrário: o processo pode terminar antes de as rotas terem desaparecido. Use os hooks do cliente onde existam, como os scripts up e down do OpenVPN ou o ExecStartPost de uma unidade systemd, porque são executados no ponto que realmente lhe importa. Os hooks são executados com os privilégios de quem os invocou, por isso um hook que reinicia a rede precisa de uma regra explícita em vez de uma suposição. Mantenha exatamente um proprietário durante a vida da ligação.
Quando dois supervisores arrancam e param o mesmo perfil, o resultado é um ciclo de reconexão que se lê como uma falha do fornecedor. O runbook termina quando a camada está documentada, o segredo tem um canal que não é argv, a condição de espera é uma verificação de estado com tempo limite, e um único processo possui o ciclo de vida.