Comecei de fora, como um utilizador faria: escrevi o nome no navegador de um telemóvel em dados móveis e vi a ligação ficar pendurada até expirar. O nome resolvia, portanto o DNS estava bem. A página de encaminhamento de portas do router de casa também era um beco sem saída, porque o endereço WAN mostrava 100.64.31.42, e não é um endereço para o qual um operador me encaminhe a partir da internet. Esse número explica toda a falha: a linha está atrás de carrier-grade NAT, logo o endereço público do meu lado do túnel pertence ao operador. O que se segue é o caminho que percorri desde esse separador pendurado até um serviço que responde.

Começar no cliente e avançar para dentro

Antes de alterar qualquer regra, prove onde a cadeia para. No portátil executei dig +short files.example.net e obtive o endereço do VPS, o que excluía DNS desatualizado na minha máquina. Depois, curl -v --connect-timeout 5 files.example.net:5022 expirou em vez de ser recusado. Essa diferença importa: um tempo esgotado costuma significar que os pacotes estão a ser descartados pelo caminho, enquanto uma recusa significa que algo respondeu e disse não.

O salto seguinte para dentro era o próprio VPS. ss -ltnp não mostrou nada à escuta na 5022, o que era esperado antes de a regra DNAT existir. Na mesma máquina, wg show (ou ip -br a show tun0 para OpenVPN) confirmou que o par de casa estava ativo com um handshake recente. Se o par estiver em baixo, nenhuma regra NAT ajuda, e a luz verde na página VPN do router de casa não significa nada.

Confirmar que a linha de casa está mesmo atrás do CGNAT

Compare o endereço que o router indica na sua interface WAN com o que um serviço externo vê. Tudo o que esteja em 100.64.0.0/10, ou seja, 100.64.x.x até 100.127.x.x, é o intervalo de endereços partilhados do RFC 6598 e não é alcançável a partir da internet. Chega à mesma conclusão quando o router afirma ter um endereço privado comum e uma consulta pública devolve algo sem relação. Uma linha CGNAT também pode trazer um endereço público que só dura até ao próximo lease, pelo que um encaminhamento de porta parece funcionar durante uma hora e depois morre em silêncio.

Alguns operadores atribuem mesmo um endereço público real, mas bloqueiam as portas de entrada 80 e 443 em contas residenciais. Se o seu serviço for apenas web e o endereço WAN for genuinamente público, pergunte ao suporte antes de construir um relay. Se não for, o desenho abaixo aplica-se a todas as portas por igual, e vale a pena parar a experiência do lado do router: o tradutor na rede do operador termina a ligação antes de ela chegar à sua interface WAN.

Apontar o nome para o endereço do VPS

O DNS não encaminha tráfego, por isso o registo A do serviço tem de conter o endereço público do VPS. Um registo A para 192.168.1.20 só resolve de forma útil para clientes que já estão dentro da VPN; a partir da internet resolve para um endereço que ninguém consegue encaminhar. Para o acesso de administração do próprio VPS mantenho um nome separado, para nunca confundir para que host aponta um registo.

Se tanto o VPS como a máquina de casa servirem HTTP, dê a cada um o seu próprio nome e deixe o VPS decidir qual responde. Juntá-los num só nome e esperar que o proxy escolha o backend certo é exatamente como se acaba a depurar o host errado durante uma tarde.

Uma porta em DNAT, SSH fica na 22

A opção direta é NAT de destino no VPS. Ative o forwarding para o kernel em execução e mantenha o endereço de túnel do servidor de casa na regra, não o seu endereço LAN:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -p tcp -d 198.51.100.10 --dport 5022 -j DNAT --to-destination 10.8.0.2

Deixe o SSH para o próprio VPS na 22 e encaminhe outra porta, por exemplo 5022, para a máquina de casa. Se encaminhar a 22 para uma máquina desligada, perde o único caminho que a poderia ter reparado. A mesma lógica aplica-se ao proxy: deixe a porta de gestão do VPS fora das regras de relay.

Torne as regras persistentes assim que funcionarem. No Debian ou Ubuntu, apt install iptables-persistent e depois netfilter-persistent save escrevem-nas em /etc/iptables/rules.v4. Num host com firewalld o equivalente é um encaminhamento de porta permanente na zona, que precisa de firewall-cmd --reload antes de se aplicar. As regras que vivem apenas em memória desaparecem no primeiro reinício de manutenção do fornecedor, normalmente a uma hora má.

Corrigir a rota de retorno, ou evitar precisar dela

O DNAT reescreve apenas o destino. O servidor de casa vê uma ligação a partir do endereço do cliente original e, se a sua rota predefinida apontar para o router de casa, a resposta sai pela WAN doméstica onde o tradutor do operador a descarta. Essa assimetria foi a segunda falha que encontrei, depois de a regra DNAT parecer completamente correta.

Duas correções funcionam. Dê à máquina de casa uma rota de política para que o tráfego do túnel volte pelo túnel:

ip rule add from 10.8.0.2 table 100
ip route add default dev wg0 table 100

Ou deixe o VPS reescrever a origem para que a resposta tenha um endereço que consiga alcançar, e deixe o conntrack invertê-la à saída:

iptables -t nat -A POSTROUTING -d 10.8.0.2 -p tcp --dport 5022 -j SNAT --to-source 10.8.0.1

A versão SNAT esconde o endereço real do cliente ao servidor de casa, por isso os registos da aplicação mostram 10.8.0.1 como par. Passe o endereço original na camada de aplicação, ou aceite perder o registo por cliente, mas decida-o de propósito em vez de o descobrir durante um incidente.

Verificar todo o caminho a partir de fora

Verifique a partir de uma rede que não seja o VPS nem a casa: um telemóvel em dados móveis, ou uma shell barata noutro sítio. nc -vz files.example.net 5022 deve indicar uma ligação bem-sucedida, e openssl s_client -connect files.example.net:443 -servername files.example.net deve mostrar o certificado do nome público. Depois verifique o security group ou a firewall cloud do fornecedor. Uma regra DNAT que nunca vê um pacote costuma estar bloqueada uma camada acima do host.

Por fim, decida o que acontece quando o túnel cai. Uma regra DNAT continua a aceitar ligações e enfia-as silenciosamente num túnel morto, o que se parece exatamente com um serviço avariado. Uma verificação de saúde no VPS que recuse a porta enquanto o par está em baixo custa poucas linhas e poupa uma hora de suposições. Depois, pare de editar regras e observe durante um dia antes de confiar.

Artigos relacionados