Conserva o aplica SNAT a las IP de los clientes VPN en el borde de la nube
Conservar el origen mantiene la identidad del cliente en cada registro, SNAT mantiene pequeña la tabla de rutas. Tres condiciones dicen cuál necesita la aplicación.
Conservar la dirección del cliente VPN hasta la aplicación hace que cada línea de registro y cada entrada de la lista de permitidos signifiquen lo mismo. Reescribirla en el borde de la nube hace la tabla de rutas más sencilla y los registros menos útiles. Ninguna de las dos opciones es incorrecta por sí sola, y el argumento que la decide rara vez tiene que ver con el rendimiento. Tres condiciones lo resuelven: si la aplicación debe saber qué persona se conectó, si el tejido de la nube aceptará el origen que pretende enviar y quién aceptará hacerse cargo de la ruta de retorno después.
Tres condiciones lo deciden
Empieza por el requisito de la aplicación, no por el diagrama de red. Si la autorización o la auditoría dependen de la dirección individual del cliente, conservarla es un requisito funcional y traducirla es una regresión. Si la aplicación solo necesita saber que el tráfico llegó por la ruta de acceso remoto, una dirección traducida es suficiente y mucho más barata de operar.
La segunda condición es mecánica. Una red virtual no confía automáticamente en un paquete que afirma una dirección que no se asignó a la interfaz emisora. La mayoría de los tejidos de nube lo imponen, de formas y con nombres distintos, y un diseño que lo ignora parecerá correcto en un diagrama y descartará en silencio en producción.
La tercera es organizativa. Conservar los orígenes significa que la tabla de rutas de la subred de la aplicación debe apuntar de vuelta a la puerta de enlace para el prefijo del cliente, y cada equipo que añada una subred después debe mantener esa ruta coherente. Es un coste pequeño una vez y recurrente en docenas de cuentas. Decide quién lo paga antes de prometer el comportamiento.
Una ruta no es permiso para suplantar
Añadir una ruta de retorno dice a tu subred adónde deben ir las respuestas. No dice al tejido que la instancia que reenvía esos paquetes tenga permiso para emitirlos con un origen ajeno. En AWS el control relevante es la comprobación de origen y destino, y es visible por instancia:
aws ec2 describe-instances --instance-ids i-0a1b2c3d4e5f60718 \
--query "Reservations[].Instances[].SourceDestCheck"
aws ec2 modify-instance-attribute --instance-id i-0a1b2c3d4e5f60718 \
--no-source-dest-check
Desactívala solo para la instancia cuyo trabajo documentado es el reenvío, y para nada más. Cada VM de aplicación que mantiene la comprobación activada es una máquina menos que puede usarse para emitir tráfico con un origen prestado. Si tu plataforma no es AWS, busca el ajuste equivalente de anti-suplantación o de direcciones permitidas en lugar de suponer que el comportamiento se traslada.
Una captura de paquetes rápida resuelve la cuestión más rápido que leer la consola. Si las respuestas salen y el cliente nunca las ve, es el tejido el que descarta el origen suplantado, no la aplicación la que falla.
Qué compra la traducción y qué cuesta
Reescribir el origen en la puerta de enlace elimina el problema de la ruta de retorno. La aplicación ve una dirección que ya sabe cómo alcanzar, y el prefijo del cliente nunca tiene que aparecer en una tabla de rutas de la nube. En Linux la regla es una línea, y merece la pena escribir la versión más estrecha que puedas:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.20.8.0/24 -o ens5 -j SNAT --to-source 10.40.3.10
Fíjate en lo que la aplicación registra ahora: 10.40.3.10 para cada usuario, en cada conexión, para siempre. Cualquier lista de direcciones permitidas construida sobre ese valor ahora concede acceso a toda la población de acceso remoto, y cualquier revisión de incidente tiene que volver a la puerta de enlace para responder quién era.
La solución no es abandonar la traducción, es dejar de fingir que la dirección es una identidad. Lleva la identidad del cliente en un campo autenticado, regístrala en la puerta de enlace junto con la tupla traducida y deja que la aplicación se una por ella. Sin la clave de unión, la traducción convierte un problema de red en uno forense permanente.
El relé es una interfaz distinta
Un proxy inverso delante de la aplicación evita por completo la cuestión de la ruta enrutada. El proxy abre su propia conexión de backend, así que el prefijo del cliente nunca necesita ser enrutable dentro de la red virtual, y la aplicación puede recibir identidad en una cabecera que el proxy establece.
Esa cabecera solo es fiable cuando el backend la acepta del proxy y de nada más. En términos de nginx eso significa nombrar explícitamente al par de confianza en lugar de creer cualquier cosa que llegue:
set_real_ip_from 10.40.3.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Cualquier cliente que pueda alcanzar el backend directamente puede falsificar la misma cabecera, así que el backend debe ser inalcanzable salvo a través del proxy. Eso es un hecho de cortafuegos, no una opinión de configuración, y es la suposición que la gente se salta cuando copia el fragmento.
El relé también cambia lo que compras. Obtienes una identidad a nivel de aplicación y un lugar natural para registrarla; renuncias a la generalidad, porque cada protocolo nuevo necesita su propio soporte de proxy. Para los servicios HTTP ese intercambio suele ser bueno, y para cualquier cosa que no sea HTTP normalmente no está disponible en absoluto.
Anota qué ve cada borde
Elijas lo que elijas, la revisión de diseño debería terminar con una tabla que nombre la dirección de origen y la identidad demostrable en cada salto. Sin ella, el primer incidente produce tres equipos que describen cada uno un cliente distinto.
| Boundary | Source the next hop sees | What is actually proven |
|---|---|---|
| Client to gateway | 172.20.8.14 | A certificate or credential was presented |
| Gateway to app subnet, preserved | 172.20.8.14 | The same session, if the return route exists |
| Gateway to app subnet, translated | 10.40.3.10 | Only that traffic came through the gateway |
| Proxy to backend | 10.40.3.10 plus a header | The proxy asserted an identity it authenticated |
Luego elige. Conserva cuando la autorización de la aplicación dependa de verdad de la dirección del cliente y puedas asumir la ruta. Traduce cuando no sea así y puedas llevar la identidad fuera de banda, y usa las indicaciones de AWS para instancias de reenvío para los ajustes de reenvío específicos de la plataforma. Recurre a un relé cuando el servicio hable HTTP y quieras que la identidad deje de ser una dirección.