Um array $_ENV vazio num script de gancho parece prova de que o OpenVPN não passou nada. Normalmente é prova de algo completamente diferente: o PHP foi configurado para não preencher essa superglobal, e os valores estavam no ambiente do processo o tempo todo. A segunda conclusão falsa é mais subtil, porque as duas variáveis de endereço num gancho de ligação significam coisas diferentes e são usadas como se fossem equivalentes. Ambos os erros custam uma tarde se começar pelo errado.

Dois endereços, duas afirmações diferentes

O ponto final exterior é o que o servidor observou quando o cliente ligou, disponível como trusted_ip para IPv4 e trusted_ip6 para IPv6. O endereço virtual é o que o pool atribuiu a esta sessão, disponível como ifconfig_pool_remote_ip.

Respondem a perguntas diferentes, e um registo normalmente precisa de um deles, não dos dois. O primeiro é de onde veio a ligação, que pode ser um endereço NAT partilhado usado por centenas de pessoas. O segundo é onde esta sessão vive dentro do túnel, e pode ser reatribuído a outra sessão mais tarde. Confundir os dois produz registos que parecem plausíveis e estão errados.

Uma leitura mínima tem este aspecto.

$outer4 = getenv('trusted_ip');
$outer6 = getenv('trusted_ip6');
$inner  = getenv('ifconfig_pool_remote_ip');
$outer  = $outer4 !== false ? $outer4 : $outer6;

Nenhum dos valores identifica uma pessoa. Um é uma observação de rede, o outro é uma concessão, e um registo que trate qualquer deles como identificador estável de dispositivo estará errado na primeira vez que um cliente voltar a ligar-se de outra rede ou receber outro endereço do pool. Escolha o campo pela pergunta que o registo tem de responder e escreva essa pergunta ao lado da coluna.

Verifique como o PHP foi iniciado, não a sua shell

O gancho corre como filho do daemon VPN com um ambiente que o daemon constrói. A sua shell interativa tem outro, e executar o script à mão testa o ambiente da shell, não o do gancho.

Comece por confirmar que o gancho disparou realmente na fase que esperava. Um script ligado à fase errada, ou um que nunca correu porque a diretiva aponta para outro caminho, produz exatamente o mesmo sintoma que uma variável em falta. Acrescente uma linha marcadora deliberada no topo do script e confirme que aparece antes de inspecionar qualquer outra coisa. Uma única linha com data e hora no log separa «nunca correu» de «correu sem o valor».

Depois confirme que interpretador e que ficheiro de configuração essa invocação usa. Editar a configuração do PHP para um servidor web não muda nada num processo CLI iniciado pelo OpenVPN, e os dois podem carregar ficheiros php.ini completamente diferentes.

Porque um $_ENV vazio não prova nada

A referência do getenv do PHP documenta uma leitura direta do ambiente do processo, que devolve false quando o nome está ausente. A superglobal $_ENV é preenchida separadamente, e a diretiva variables_order decide que superglobais são preenchidas.

Se essa diretiva omitir E, $_ENV fica vazio independentemente do que o ambiente contiver. O código que o indexa passa então a reportar uma variável em falta que na verdade está presente, e a investigação segue para o OpenVPN quando a resposta está no php.ini. Verifique a diretiva especificamente para a configuração CLI, não para o servidor web.

Ler com getenv evita toda esta confusão, e um script de envolvimento que limpa o ambiente antes de invocar o interpretador volta a introduzi-la noutra forma.

Guarde uma associação, não uma atualização de linha

Decida de que valor o registo precisa antes de o escrever. Se o objetivo é assinalar de onde veio uma sessão, guarde o ponto final exterior e rotule-o como observação. Se o objetivo é mapear uma sessão a um endereço de túnel durante uma ligação, guarde o endereço do pool e associe-o à sessão.

Atualize pela identidade autenticada e pela sessão atual, não por cada linha que partilha um endereço de túnel, porque os endereços do pool são reutilizados e um evento de desconexão tardio pode sobrescrever os dados de uma ligação mais recente. Trate o IPv6 explicitamente em vez de escrever silenciosamente apenas o valor IPv4. Uma linha com o endereço exterior NULL é melhor do que uma linha com o errado, porque a primeira está visivelmente incompleta.

Associe a escrita ao identificador de sessão que o OpenVPN fornece para que uma reconexão crie um novo registo em vez de editar o antigo. Use instruções parametrizadas e uma conta com apenas as permissões de que a operação precisa. Um gancho corre com a autoridade do daemon, por isso uma consulta descuidada é um problema maior do que uma linha de log errada.

Diagnostique sem despejar o ambiente

Registe que nomes estavam presentes, que fase correu e que interpretador foi usado. Não imprima o ambiente completo, porque um processo de gancho pode herdar valores não relacionados que não deviam acabar num ficheiro de log.

Verifique uma ligação de ponta a ponta: leia o ponto final exterior, leia o endereço atribuído e confirme ambos contra a própria visão do servidor sobre essa sessão. Uma vez confirmado o par para um cliente, a associação pode ser confiada noutro sítio.

Artigos relacionados