Nada anima un proyecto de VPN rutinario como descubrir que ambos extremos usan 10.0.0.0/8. De repente cada ruta miente, la mitad de tus paquetes van al sitio equivocado, y alguien pregunta por qué “la VPN está arriba” pero la base de datos sigue caída.
NAT a través de VPN es la forma pragmática de conectar redes superpuestas sin renumerar todo el entorno hoy. No es “limpio”, pero a menudo es la opción menos mala que mantiene la producción estable mientras compras tiempo para una higiene de IP adecuada.
El problema real: redes superpuestas y enrutamiento ambiguo
Cuando dos redes comparten el mismo espacio IP, el enrutamiento se vuelve ambiguo. Si el Sitio A es 10.20.0.0/16 y el Sitio B también es 10.20.0.0/16, tu router no puede distinguir “remoto 10.20.1.10” de “local 10.20.1.10”. Un túnel VPN no soluciona eso. Una VPN es solo un camino; el enrutamiento sigue decidiendo a dónde van los paquetes.
En diseños sin superposición, anuncias rutas (estáticas, BGP, OSPF, lo que sea), y el tráfico fluye. En diseños con superposición, los anuncios de rutas son activamente peligrosos. Tus hosts pueden intentar alcanzar direcciones “remotas” mediante ARP local. O puedes hacer blackhole del tráfico al seleccionar la ruta “equivocada” por preferencia de métrica. Peor: puede parecer bien desde una dirección y fallar desde la otra, que es el tipo de problema que convierte los cerebros de on-call en puré.
NAT a través de VPN evita la ambigüedad traduciendo un lado (a veces ambos) a un rango de direcciones “virtual” único para cruzar el túnel. Mantienes el direccionamiento interno sin cambios. El túnel ve un mundo sin superposición. El enrutamiento vuelve a ser determinista.
Dos reglas para mantenerte honesto:
- No estás arreglando la superposición; la estás aislando. NAT es una capa de compatibilidad, no una cura.
- Si puedes renumerar de forma segura, hazlo. NAT a través de VPN es lo que haces cuando “de forma segura” no está disponible este trimestre.
Hechos e historia que explican por qué esto sigue ocurriendo
- RFC 1918 (1996) definió el espacio privado IPv4 (
10/8,172.16/12,192.168/16), lo que convirtió “usar 10.x” en el reflejo corporativo por defecto. - NAT se popularizó a finales de los 90 cuando la ansiedad por el agotamiento de IPv4 se encontró con la realidad del crecimiento empresarial. Resolvió la escasez de direcciones pero normalizó la reutilización de direcciones.
- IPsec se diseñó con identidad IP extremo a extremo en mente; NAT fue un vecino incómodo, lo que llevó a NAT-T (NAT traversal) para llevar ESP sobre UDP.
- Muchas empresas copiaron rangos de laboratorio de proveedores (
10.0.0.0/8y192.168.0.0/16) porque “funcionaba en la demo”, y luego escalaron ese error a miles de subredes. - Fusiones y adquisiciones son una fábrica de superposiciones: dos redes maduras colisionan, ambas convencidas de que su
10.0.0.0/8es el único10/8. - Los predeterminados de VPC en la nube (como redes iniciales
10.0.0.0/16) hicieron la superposición aún más probable cuando equipos montaban entornos sin IPAM central. - Carrier-grade NAT enseñó a una generación a aceptar la traducción como normal, incluso cuando rompe protocolos que incrustan IPs en la carga útil.
- Algunos sistemas industriales y legados fijan IPs en configuraciones, licencias o ACLs, convirtiendo la renumeración en un evento de “preguntar a legal” en lugar de una tarea de ingeniería.
Una idea para tener en mente parafraseada: paraphrased idea
de Richard Cook (operaciones y seguridad): los sistemas tienen éxito porque la gente se adapta; los fracasos ocurren cuando la complejidad supera esas adaptaciones.
Patrones de diseño: cómo se hace NAT a través de VPN en sistemas reales
Patrón 1: NAT “subred alias” unidireccional (más común, menos confuso)
Elige un CIDR “alias” no superpuesto que exista solo como destino de traducción. Ejemplo:
- Sitio A real:
10.20.0.0/16 - Sitio B real:
10.20.0.0/16(sí, igual) - Alias para Sitio B visto desde A:
172.31.20.0/24(o mayor)
Sitio A enruta 172.31.20.0/24 hacia la VPN. En el borde VPN del Sitio B, haces DNAT 172.31.20.x → 10.20.x, y SNAT el tráfico de retorno para que vuelva desde 172.31.20.x. Esto hace que las sesiones sean simétricas y enrutable.
Cuándo usarlo: cuando solo un lado necesita alcanzar al otro, o cuando puedes tolerar direcciones “reales vs alias” asimétricas en configuraciones.
Patrón 2: NAT bidireccional (dos espacios alias)
Si ambos lados se superponen y ambos deben iniciar conexiones, a menudo necesitas dos espacios alias:
- Alias para A visto por B:
172.31.10.0/24 - Alias para B visto por A:
172.31.20.0/24
Esto evita “¿quién es 10.20.1.10?” por completo a través del túnel. También duplica las piezas móviles, lo que dobla las formas de equivocarse sutilmente.
Patrón 3: NAT solo para servicios específicos (NAT quirúrgico)
A veces no necesitas “conectividad de red”. Necesitas “TCP/5432 desde la app hasta la DB”. En esos casos, traduce solo los VIPs de servicio:
- Crea un rango alias pequeño (incluso /32s)
- DNAT esos IP alias a los servidores reales
- Limita las políticas de firewall a esos puertos
Esto reduce el radio de impacto. También te obliga a documentar dependencias, lo cual siempre es popular hasta que pides a alguien que lo haga.
Patrón 4: Proxies a nivel de aplicación en lugar de NAT (cuando NAT te romperá)
Algunos protocolos odian NAT. SIP, ciertos modos de FTP, demonios de licencias extraños y cualquier cosa que inserte IPs en la carga útil puede comportarse como si fuera 2003 otra vez. Si la aplicación se rompe, deja de discutir con paquetes y usa un proxy:
- HTTP(S): reverse proxy o forward proxy
- Bases de datos: proxy TCP con health checks
- SSH: bastion/jump host
Los proxies cuestan esfuerzo operativo pero pueden salvarte de casos límite de traducción, especialmente con protocolos que abren múltiples conexiones.
Patrón 5: Filtrado de rutas con VRFs (evita NAT cuando la superposición es “organizativa”)
Si la superposición existe porque las redes estaban separadas lógicamente, las VRF a veces pueden solucionarlo sin NAT manteniendo dos prefijos idénticos en tablas de enrutamiento separadas. Eso es elegante en routers capaces y miserable en una VM Linux cualquiera actuando como gateway VPN. Úsalo si ya ejecutas VRFs y tus endpoints VPN las soportan bien.
Broma #1: NAT es como cinta americana—fuerte, versátil y de algún modo siempre presente en la reconstrucción de la escena del crimen.
Cómo elegir un enfoque (y qué estás realmente intercambiando)
Tu decisión gira mayormente en tres tensiones:
- Claridad operativa vs rapidez: Renumerar es claro y a prueba de futuro, pero lento. NAT es rápido, pero lo depurarás a las 2 a.m.
- Simetría vs simplicidad: NAT unidireccional es más simple pero puede sorprender al “otro” lado. NAT bidireccional es simétrico pero complejo.
- Observabilidad vs opacidad: La traducción puede ocultar IPs originales a menos que registres los mappings de conntrack/NAT y preserves contexto en logs.
Usa esto como una regla práctica:
- Si es un puente por una fusión con muchos servicios y dependencias desconocidas: empieza con NAT quirúrgico o proxies. Expande solo cuando entiendas el tráfico.
- Si es una app → una dependencia: haz NAT de VIP de servicio. No traduzcas subredes enteras “porque es más fácil”.
- Si es un interconectado a largo plazo con muchos iniciadores en ambas direcciones: considera NAT bidireccional pero también programa la renumeración. NAT no debería convertirse en arquitectura.
Recorrido de paquete: qué le ocurre a una conexión TCP
Ejemplo: la app en Sitio A (10.20.5.10) necesita Postgres en Sitio B (10.20.8.25). Existe superposición, así que le damos a B una IP alias 172.31.20.25 que A usará.
- La app conecta:
10.20.5.10:54012→172.31.20.25:5432. - Enrutamiento en Sitio A envía
172.31.20.0/24al gateway VPN, dentro del túnel. - El gateway VPN del Sitio B DNAT reescribe destino:
172.31.20.25→10.20.8.25. - El gateway del Sitio B SNAT (importante) reescribe el origen a un alias estable (o IP del gateway) para que los paquetes de retorno se obliguen a volver por el gateway y puedan ser des-transladados consistentemente.
- El servidor responde al origen SNAT, no directamente a
10.20.5.10(lo cual sería ambiguo localmente y probablemente erróneo). - El gateway des-translada en la ruta de retorno, de modo que la app vea respuestas desde
172.31.20.25, manteniendo la consistencia de la sesión.
Si omites el paso de SNAT, obtendrás el clásico fallo “SYN pasa, SYN-ACK desaparece”. Eso no es un misterio. Es enrutamiento asimétrico causado por tu propio optimismo.
Tareas prácticas: comandos, salidas y la decisión que tomas
El objetivo aquí no es ejecutar comandos por deporte. Cada tarea responde a una pregunta, y cada respuesta obliga a una decisión.
Tarea 1: Confirma que la superposición es real (y cuán grande es el radio de impacto)
cr0x@server:~$ ip -br addr
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 10.20.5.254/24
wg0 UP 10.99.0.1/24
Qué significa: Ves subredes locales. Este host está en 10.20.5.0/24.
Decisión: Si el lado remoto también usa 10.20.0.0/16 o similar, no puedes enrutarlo directamente. Necesitas NAT, VRFs o renumeración.
Tarea 2: Comprueba tu ruta al subnet alias (¿el tráfico entra siquiera en la VPN?)
cr0x@server:~$ ip route get 172.31.20.25
172.31.20.25 dev wg0 src 10.99.0.1 uid 0
cache
Qué significa: El tráfico hacia la IP alias irá por wg0.
Decisión: Si dice dev eth0 o muestra una puerta local, no estás usando el túnel. Arregla el enrutamiento antes de tocar NAT.
Tarea 3: Verifica el handshake y el tráfico reciente de la VPN (ejemplo WireGuard)
cr0x@server:~$ sudo wg show
interface: wg0
public key: fM0...redacted
listening port: 51820
peer: 8kQ...redacted
endpoint: 198.51.100.10:51820
allowed ips: 172.31.20.0/24
latest handshake: 1 minute, 12 seconds ago
transfer: 128.34 MiB received, 141.02 MiB sent
Qué significa: El handshake es reciente; AllowedIPs incluye el subnet alias. Los contadores de tráfico se mueven.
Decisión: Si latest handshake es “never”, para. Tienes un problema de VPN, no de NAT.
Tarea 4: Confirma que el reenvío de IP está activado (el requisito más aburrido)
cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
Qué significa: Linux enrutará paquetes.
Decisión: Si es 0, actívalo y persístelo vía /etc/sysctl.d/*.conf. Sin reenvío, las reglas NAT pueden ser perfectas y aun así no hacer nada.
Tarea 5: Valida la política de firewall que permite el reenvío (nftables)
cr0x@server:~$ sudo nft list ruleset | sed -n '1,120p'
table inet filter {
chain forward {
type filter hook forward priority filter; policy drop;
iifname "wg0" oifname "eth0" ip daddr 10.20.8.25 tcp dport 5432 accept
iifname "eth0" oifname "wg0" ct state established,related accept
}
}
Qué significa: Drop por defecto, permiso explícito para Postgres, y tráfico de retorno establecido es aceptado.
Decisión: Si no ves una regla established/related para la dirección de retorno, tendrás tráfico unidireccional y culparás a NAT. No lo hagas.
Tarea 6: Inspecciona reglas NAT (nftables)
cr0x@server:~$ sudo nft list table ip nat
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iifname "wg0" ip daddr 172.31.20.25 dnat to 10.20.8.25
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "eth0" ip daddr 10.20.8.25 snat to 10.20.5.254
}
}
Qué significa: DNAT traduce alias a real. SNAT fuerza las respuestas a volver al gateway.
Decisión: Si falta SNAT, añádelo o usa un SNAT/masquerade más general para el flujo alias→real. Si no, el tráfico de retorno puede evitar el gateway.
Tarea 7: Observa entradas conntrack mientras pruebas (¿las sesiones se están traduciendo?)
cr0x@server:~$ sudo conntrack -L | grep 5432 | head
tcp 6 431999 ESTABLISHED src=10.20.5.10 dst=172.31.20.25 sport=54012 dport=5432 src=10.20.8.25 dst=10.20.5.254 sport=5432 dport=54012 [ASSURED] mark=0 use=1
Qué significa: Puedes ver tanto la tupla original como la tupla traducida. La ruta de respuesta está anclada a la IP del gateway (10.20.5.254) debido a SNAT.
Decisión: Si conntrack no muestra nada mientras pruebas, tus paquetes no llegan al gateway. Revisa enrutamiento y AllowedIPs/selectores.
Tarea 8: Captura de paquetes en ambas interfaces (prueba dónde muere)
cr0x@server:~$ sudo tcpdump -ni wg0 host 172.31.20.25 and tcp port 5432 -c 5
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wg0, link-type RAW (Raw IP), snapshot length 262144 bytes
IP 10.20.5.10.54012 > 172.31.20.25.5432: Flags [S], seq 221733, win 64240, options [mss 1380,sackOK,TS val 123 ecr 0,nop,wscale 7], length 0
IP 10.20.5.10.54012 > 172.31.20.25.5432: Flags [S], seq 221733, win 64240, options [mss 1380,sackOK,TS val 1123 ecr 0,nop,wscale 7], length 0
Qué significa: SYNs están entrando en la interfaz del túnel. Si nunca ves SYN-ACKs, el problema está después del ingreso al túnel (DNAT, firewall, servidor, enrutamiento de retorno).
Decisión: Entonces captura en eth0 para confirmar que ocurrió DNAT.
cr0x@server:~$ sudo tcpdump -ni eth0 host 10.20.8.25 and tcp port 5432 -c 5
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 10.20.5.254.54012 > 10.20.8.25.5432: Flags [S], seq 221733, win 64240, options [mss 1460,sackOK,TS val 555 ecr 0,nop,wscale 7], length 0
Qué significa: SNAT y DNAT están funcionando. El servidor ve la IP origen del gateway.
Decisión: Si el servidor espera la IP real del cliente para ACLs, necesitas autenticación a nivel de app, PROXY protocol (donde esté soportado), o una estrategia de logs diferente. NAT ocultará clientes a menos que diseñes alrededor de eso.
Tarea 9: Comprueba el filtrado de ruta inversa (el que suelta silenciosamente)
cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.eth0.rp_filter
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
Qué significa: El filtrado de ruta inversa estricto está activado. Con asimetría y NAT, rp_filter puede soltar paquetes válidos.
Decisión: Si ves drops intermitentes, pon rp_filter a 2 (loose) en interfaces relevantes, o rediseña para mantener enrutamiento simétrico. No desactives globalmente a menos que entiendas el riesgo.
Tarea 10: Valida MTU y comportamiento PMTUD (VPN + NAT ama la fragmentación)
cr0x@server:~$ ping -M do -s 1420 172.31.20.25 -c 3
PING 172.31.20.25 (172.31.20.25) 1420(1448) bytes of data.
ping: local error: message too long, mtu=1420
ping: local error: message too long, mtu=1420
ping: local error: message too long, mtu=1420
--- 172.31.20.25 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2041ms
Qué significa: Tu MTU de ruta es menor del que asumiste. La encapsulación VPN añade sobrecarga; los dispositivos NAT y firewalls a veces manejan mal los ICMP de “fragmentation-needed”.
Decisión: Reduce MTU del túnel (por ejemplo WireGuard), clampa MSS en el borde, o arregla el manejo de ICMP. Si las sesiones TCP se quedan colgadas bajo carga pero pings pequeños funcionan, MTU es un sospechoso principal.
Tarea 11: Traza ruta con SYN TCP hacia el servicio real (prueba L3 vs L4)
cr0x@server:~$ sudo traceroute -T -p 5432 172.31.20.25 -n
traceroute to 172.31.20.25 (172.31.20.25), 30 hops max, 60 byte packets
1 10.99.0.2 12.112 ms 11.901 ms 11.774 ms
2 172.31.20.25 24.310 ms 24.221 ms 24.105 ms
Qué significa: Alcanzas el endpoint alias en dos saltos (peer del túnel, luego destino). No prueba que el puerto esté abierto, pero demuestra que el enrutamiento es razonable.
Decisión: Si traceroute muere en el salto 1, tus AllowedIPs/selectores o enrutamiento hacia el túnel están mal. No toques aún config de servidores.
Tarea 12: Verifica que el servicio realmente escucha (en el lado destino)
cr0x@server:~$ sudo ss -lntp | grep 5432
LISTEN 0 4096 0.0.0.0:5432 0.0.0.0:* users:(("postgres",pid=1442,fd=6))
Qué significa: Postgres está escuchando en todas las interfaces.
Decisión: Si está ligado a 127.0.0.1 o a una IP específica que no coincide con el objetivo DNAT, arregla eso primero. NAT no puede conectar a lo que no está escuchando.
Tarea 13: Confirma la ruta de retorno del servidor hacia el gateway (evita bypass)
cr0x@server:~$ ip route get 10.20.5.254
10.20.5.254 via 10.20.8.1 dev eth0 src 10.20.8.25 uid 0
cache
Qué significa: El servidor retornará a su router local, que entonces debería alcanzar el gateway NAT (dependiendo de la topología). Si el gateway NAT está adyacente L2, puedes ver dev eth0 directamente.
Decisión: Si el servidor tiene una ruta más directa al subnet cliente, puedes obtener retorno asimétrico. Considera policy routing o asegúrate de que SNAT use una dirección que fuerce el retorno al gateway.
Tarea 14: Comprueba contadores de reglas NAT para confirmar impactos (contadores nftables)
cr0x@server:~$ sudo nft -a list chain ip nat prerouting
table ip nat {
chain prerouting { # handle 2
type nat hook prerouting priority dstnat; policy accept;
iifname "wg0" ip daddr 172.31.20.25 counter packets 128 bytes 7680 dnat to 10.20.8.25 # handle 12
}
}
Qué significa: La regla DNAT está coincidiendo. Los contadores aumentan cuando pruebas.
Decisión: Si los contadores quedan en cero, o el tráfico no llega, o la coincidencia es incorrecta (nombre de interfaz, IP destino, familia de direcciones). Arregla condiciones de match antes de inventar reglas nuevas.
Tarea 15: Valida selectores IPsec (las VPN basadas en políticas pueden “comerse” diseños NAT)
cr0x@server:~$ sudo ip xfrm policy
src 172.31.20.0/24 dst 10.20.8.0/24
dir out priority 1000 ptype main
tmpl src 203.0.113.2 dst 198.51.100.2 proto esp reqid 1 mode tunnel
src 10.20.8.0/24 dst 172.31.20.0/24
dir in priority 1000 ptype main
tmpl src 198.51.100.2 dst 203.0.113.2 proto esp reqid 1 mode tunnel
Qué significa: Las políticas del kernel definen qué se cifra. Si tu subnet alias no está en los selectores, los paquetes no entrarán en el túnel aunque existan rutas.
Decisión: Actualiza selectores (en ambos extremos) para que coincidan con las direcciones post-NAT vistas por el túnel. Para IPsec basado en políticas, NAT y selectores deben coincidir o perseguirás fantasmas.
Tarea 16: Prueba desde el host de la aplicación con origen explícito (demuestra quién está siendo NATeado)
cr0x@server:~$ psql "host=172.31.20.25 port=5432 user=app dbname=appdb connect_timeout=3" -c "select 1;"
?column?
----------
1
(1 row)
Qué significa: El camino de extremo a extremo funciona para el protocolo de aplicación real. El éxito ICMP no cuenta; el éxito de la app sí.
Decisión: Si psql falla pero SYN/SYN-ACK TCP funciona, revisa autenticación (pg_hba.conf), TLS SNI/certs, o expectativas L7 que incluyan IPs.
Guion de diagnóstico rápido
Cuando alguien dice “la VPN está arriba pero el servicio cae”, no vagues. Ejecuta esto en orden. Para tan pronto como encuentres una discrepancia.
Primero: ¿El túnel es real y el tráfico es elegible para usarlo?
- WireGuard:
sudo wg show→ ¿handshake reciente? ¿contadores de transferencia se mueven? - IPsec: comprueba SAs y políticas → ¿los selectores incluyen el subnet alias?
- Enrutamiento:
ip route get <alias-ip>→ ¿elige la interfaz del túnel?
Si cualquiera de estos falla, las reglas NAT son irrelevantes.
Segundo: ¿Se traducen y reenvían paquetes?
sysctl net.ipv4.ip_forward→ debe ser 1- Contadores NAT (nftables/iptables) → ¿coinciden DNAT/SNAT?
conntrack -L→ ¿existe una entrada para el flujo?
Si DNAT impacta pero SNAT no, espera pérdida de SYN-ACK y timeouts.
Tercero: ¿El tráfico de retorno se fuerza de vuelta por el gateway?
- Captura en la interfaz interna: ¿ves respuestas del servidor al origen SNAT?
- Revisa rp_filter; el modo loose suele ser necesario en bordes NAT.
- Confirma la ruta del servidor hacia la IP SNAT es razonable.
Cuarto: ¿La aplicación realmente quiere hablar?
- Puerto abierto, servicio escuchando, nombres TLS correctos, ACLs actualizadas para orígenes SNATeados.
- Prueba con la herramienta cliente real (psql, curl, ldapsearch). Ping es un subidón moral, no una validación.
Errores comunes: síntomas → causa raíz → solución
1) Síntoma: “SYN sale, nada vuelve”
Causa raíz: Falta SNAT, de modo que el servidor responde a la IP origen original vía su ruta normal, evitando el gateway VPN (retorno asimétrico).
Solución: Añade SNAT/masquerade en el gateway VPN para los flujos traducidos, o usa policy routing para forzar el retorno vía el gateway.
2) Síntoma: Algunos puertos funcionan, otros cuelgan misteriosamente
Causa raíz: Reglas de firewall forward permiten un puerto de prueba pero no los flujos reales de la aplicación, o el estado conntrack no está permitido de vuelta.
Solución: Trata el reenvío como su propia política. Permite established/related en ambas direcciones. Confirma que los contadores incrementan en la regla específica.
3) Síntoma: Funciona para peticiones pequeñas, muere en transferencias grandes
Causa raíz: Problemas de MTU/PMTUD sobre encapsulación; ICMP “fragmentation needed” bloqueado; MSS no clamped.
Solución: Baja MTU del túnel y/o clampa MSS en paquetes SYN. Asegura que ICMP esté permitido para PMTUD o acepta que ajustarás MTU para siempre.
4) Síntoma: Caídas aleatorias bajo carga, especialmente en gateways multi-homed
Causa raíz: El filtrado de ruta inversa suelta paquetes que no coinciden con expectativas de enrutamiento tras NAT.
Solución: Pon rp_filter en modo loose (2) en interfaces relevantes; mantén enrutamiento simétrico donde sea posible.
5) Síntoma: “La VPN está conectada, pero nadie alcanza la subnet alias”
Causa raíz: Selectores de IPsec basados en políticas no incluyen el rango alias, así que el tráfico nunca entra en el túnel.
Solución: Actualiza selectores para que coincidan con direcciones post-NAT. Para IPsec basado en rutas, verifica el enrutamiento VTI en su lugar.
6) Síntoma: Logs de la aplicación muestran IP cliente incorrecta, y límites bloquean al gateway
Causa raíz: SNAT colapsa muchos clientes en una sola IP origen; sistemas L7 lo interpretan como un único cliente ruidoso.
Solución: Prefiere pools SNAT por cliente, PROXY protocol donde esté soportado, o mueve a un proxy de aplicación que preserve identidad cliente.
7) Síntoma: DNS funciona, pero conectar por nombres golpea máquinas locales en su lugar
Causa raíz: DNS en split-brain devuelve registros A superpuestos; los clientes resuelven a 10.x y enrutan localmente.
Solución: Publica IPs alias en la vista DNS usada por el lado remoto, o usa reenvío condicional a una zona DNS que devuelva direcciones alias.
8) Síntoma: Reglas NAT nuevas “funcionan” en pruebas y luego rompen una semana después
Causa raíz: Agotamiento de la tabla conntrack, o reglas NAT dependen de nombres/direcciones de interfaz dinámicas que cambiaron.
Solución: Monitorea uso de conntrack, ajústalo apropiadamente, fija nombres de interfaz, y evita coincidencias frágiles. Haz las reglas explícitas y revísalas como código.
Tres mini-historias corporativas (las que enseñan)
Mini-historia #1: El incidente causado por una suposición equivocada
La Compañía A adquirió una firma más pequeña y necesitaba “conectividad rápida” para que los sistemas financieros pudieran sacar datos para fin de mes. Ambos lados usaban 10.0.0.0/8, naturalmente. El equipo de red creó un rango alias y hizo DNAT en el gateway VPN remoto. Pruebas básicas pasaron: ping, traceroute, incluso una conexión TCP rápida al puerto de la base de datos.
A las 9:05 a.m. del día de cierre, los trabajos ETL arrancaron y rápidamente hicieron timeout. Capturas mostraron SYN y SYN-ACK, luego largos silencios. El equipo escaló al proveedor de VPN, porque eso es lo que la gente hace cuando está cansada y ligeramente ofendida por la realidad.
La suposición equivocada: “Si DNAT funciona, el tráfico de retorno encontrará el camino de regreso”. No lo hará. La base de datos respondió a la IP cliente original (todavía superpuesta), y la respuesta llegó a un host local con la misma dirección en el lado de la base de datos. A veces ese host existía y mandaba RSTs. A veces no, y las respuestas desaparecían. La red estaba, en cierto sentido, haciendo exactamente lo que se le dijo.
La solución fue contundente y eficaz: SNAT en el gateway VPN para los flujos traducidos, forzando todo el tráfico de retorno a través de la misma caja. Una vez simétricas las sesiones, los ETL corrieron. Nadie agradeció a NAT, pero todos dejaron de gritar al concentrador VPN.
Después hicieron lo que debieron haber hecho antes: documentaron un recorrido de paquete con ambas traducciones y convirtieron la “verificación de simetría” en parte de la revisión de cambios. El incidente no fue causado por la complejidad. Fue causado por saltarse las partes aburridas de la complejidad.
Mini-historia #2: La optimización que salió mal
La Compañía B tenía un puente NAT a través de IPsec de larga vida entre dos centros de datos con redes de laboratorio superpuestas. No era bonito, pero era estable. Entonces alguien notó CPU alta en los gateways VPN en horas pico y decidió optimizar: “Reduciremos la presión de conntrack usando reglas NAT más amplias y menos entradas de estado”.
Sustituyeron un conjunto de reglas SNAT estrechas por un gran masquerade, efectivamente NATeando más tráfico del previsto. La CPU bajó. Victoria. Dos días después, la monitorización de seguridad se encendió: IDS reportó un pico de patrones de “movimiento lateral” a través del túnel. Era falso—pero costoso.
El problema fue la observabilidad. Con masquerade más amplio, múltiples sistemas internos colapsaron en la misma identidad traducida. Los logs se volvieron ambiguos. Alertas que antes ligaban eventos a fuentes específicas ahora señalaban “el gateway NAT”, que es el equivalente en redes de “alguien”.
Peor aún, un sistema de rate-limiting en el lado remoto vio una única fuente golpeando APIs y empezó a limitar—limitando a todos. La optimización mejoró una métrica (CPU) incendiando otra (claridad diagnóstica) y luego activó shaping de tráfico por accidente.
El rollback restauró traducciones estrechas. La solución real fue más madura: escalar los gateways correctamente, aumentar límites de conntrack con monitorización, y mantener el alcance de NAT lo más pequeño posible. Los problemas de rendimiento a menudo se resuelven con capacidad y arquitectura, no volviendo inútiles tus logs.
Mini-historia #3: La práctica aburrida pero correcta que salvó el día
La Compañía C operaba un entorno regulado con control de cambios dolorosamente estricto. Los ingenieros se quejaban hasta que un día eso los salvó. Necesitaban conectar on-prem a una VPC en la nube que tenía—sorpresa—rangos solapados con un segmento de servicios compartidos interno.
El equipo propuso NAT a través de VPN con un rango alias. Antes de implementar, hicieron tres cosas aburridas: reservaron el rango alias en IPAM (aunque fuera “virtual”), escribieron una página con el recorrido de paquete, y crearon monitorización sintética desde ambos lados usando las direcciones alias. También añadieron checks de conntrack y contadores NAT al runbook.
Durante el corte, faltaba una regla de firewall para conexiones establecidas de retorno. La comprobación sintética falló de inmediato y los contadores NAT mostraron DNAT impactando pero sin tráfico de retorno. Ningún cliente se enteró porque el equipo lo detectó en minutos, no horas.
Lo mejor del postmortem: no incluyó heroicidades. Incluyó una checklist, un contador y un gráfico. Ese es el tipo de aburrimiento al que debes aspirar.
Broma #2: Si alguna vez te sientes inútil, recuerda que hay una regla NAT “temporal” de 2017 todavía enroutando tráfico de nómina.
Listas de verificación / plan paso a paso
Plan paso a paso para NAT a través de VPN que no te sabotee después
- Define el alcance del negocio. Enumera los servicios y puertos exactos requeridos. Si la lista es “todo”, estás a punto de construir una segunda red. Para y renegocia.
- Elige CIDRs alias deliberadamente. Usa rangos que no choquen con ninguno de los lados ahora ni en expansiones plausibles futuras. Resérvalos en IPAM como si fuera serio.
- Decide NAT unidireccional vs bidireccional. Unidireccional es menos costoso operativamente. Bidireccional es más uniforme para apps bidireccionales pero más difícil de razonar.
- Elige el punto de traducción. Haz NAT en el gateway VPN si necesitas retorno simétrico y control centralizado. Evita “NAT esparcido por hosts random”.
- Escribe un recorrido de paquete. Un diagrama, un flujo de ejemplo, ambas traducciones mostradas. Si no puedes explicarlo, no puedes operarlo.
- Implementa enrutamiento/selectores primero. Asegura que los CIDRs alias enruten hacia el túnel y estén permitidos por WireGuard AllowedIPs o selectores IPsec.
- Implementa reglas firewall de forward segundo. Empieza con allow explícito para puertos requeridos y established/related de retorno. Drop por defecto está bien si eres disciplinado.
- Implementa DNAT + SNAT juntos. Trátalos como un par para servicios stateful. DNAT sin SNAT es una trampa a menos que sepas que el enrutamiento de retorno está fijado.
- Instrumenta los bordes. Recoge: contadores NAT, uso de conntrack, bytes del túnel y drops en interfaces. Alerta por cambios, no solo por fallos.
- Prueba en L7. Usa herramientas cliente reales. Para HTTP, verifica headers y nombres TLS. Para BD, ejecuta una consulta real.
- Planifica rollback. Ser valiente no es estrategia de rollback. Mantén rutas y políticas antiguas listas para reaplicar.
- Pon fecha de deprecación. NAT a través de VPN tiende a volverse permanente a menos que programes renumerado o una interconexión más limpia.
Checklist pre-cambio (imprimible en tu cabeza)
- CIDR alias reservado y documentado
- Routing/AllowedIPs/selectores incluyen el CIDR alias
- Reglas DNAT y SNAT revisadas para simetría
- Forward firewall permite puertos requeridos + established/related
- rp_filter evaluado (loose donde sea necesario)
- Plan MTU (MTU túnel explícito o MSS clamp)
- Monitorización y pruebas sintéticas listas
- Plan de rollback probado (al menos una vez en laboratorio)
Preguntas frecuentes
1) ¿Siempre necesito SNAT cuando hago DNAT a través de una VPN?
No siempre, pero asume que sí hasta que se demuestre lo contrario. Si el host destino puede retornar tráfico vía el mismo gateway de forma determinista (sin rutas que lo eviten), podrías omitir SNAT. En redes superpuestas, la determinación de retorno es rara. Usa SNAT para forzar simetría.
2) ¿Puedo resolver redes superpuestas anunciando rutas más específicas?
Si la superposición es idéntica (ambos tienen 10.20.0.0/16), más específicas no arreglan la ambigüedad de identidad en los hosts. Podrías ganar en routers y perder en ARP y enrutamiento local. NAT o VRFs son los arreglos usuales; renumerar es la solución real.
3) ¿El rango alias debe ser RFC1918 o puede parecer espacio público?
Usa RFC1918 salvo que tengas un entorno muy controlado y una razón fuerte. Espacio con apariencia pública puede filtrarse en logs, monitorización o terceros y confundir la respuesta a incidentes. El objetivo es unicidad y claridad interna, no hacerse pasar por la Internet pública.
4) ¿Cuál es la diferencia entre NAT a través de VPN y NAT traversal (NAT-T)?
NAT-T trata de hacer pasar IPsec por un dispositivo NAT en el camino encapsulando ESP en UDP. NAT a través de VPN es que tú deliberadamente traduces direcciones para resolver superposición o restricciones de política. Acrónimos parecidos, problema totalmente distinto.
5) ¿WireGuard puede hacer NAT por mí?
WireGuard es enrutamiento/crypto; no implementa NAT por sí mismo. Haces NAT con nftables/iptables en el gateway. El campo AllowedIPs de WireGuard actúa como mecanismo de enrutamiento/filtrado, y es fácil equivocarse al añadir rangos alias.
6) ¿Cómo mantengo visibilidad de la IP real del cliente para logs y ACLs?
Usualmente no puedes con SNAT puro; ese es el propósito de SNAT. Opciones: pools SNAT por cliente, proxies de aplicación que preserven identidad del cliente, o características específicas de protocolo (como PROXY protocol) donde estén soportadas.
7) ¿Es mala idea el NAT bidireccional?
No es malvada; es solo fácil de malentender. Si debes soportar inicios de ambos lados y no puedes renumerar, NAT bidireccional puede ser correcto. Requiere mejor documentación, monitorización más ajustada y descubrimiento de servicios/DNS más cuidadoso.
8) ¿Y IPv6—hace que este problema desaparezca?
IPv6 reduce la escasez de direcciones y debería reducir la presión por superposición, pero la realidad incluye sistemas legados y despliegues parciales. Además, la gente todavía puede superponer prefijos ULA si tratan el direccionamiento como una sugerencia. El problema de disciplina no desaparece.
9) ¿Por qué el DNS se vuelve un lío especial con alias NAT?
Porque los nombres son conceptos compartidos y las IP no lo son. Si “db.internal” resuelve a 10.20.8.25 en un lado y eso también es un host válido local en el otro, los clientes conectarán confiados al sitio equivocado. Usa DNS Split-horizon o nombres alias dedicados que resuelvan a IPs alias para uso entre sitios.
10) ¿Cuánto tiempo podemos mantener NAT a través de VPN?
Técnicamente: años. Operativamente: hasta que olvides cómo funciona y necesites cambiarlo bajo presión. Ponle un dueño, mantenlo monitorizado y planifica una salida (renumerado, VRFs o integración de red limpia).
Conclusión: siguientes pasos que no arruinarán tu semana
NAT a través de VPN es una herramienta pragmática para un mundo desordenado: fusiones, shadow IT, CIDRs por defecto en la nube y “lo limpiaremos después”. Funciona cuando respetas dos cosas: simetría y alcance. Haz determinista el tráfico de retorno. Traduce solo lo necesario. Instrumenta todo lo que toques.
Pasos siguientes que puedes hacer de inmediato:
- Elige y reserva CIDRs alias en IPAM (aunque sean “virtuales”).
- Escribe un recorrido de paquete de una página para un flujo crítico, incluyendo DNAT y SNAT.
- Implementa contadores NAT + monitorización conntrack en los gateways VPN.
- Crea una comprobación sintética que use las direcciones alias desde ambos lados y falle alto.
- Agenda la reunión incómoda sobre renumeración, porque NAT no es un plan de retiro.