Um script de hook do OpenVPN pode usar o túnel que acabou de construir?
O OpenVPN executa hooks dentro do seu próprio arranque, então um script que precisa do túnel espera por um túnel que espera por ele. Desacople o trabalho e escolha o hook pelo evento.
Se um script de hook alcança o outro lado do túnel depende de três condições: a que evento está ligado, se o OpenVPN ainda está dentro da sua sequência de arranque quando o script corre e se o trabalho foi desacoplado dessa sequência. A maioria dos scripts falha na terceira. Acrescentar uma pausa trata um problema de ciclo de vida como um problema de temporização, e funciona o suficiente para enganar.
Decida primeiro o evento, depois o mecanismo de adiar o trabalho, depois o local onde o trabalho adiado corre. Essas três decisões são independentes, e misturá-las é como um hook de duas linhas se torna uma tarde inteira.
Porque é que o hook espera por um túnel que espera por ele
OpenVPN chama os seus hooks de forma síncrona, dentro do mesmo processo que move os pacotes. up dispara quando o dispositivo tun ou tap existe, mas antes de qualquer rota ser adicionada, e route-up dispara depois das rotas; nenhum dos dois momentos promete que a contraparte responda. Enquanto um script de qualquer dos hooks ainda corre, o daemon não encaminha, pelo que um comando que espera que o tráfego atravesse o túnel espera por um túnel que espera pelo comando. Esta espera circular é a razão pela qual uma execução manual passa e o hook entra em timeout.
O remendo óbvio, dormir alguns segundos, às vezes funciona porque o extremo remoto subiu sozinho, não porque a pausa tenha corrigido algo. Um auxiliar que consulta a prontidão é outra resposta: o hook retorna, o encaminhamento começa e o auxiliar obtém o que precisa quando está realmente lá.
Escolha o hook pelo evento, não pela conveniência
Ligue up ao trabalho que só precisa do dispositivo, route-up ao trabalho que precisa de rotas, e reserve client-connect e client-disconnect para tarefas por cliente do lado do servidor. A limpeza ao desligar tem de tolerar ser executada duas vezes, porque as reconexões sobre uma interface persistente não seguem a mesma sequência que um reinício completo. No servidor, client-connect dispara quando o cliente se autentica, não quando o daemon arranca, o que vale a pena confirmar antes de mover a lógica para lá. Se o trabalho pertence ao ciclo de vida do serviço e não a uma única ligação, uma unidade systemd é um lar melhor do que qualquer hook.
Os comandos do hook são executados diretamente pelo daemon, sem shell pelo meio, por isso ifconfig_remote numa linha up chega como texto literal. Envolva o comando numa shell explícita, ou mantenha a lógica num script que leia o ambiente. ipchange é uma diretiva que acrescenta os seus próprios argumentos: entrega o endereço e a porta ao comando, pelo que um script escrito para nenhum vê dois inesperados.
Três formas de desacoplar o trabalho
A primeira opção é enviar o auxiliar para segundo plano a partir do interior do hook: inicie-o com setsid ou systemd-run --scope, feche os descritores herdados e saia imediatamente com zero. A segunda é deixar o hook escrever um pequeno ficheiro de estado e deixar um temporizador systemd ou uma unidade de caminho agir sobre ele, o que mantém o hook trivial e coloca a política de repetição onde há registos. A terceira é abandonar o hook por completo e mover o trabalho para uma unidade ordenada depois do serviço VPN, que é a resposta certa quando o trabalho não é de todo por ligação. As três partilham uma regra: o hook tem de retornar antes de precisar do túnel.
Escolha o que escolher, torne o auxiliar idempotente e observável. Duas invocações sobrepostas não devem executar a mesma ação irreversível duas vezes, e um auxiliar que falha tem de deixar algo que uma pessoa possa ler.
Separe as falhas de sandbox das falhas de ciclo de vida
Quando um script corre a partir de uma linha root e falha como serviço, a causa é normalmente uma sandbox e não a rede. Uma ProtectHome restritiva, uma ProtectSystem só de leitura, ou um diretório de trabalho que não existe podem tornar o script ou os seus dados inalcançáveis, e num host SELinux o ficheiro também precisa de um contexto que permita a execução. Leia a unidade com systemctl cat openvpn-server@server e o registo com journalctl -u openvpn-server@server -n 80, e depois procure um erro de permissão ou de contexto em vez de um tempo limite de ligação. Desativar a sandbox deve ser o último movimento, não o primeiro.
Uma falha de ciclo de vida parece diferente: o hook arranca, o auxiliar corre e o socket simplesmente ainda não está lá. Escreva uma linha com marca temporal a partir do próprio hook, desligue e volte a ligar, e leia os eventos por ordem. Quando o auxiliar precisa mesmo do túnel, deixe-o consultar a prontidão em vez de dormir durante um período fixo.
Três campos tornam o relatório seguinte útil: que hook correu, que conta usou e onde parou. Sem eles, cada investigação posterior começa do zero.