NAT de horquilla: por qué el extremo VPN falla desde dentro
Un cliente local que usa la dirección pública sale de la LAN y vuelve a entrar. Cuando el router no hace hairpin, fuera funciona y dentro no.
Un servidor VPN que responde desde una red móvil y falla desde el sofá normalmente no es un problema de certificado. El cliente dentro de la LAN pide al router que traduzca un paquete cuyo destino es la propia dirección pública del router, lo que significa que el paquete debe salir y volver a entrar de inmediato. Esa maniobra es el hairpinning, y muchos routers o no la implementan o solo lo hacen cuando se activa una casilla. Que la prueba desde fuera pase es lo que confunde, porque demuestra que el listener y la regla de reenvío están bien.
El paquete sale y vuelve a entrar
Siga el paquete. El cliente resuelve el nombre público, se conecta a la dirección pública y el NAT de destino del router reescribe el destino hacia el servidor interno. La respuesta del servidor se dirige a la dirección LAN del cliente, así que vuelve por la interfaz LAN del router sin atravesar nunca la regla NAT que habría destraduido el origen.
Ahora el cliente recibe un paquete de una dirección a la que nunca envió nada y lo descarta. Esa asimetría es toda la avería.
La RFC 4787 describe el comportamiento que se espera de un NAT en este caso, y la versión corta es que en la práctica es opcional incluso donde está especificado en teoría. Algunos routers llaman al ajuste NAT loopback, otros lo llaman hairpin NAT o NAT reflection, y algunos no exponen nada. Un router que carece de ello no está mal configurado; hace lo normal, y la solución corresponde a otro sitio. No concluya de una prueba local fallida que la regla de reenvío pública es incorrecta.
Comprobación 1: pruebe los dos caminos por separado
Desde fuera de la LAN, conéctese con el mismo perfil que usaría un usuario real y confirme que la sesión se establece. Desde dentro, conéctese a la dirección pública con el mismo perfil y anote el error exacto y la hora.
Una prueba local precisa conserva el nombre de host y solo sustituye la dirección: curl -v --resolve vpn.example.com:443:203.0.113.10 https://vpn.example.com/ envía la petición a la dirección pública presentando a la vez el nombre de servidor correcto. Eso separa un problema de resolución de nombres de un problema de traducción, que se confunden con facilidad cuando el mismo nombre funciona desde una cafetería. Anote si el cliente falla en la conexión TCP o más tarde en TLS, porque lo primero apunta a la traducción y lo segundo a la identidad.
Comprobación 2: lea lo que ve el servidor
La observación más útil es la visión del servidor. Ejecute una captura en el host VPN filtrada por la dirección LAN del cliente y por la dirección LAN del router, y luego repita el intento local. Si no llega nada, el paquete no sobrevivió a la traducción.
Si una conexión llega desde la dirección LAN del router en lugar de la del cliente, está ocurriendo hairpinning y el origen se reescribió. Esa es una configuración que funciona, no una avería.
Comprobación 3: arréglelo sin tocar el camino externo
Existen tres formas admitidas, en orden creciente de radio de impacto. La más estrecha es el DNS dividido: publique un registro interno para que el mismo nombre de servidor resuelva a la dirección interna para los clientes de la LAN, lo que evita por completo el camino público. La siguiente es habilitar la opción documentada de loopback o reflection del router, si la tiene, y aplicarla solo a este servicio. La más amplia es una regla source-NAT en el router que reescribe el tráfico proveniente de la LAN hacia el servidor para que la respuesta vuelva por el router; en un router Linux es una regla MASQUERADE en POSTROUTING que coincide con la dirección y el puerto del servidor. Las tres dejan intacto el camino externo, y esa es la propiedad que hay que preservar.
No amplíe el reenvío de puertos no relacionado para que el camino local se parezca al externo, ni mueva el servicio a otro puerto para eludir el problema. Ambos cambios alteran a qué puede llegar el mundo exterior para arreglar algo que solo ve el mundo interior.
El DNS dividido tiene una trampa que merece mencionarse. Sustituir un nombre de host por una IP arbitraria cambia lo que valida el cliente, así que el registro interno debe seguir coincidiendo con el nombre del certificado.
Comprobación 4: verifique ambos caminos después
Repita el intento externo desde fuera de la LAN, repita el intento interno con el mismo perfil y confirme que el registro del servidor muestra dos sesiones exitosas distintas en lugar de un éxito y un silencio. Después compruebe que otros clientes siguen llegando al listener y que las rutas a recursos privados no han cambiado.
Mantenga el registro corto: qué dirección usó cada cliente, qué vio el servidor y cuál de las tres soluciones se aplicó. Los requisitos de hairpinning de la RFC 4787 son la referencia de lo que se espera de un NAT aquí, y explican por qué un router sin la función se comporta con normalidad. Un fallo local que el mundo exterior no puede reproducir es una cuestión de traducción hasta que se demuestre lo contrario, así que pruébelo como tal.