Comecei desde fóra, como faría un usuario: escribín o nome no navegador dun teléfono con datos móbiles e vin como a conexión quedaba colgada ata caducar. O nome resolvíase, así que o DNS estaba ben. A páxina de redirección de portos do router da casa tamén era un calexón sen saída, porque o seu enderezo WAN marcaba 100.64.31.42, e ese non é un enderezo ao que un provedor me encamiñe desde internet. Ese número explica todo o fallo: a liña está detrás de carrier-grade NAT, así que o enderezo público do meu lado do túnel pertence ao provedor. O que segue é o camiño que percorrín desde esa pestana colgada ata un servizo que responde.

Comezar polo cliente e avanzar cara a dentro

Antes de cambiar calquera regra, demostra onde se detén a cadea. No portátil executei dig +short files.example.net e obtiven o enderezo do VPS, o que descartaba un DNS obsoleto na miña máquina. Despois, curl -v --connect-timeout 5 files.example.net:5022 caducou en vez de ser rexeitado. Esa diferenza importa: un tempo esgotado adoita significar que se están descartando paquetes polo camiño, mentres que un rexeitamento significa que algo respondeu e dixo que non.

O seguinte salto cara a dentro era o propio VPS. ss -ltnp non mostrou nada escoitando no 5022, o cal era agardable antes de que existise a regra DNAT. Na mesma máquina, wg show (ou ip -br a show tun0 para OpenVPN) confirmou que o par da casa estaba activo cun handshake recente. Se o par está caído, ningunha regra NAT axudará, e a luz verde da páxina VPN do router da casa non significa nada.

Confirmar que a liña da casa está realmente detrás de CGNAT

Compara o enderezo que o router informa na súa interface WAN co que ve un servizo externo. Todo o que está en 100.64.0.0/10, é dicir, 100.64.x.x ata 100.127.x.x, é o rango de enderezos compartidos do RFC 6598 e non se pode acadar desde internet. Chegas á mesma conclusión cando o router afirma ter un enderezo privado normal e unha consulta pública devolve algo que non ten relación. Unha liña CGNAT tamén pode traer un enderezo público que só dura ata o seguinte arrendamento, de xeito que unha redirección de porto parece funcionar unha hora e despois morre en silencio.

Algúns provedores si entregan un enderezo público real, pero bloquean os portos entrantes 80 e 443 en contas residenciais. Se o teu servizo é só web e o enderezo WAN é realmente público, pregunta ao soporte antes de construír un relé. Se non o é, o deseño de abaixo aplícase a todos os portos por igual, e paga a pena deter o experimento no lado do router: o tradutor da rede do provedor remata a conexión antes de que chegue á túa interface WAN.

Apuntar o nome ao enderezo do VPS

O DNS non retransmite tráfico, así que o rexistro A do servizo debe conter o enderezo público do VPS. Un rexistro A cara a 192.168.1.20 só se resolve de forma útil para clientes que xa están dentro da VPN; desde internet resólvese a un enderezo que ninguén pode encamiñar. Para o acceso de administración do propio VPS manteño un nome á parte, para non confundir nunca a que host apunta un rexistro.

Se tanto o VPS como a máquina da casa serven HTTP, dálle a cada un o seu propio nome e deixa que o VPS decida cal responde. Fundilos nun só nome e esperar que o proxy escolla o backend correcto é exactamente como acabas depurando o host equivocado durante toda unha tarde.

Un porto en DNAT, SSH queda no 22

A opción directa é NAT de destino no VPS. Activa o reenvío para o núcleo en execución e mantén o enderezo de túnel do servidor da casa na regra, non o seu enderezo 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

Deixa o SSH cara ao propio VPS no 22 e reenvía outro porto, por exemplo o 5022, á máquina da casa. Se reenvías o 22 a unha máquina apagada, perdes o único camiño que a podería ter arranxado. A mesma lóxica aplícase ao proxy: deixa o porto de administración do VPS fóra das regras de relé.

Fai persistentes as regras cando funcionen. En Debian ou Ubuntu, apt install iptables-persistent e despois netfilter-persistent save escríbenas en /etc/iptables/rules.v4. Nun host con firewalld o equivalente é un reenvío de porto permanente na zona, que necesita firewall-cmd --reload antes de aplicarse. As regras que só viven en memoria desaparecen no primeiro reinicio de mantemento do provedor, normalmente a unha hora mala.

Arranxar a ruta de volta, ou evitar necesitala

DNAT reescribe só o destino. O servidor da casa ve unha conexión desde o enderezo do cliente orixinal, e se a súa ruta por defecto apunta ao router da casa, a resposta sae pola WAN doméstica onde o tradutor do provedor a descarta. Esa asimetría foi o segundo fallo co que me atopei, despois de que a regra DNAT parecese completamente correcta.

Dous arranxos funcionan. Dálle á máquina da casa unha ruta de política para que o tráfico do túnel volva polo túnel:

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

Ou deixa que o VPS reescriba a orixe para que a resposta teña un enderezo que poida acadar, e deixa que conntrack a inverta á 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 versión SNAT agocha o enderezo real do cliente ao servidor da casa, así que os rexistros da aplicación mostran 10.8.0.1 como par. Pasa o enderezo orixinal na capa de aplicación, ou acepta perder o rexistro por cliente, pero decídeo a conciencia en vez de descubrilo durante un incidente.

Comprobar todo o camiño desde fóra

Verifica desde unha rede que non sexa nin o VPS nin a casa: un teléfono con datos móbiles, ou unha shell barata noutro sitio. nc -vz files.example.net 5022 debería informar dunha conexión correcta, e openssl s_client -connect files.example.net:443 -servername files.example.net debería mostrar o certificado do nome público. Despois revisa o grupo de seguridade ou a devasa na nube do provedor. Unha regra DNAT que nunca ve un paquete adoita estar bloqueada unha capa por riba do host.

Por último, decide que pasa cando o túnel cae. Unha regra DNAT segue aceptando conexións e aliméntaas en silencio cara a un túnel morto, o que parece exactamente un servizo roto. Unha comprobación de saúde no VPS que rexeite o porto mentres o par está caído custa unhas poucas liñas e aforra unha hora de conxecturas. Despois, deixa de editar regras e observa durante un día antes de confiar nel.

Artigos relacionados