NAT em grampo: por que o endpoint VPN falha por dentro
Um cliente local que usa o endereço público sai da LAN e volta a entrar. Quando o router não faz hairpin, funciona por fora e não por dentro.
Um servidor VPN que responde de uma rede móvel e falha do sofá normalmente não é um problema de certificado. O cliente dentro da LAN pede ao router que traduza um pacote cujo destino é o próprio endereço público do router, o que significa que o pacote tem de sair e voltar a entrar imediatamente. Essa manobra chama-se hairpinning, e muitos routers ou não a implementam ou só o fazem quando uma caixa de seleção está ativa. É o sucesso do teste por fora que torna a coisa confusa, porque prova que o listener e a regra de encaminhamento estão bem.
O pacote sai e volta a entrar
Siga o pacote. O cliente resolve o nome público, liga-se ao endereço público, e o NAT de destino do router reescreve o destino para o servidor interno. A resposta do servidor é endereçada ao endereço LAN do cliente, por isso volta pela interface LAN do router sem nunca atravessar a regra NAT que teria destraduzido a origem.
Agora o cliente recebe um pacote de um endereço para o qual nunca enviou nada, e descarta-o. Essa assimetria é toda a avaria.
A RFC 4787 descreve o comportamento esperado de um NAT neste caso, e a versão curta é que na prática é opcional mesmo onde está especificado em teoria. Alguns routers chamam ao parâmetro NAT loopback, outros chamam-lhe hairpin NAT ou NAT reflection, e alguns não expõem nada. Um router que não o tem não está mal configurado; faz a coisa normal, e a correção pertence a outro lugar. Não conclua de um teste local falhado que a regra de encaminhamento pública está errada.
Verificação 1: teste os dois caminhos separadamente
De fora da LAN, ligue-se com o mesmo perfil que um utilizador real usaria e confirme que a sessão é estabelecida. De dentro, ligue-se ao endereço público com o mesmo perfil e anote o erro exato e a hora.
Um teste local preciso mantém o nome do host e substitui apenas o endereço: curl -v --resolve vpn.example.com:443:203.0.113.10 https://vpn.example.com/ envia o pedido para o endereço público apresentando ainda o nome de servidor correto. Isso separa um problema de resolução de nomes de um problema de tradução, fáceis de confundir quando o mesmo nome funciona a partir de um café. Anote se o cliente falha na ligação TCP ou mais tarde em TLS, porque o primeiro aponta para a tradução e o segundo para a identidade.
Verificação 2: leia o que o servidor vê
A observação mais útil é a visão do servidor. Execute uma captura no host VPN filtrada pelo endereço LAN do cliente e pelo endereço LAN do router, e depois repita a tentativa local. Se nada chegar, o pacote não sobreviveu à tradução.
Se uma ligação chegar do endereço LAN do router em vez do do cliente, está a ocorrer hairpinning e a origem foi reescrita. É uma configuração que funciona, não uma avaria.
Verificação 3: corrija sem tocar no caminho externo
Existem três formas suportadas, por ordem crescente de raio de impacto. A mais estreita é o DNS dividido: publique um registo interno para que o mesmo nome de servidor resolva no endereço interno para os clientes da LAN, o que evita por completo o caminho público. A seguinte é ativar a opção documentada de loopback ou reflection do router, se existir, e aplicá-la apenas a este serviço. A mais ampla é uma regra source-NAT no router que reescreve o tráfego proveniente da LAN para o servidor, para que a resposta volte pelo router; num router Linux é uma regra MASQUERADE em POSTROUTING que corresponde ao endereço e à porta do servidor. As três deixam o caminho externo intacto, e é essa a propriedade a preservar.
Não alargue o encaminhamento de portas não relacionado para que o caminho local se pareça com o externo, nem mude o serviço para outra porta para contornar o problema. Ambas as alterações mudam o que o mundo exterior consegue alcançar para corrigir algo que só o mundo interior vê.
O DNS dividido tem uma armadilha que vale a pena nomear. Substituir um nome de host por um IP arbitrário muda o que o cliente valida, por isso o registo interno tem de continuar a coincidir com o nome do certificado.
Verificação 4: verifique ambos os caminhos depois
Repita a tentativa externa de fora da LAN, repita a tentativa interna com o mesmo perfil e confirme que o registo do servidor mostra duas sessões bem-sucedidas distintas em vez de um sucesso e um silêncio. Depois verifique que outros clientes continuam a alcançar o listener e que as rotas para recursos privados não mudaram.
Mantenha o registo curto: que endereço usou cada cliente, o que viu o servidor e qual das três correções foi aplicada. Os requisitos de hairpinning da RFC 4787 são a referência para o que se espera de um NAT aqui, e explicam porque é que um router sem a funcionalidade se comporta normalmente. Uma falha local que o mundo exterior não consegue reproduzir é uma questão de tradução até prova em contrário, por isso teste-a como tal.