El problema: necesitas publicar “solo un servicio interno” para unos pocos usuarios remotos. El equipo de red dice “ponlo detrás de la VPN.” Alguien más dice “simplemente reenvía el puerto.” Al poco, tu VPN se convierte en la puerta trasera más cara del mundo—lo suficientemente amplia para movimiento lateral, fuerza bruta y exposición accidental de datos.
Esta es una guía de campo para quienes operan sistemas reales: cómo combinar acceso VPN y reenvío de puertos sin convertir tu red privada en un perímetro blando y resbaladizo. Seremos concretos sobre enrutamiento, NAT, cortafuegos, identidad, registro y modos de fallo. Y lo haremos con comandos que puedes ejecutar hoy.
El modelo mental: la VPN es una red, no una capa mágica
Una VPN no es “seguridad”. Una VPN es un conjunto de rutas de red y decisiones de confianza. Cuando das acceso VPN a un dispositivo, le estás concediendo la capacidad de enviar paquetes hacia tu entorno. Todo lo demás son detalles: enrutamiento, cifrado, autenticación, filtrado, observabilidad y la verdad irreversible de que un cliente comprometido ahora está “dentro” de todo lo que expones.
El reenvío de puertos suena como un compromiso ordenado: “Reenviamos el puerto 443 desde la puerta de enlace VPN a un servicio interno. Solo los usuarios VPN pueden alcanzarlo. Listo.” El problema es que el reenvío rara vez es el único cambio realizado. Los entornos acumulan: una ruta de conveniencia aquí, un agujero de cortafuegos “temporal” allá, un AllowedIPs demasiado amplio en WireGuard porque alguien se cansó de depurar. En seis meses, nadie recuerda por qué la puerta de enlace VPN puede alcanzar la mitad de las subredes privadas.
Aquí está la línea base con opinión:
- Prefiere la exposición a nivel de aplicación sobre la exposición a nivel de red. Un proxy inverso con autenticación vence la simple accesibilidad L3.
- Prefiere listas de permitidos explícitas sobre confianza implícita. “En la VPN” no es una lista de permitidos.
- Prefiere un radio de blast reducido sobre trucos sofisticados de reenvío. Si no puedes explicar el enrutamiento en dos minutos, no podrás operarlo a las 3 a.m.
VPN + reenvío de puertos puede ser seguro. Pero solo si lo tratas como si estuvieras construyendo una mini red de borde dentro de tu empresa: mínimo privilegio, flujos bien definidos y límites rígidos.
Hechos y contexto histórico que moldean los errores actuales con VPN
Esto no es trivia. Explica por qué las “soluciones rápidas con VPN” siguen introduciendo riesgo en producción.
- Las VPN popularizaron la seguridad “cáscara dura, centro blando”. Las primeras VPN corporativas asumían una LAN interna confiable; una vez conectado, básicamente estabas “dentro”. Ese modelo envejeció mal.
- El NAT se volvió la manta de seguridad por defecto en los 2000. NAT nunca fue diseñado como cortafuegos, pero enseñó a los operadores a equiparar “no enrutable públicamente” con “seguro”.
- IPsec se diseñó primero para sitio a sitio. Muchas implementaciones de IPsec asumen redes estables y subredes claras; forzar acceso de cliente ad-hoc conduce a una política enmarañada.
- OpenVPN normalizó “push routes” a clientes. Es cómodo—y peligrosamente fácil empujar acceso amplio (o configuraciones de DNS) sin darse cuenta del alcance.
- WireGuard evita deliberadamente funciones de “política”. Es rápido y simple, pero eso significa que debes implementar control de acceso en cortafuegos y enrutamiento, no en el protocolo VPN.
- Hairpin NAT existe porque los usuarios reales hacen cosas raras. La gente marca nombres públicos y los reutiliza internamente; si no planificas el tráfico hairpin, depurarás fantasmas.
- El reenvío de puertos es anterior a la nube. Es un truco clásico de administradores de la era de routers de oficina pequeña. Funciona—hasta que necesitas auditabilidad y segmentación.
- Zero Trust no mató las VPN; las replanteó. Las mejores VPN modernas son transporte controlado más políticas conscientes de identidad, no un túnel hacia el reino.
La historia deja hábitos. Tu trabajo es romper los que convierten “acceso remoto” en “compromiso remoto”.
Patrones más seguros para exponer servicios vía VPN
Patrón A: Proxy inverso en el borde VPN (recomendado)
Coloca un proxy inverso (nginx, HAProxy, Envoy, Caddy—elige el que prefieras) en la puerta de enlace VPN o en un host dedicado de “borde VPN”. Termina TLS allí. Exige autenticación fuerte (mTLS, OIDC, SSO). Reenvía a servicios internos en redes privadas. La VPN proporciona el transporte; el proxy proporciona identidad y política.
Por qué es bueno:
- La exposición del servicio es a nivel de aplicación; puedes aplicar reglas por ruta/host.
- Puedes registrar solicitudes, limitar tasa y bloquear tonterías evidentes.
- Puedes fijar el acceso a un único destino interno en lugar de abrir enrutamiento a una subred.
Patrón B: Reenvía el puerto solo a una IP:puerto interna, con anclaje de cortafuegos
Si debes reenviar TCP/UDP crudo, hazlo de forma estrecha. Ancla el puerto reenviado a un único destino interno, y luego ancla el cortafuegos para que solo las IPs cliente VPN (o una lista de permitidos reducida) puedan alcanzar ese puerto en la puerta de enlace.
Aquí es donde los operadores se vuelven descuidados: implementan DNAT pero olvidan las reglas de filtrado. DNAT sin filtro es un sistema de “política por accidente”.
Patrón C: Usa un bastión / jump host para protocolos administrativos
El acceso administrativo (SSH, RDP, consolas de bases de datos) debe pasar por un jump host, no por puertos reenviados al azar. Un buen bastión te da:
- Autenticación por usuario y registros de sesión.
- Un punto de estrangulamiento único para endurecimiento y monitorización.
- Un lugar para aplicar MFA sin reinventar la rueda.
Patrón D: Split tunnel con rutas explícitas, no “todo por la VPN”
Las VPN de túnel completo están bien si las gestionas bien, pero aumentan el radio de blast cuando no lo haces. El split tunnel con enrutamiento explícito solo a lo que los usuarios necesitan reduce riesgo y carga de soporte (menos tickets de “la VPN mató mi Zoom”).
Patrón E: No expongas el servicio—replica
Para algunas cargas de trabajo, lo más seguro es no exponer nada. Replica datos de solo lectura a un servicio en DMZ, o publica mediante una API dedicada que aplique autorización. Esta es la arquitectura “aburrida” que evita reenvíos ingeniosos.
Chequeo de realidad: si tu plan depende de “nadie escaneará ese puerto porque está en la VPN”, has construido un sistema de seguridad basado en esperanza y bridas.
Modelo de amenazas: cómo fallan la VPN + reenvío
1) Movimiento lateral desde un cliente comprometido
El endpoint cliente de la VPN suele ser el entorno menos controlado que posees: portátiles personales, móviles, máquinas de contratistas. Si uno está comprometido y tiene un alcance VPN amplio, un atacante obtiene escaneo interno, robo de credenciales y pivoting. El reenvío de puertos puede amplificar esto al facilitar el acceso a servicios internos a través de una única puerta conocida.
2) Reglas “temporales” que se vuelven permanentes
Las reglas de reenvío y las excepciones de cortafuegos tienen una vida media más larga que tu paciencia. Si no tienes automatización y revisiones, las excepciones viven para siempre. Y se acumulan.
3) Desajuste de autenticación: acceso de red vs acceso de aplicación
Una VPN autentica un dispositivo o usuario para la red. Tu app autentica usuarios (o no). Si expones un servicio que asume “LAN = confiable”, acabas de teletransportar esa suposición a cada cliente VPN.
4) Confusión de DNS y sorpresas por virtual hosting basado en nombre
Los usuarios alcanzan el servicio por un nombre público; tu reenvío o proxy inverso depende de SNI/Host headers; alguien prueba por IP; de pronto funciona para algunos clientes y no para otros. El diseño DNS importa aquí más de lo que quieres admitir.
5) MTU y bugs de fragmentación que solo aparecen en producción
La encapsulación VPN reduce el MTU efectivo. Algunos caminos bloquean ICMP “Fragmentation Needed”, y entonces los handshakes TLS se cuelgan sin explicación. El tráfico reenviado hereda estos problemas.
6) Rutas mal dimensionadas (AllowedIPs, push routes o rutas estáticas)
Este es el clásico. Intentabas permitir acceso a 10.20.30.40:443. Alguien empuja 10.20.0.0/16 “por conveniencia.” Tu VPN se acaba de convertir en una red corporativa en la sombra.
Chiste #1: NAT es como el plástico burbuja: te hace sentir seguro, pero si te lanzas desde el tejado igual vas a tener un mal día.
Principio operativo: trata la puerta de enlace VPN como un borde de internet
Incluso si solo “usuarios de confianza” conectan, opera la puerta de enlace VPN como si estuviera expuesta a tráfico adversarial:
- Sistema operativo endurecido, paquetes mínimos.
- Cortafuegos estricto con denegar por defecto.
- Logs estructurados enviados fuera del host.
- Límites de tasa cuando sea posible.
- Configuración gestionada como código; cambios revisados.
Tareas prácticas con comandos: verificar, restringir, reenviar, observar
Estas tareas están escritas para puertas de enlace VPN basadas en Linux. Los comandos asumen que tienes root o sudo. Para cada una: qué ejecutas, qué significa la salida y qué decisión tomas.
Tarea 1: Confirma el estado de reenvío de IP (porque “forwarding” no es una sensación)
cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
Significado: el kernel no reenviará paquetes IPv4 entre interfaces. Las reglas DNAT pueden seguir reescribiendo, pero el enrutamiento no hará pasar tráfico como se espera.
Decisión: Si esta es una puerta de enlace VPN que debe enrutar/reencaminar, ponla a 1 y persístelo. Si no debe enrutar, mantenla en 0 y revisa tu diseño.
Tarea 2: Comprueba el MTU efectivo en la interfaz VPN (asesino silencioso del TLS)
cr0x@server:~$ ip link show dev wg0
5: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/none
Significado: WireGuard suele usar por defecto MTU 1420; tu red subyacente puede necesitar menos. Si ves MTU 1500 y estás tunelando sobre PPPoE/LTE, espera problema.
Decisión: Si tienes cuelgues intermitentes, prueba con MTU menor (por ejemplo 1380) y verifica con PMTU (Tarea 11).
Tarea 3: Verifica qué rutas usará la puerta de enlace para alcanzar el servicio interno
cr0x@server:~$ ip route get 10.20.30.40
10.20.30.40 via 10.20.0.1 dev eth1 src 10.20.0.10 uid 0
cache
Significado: la puerta de enlace enviará tráfico a 10.20.30.40 vía 10.20.0.1 por eth1 usando fuente 10.20.0.10.
Decisión: Si la ruta apunta a la interfaz equivocada, arregla el enrutamiento antes de tocar NAT. Las reglas DNAT no pueden salvar un enrutamiento malo.
Tarea 4: Confirma que el servicio esté realmente escuchando en el host interno
cr0x@server:~$ ss -lntp | head
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=911,fd=3))
LISTEN 0 512 10.20.30.40:443 0.0.0.0:* users:(("nginx",pid=1220,fd=6))
Significado: nginx está escuchando en 10.20.30.40:443. Genial. Si solo escuchara en 127.0.0.1, reenviarlo fallaría a menos que también reenvíes en ese host.
Decisión: Si no escucha donde esperas, arregla la dirección de bind del servicio antes de depurar la red.
Tarea 5: Valida la política por defecto del cortafuegos (si está ACCEPT en todas partes, estás apostando)
cr0x@server:~$ sudo iptables -S | head -n 12
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N VPN_IN
-N VPN_FWD
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i wg0 -j VPN_IN
-A FORWARD -i wg0 -j VPN_FWD
Significado: denegar por defecto INPUT y FORWARD, con cadenas dedicadas para VPN. Esta es la postura que quieres en una puerta de enlace.
Decisión: Si INPUT/FORWARD están en ACCEPT por defecto, planifica una migración controlada a denegar por defecto. Empieza añadiendo permisos explícitos, luego cambia políticas durante una ventana de mantenimiento.
Tarea 6: Crea un DNAT de puerto estrecho (VPN IP:8443 → interno 10.20.30.40:443)
cr0x@server:~$ sudo iptables -t nat -A PREROUTING -i wg0 -p tcp --dport 8443 -j DNAT --to-destination 10.20.30.40:443
cr0x@server:~$ sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp -d 10.20.30.40 --dport 443 -j MASQUERADE
cr0x@server:~$ sudo iptables -A FORWARD -i wg0 -o eth1 -p tcp -d 10.20.30.40 --dport 443 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
cr0x@server:~$ sudo iptables -A FORWARD -i eth1 -o wg0 -p tcp -s 10.20.30.40 --sport 443 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Significado: PREROUTING cambia el destino del tráfico que llega por la VPN. POSTROUTING hace masquerade para que el host interno responda vía la puerta de enlace aunque no conozca las subredes cliente VPN.
Decisión: Prefiere enrutamiento sin masquerade cuando sea posible (más limpio, preserva IP cliente), pero si no puedes añadir rutas en el host/red interna, MASQUERADE es pragmático. Documentalo: afecta registros y trazas de auditoría.
Tarea 7: Restringe quién puede usar el reenvío (lista de permitidos de subred cliente VPN o IPs específicas)
cr0x@server:~$ sudo iptables -I FORWARD 1 -i wg0 -p tcp -s 10.66.0.0/24 -d 10.20.30.40 --dport 443 -j ACCEPT
cr0x@server:~$ sudo iptables -I FORWARD 2 -i wg0 -p tcp -d 10.20.30.40 --dport 443 -j DROP
Significado: solo clientes desde 10.66.0.0/24 pueden alcanzar el servicio interno; otros son bloqueados aunque DNAT ocurra.
Decisión: Estrecha más cuando puedas: IPs cliente individuales, no subredes enteras. Si necesitas “algunos usuarios sí, otros no”, deja de confiar solo en políticas por IP y añade autenticación a nivel de aplicación.
Tarea 8: Confirma que los contadores NAT y filter se incrementan (prueba que el tráfico golpea tus reglas)
cr0x@server:~$ sudo iptables -t nat -L PREROUTING -n -v | head
Chain PREROUTING (policy ACCEPT 120 packets, 9200 bytes)
pkts bytes target prot opt in out source destination
12 720 DNAT tcp -- wg0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8443 to:10.20.30.40:443
Significado: los contadores pkts/bytes muestran si tu regla se está usando. Contadores a cero significan que tu tráfico no llega a wg0, no es TCP, o no golpea el dport 8443.
Decisión: Si los contadores quedan en cero durante una prueba, para de adivinar y traza la ruta: selección de interfaz, enrutamiento en el cliente y si el cliente realmente está en la VPN.
Tarea 9: Verifica AllowedIPs del peer de WireGuard (clásico bug de acceso demasiado amplio)
cr0x@server:~$ sudo wg show wg0
interface: wg0
public key: 8qGk...redacted
listening port: 51820
peer: 7n9H...redacted
endpoint: 203.0.113.50:53122
allowed ips: 10.66.0.10/32
latest handshake: 1 minute, 2 seconds ago
transfer: 188.22 KiB received, 412.91 KiB sent
Significado: este peer solo tiene permitido origen 10.66.0.10/32. Bien. Si ves “0.0.0.0/0” o una subred privada grande, le has otorgado mucho más alcance del que crees.
Decisión: Mantén AllowedIPs ajustado en el lado servidor. Usa reglas de cortafuegos igualmente. Trata AllowedIPs como una primera barrera, no como la única.
Tarea 10: Captura paquetes para probar donde mueren (tcpdump: el suero de la verdad)
cr0x@server:~$ sudo tcpdump -ni wg0 tcp port 8443 -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
12:04:11.112233 IP 10.66.0.10.51512 > 10.66.0.1.8443: Flags [S], seq 39192812, win 64240, options [mss 1360,sackOK,TS val 9911 ecr 0,nop,wscale 7], length 0
12:04:12.113244 IP 10.66.0.10.51512 > 10.66.0.1.8443: Flags [S], seq 39192812, win 64240, options [mss 1360,sackOK,TS val 10911 ecr 0,nop,wscale 7], length 0
Significado: los paquetes SYN llegan a la puerta de enlace. Si no ves SYN-ACK de vuelta, la puerta de enlace no está reenviando correctamente, el host interno no es alcanzable o el tráfico de retorno está roto.
Decisión: Ejecuta una segunda captura en eth1: tcpdump -ni eth1 host 10.20.30.40 and tcp port 443. Si ves SYN en wg0 pero nada en eth1, la culpa es de NAT/filtrado/enrutamiento en la puerta de enlace.
Tarea 11: Prueba PMTU desde la perspectiva de un cliente VPN
cr0x@server:~$ ping -M do -s 1372 -c 3 10.66.0.1
PING 10.66.0.1 (10.66.0.1) 1372(1400) bytes of data.
1380 bytes from 10.66.0.1: icmp_seq=1 ttl=64 time=32.1 ms
1380 bytes from 10.66.0.1: icmp_seq=2 ttl=64 time=31.8 ms
1380 bytes from 10.66.0.1: icmp_seq=3 ttl=64 time=32.5 ms
--- 10.66.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
Significado: el camino soporta al menos paquetes de 1400 bytes sin fragmentación. Si esto falla, reduce MTU en wg0 y/o arregla el bloqueo de ICMP aguas arriba.
Decisión: Si depuras “algunas HTTPS funcionan, cargas grandes fallan”, MTU es un sospechoso principal. Arréglalo antes de culpar a TLS.
Tarea 12: Comprueba reverse path filtering (rp_filter) cuando enrutas entre interfaces
cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 1
Significado: rp_filter estricto puede descartar paquetes cuando ocurre enrutamiento asimétrico (común con VPN y múltiples interfaces).
Decisión: En una puerta de enlace VPN que hace forwarding/NAT, pon rp_filter a 0 o 2 (loose) según tu diseño. Hazlo deliberadamente; documenta por qué.
Tarea 13: Confirma presión en la tabla conntrack (el forwarding muere bajo carga)
cr0x@server:~$ sudo conntrack -S
cpu=0 found=1287 invalid=4 ignore=0 insert=4218 insert_failed=0 drop=0 early_drop=0 error=0 search_restart=0
Significado: insert_failed y drop indican agotamiento o presión de conntrack. Incluso una puerta de enlace VPN “pequeña” puede caer cuando todos se reconectan tras un fallo de Wi‑Fi.
Decisión: Si aumentan los drops, sube límites de conntrack, reduce reglas stateful donde sea seguro, o escala puertas de enlace. Y deja de usar la puerta de enlace VPN como una caja NAT de propósito general para todo.
Tarea 14: Confirma quién está conectado y cuán recientemente (porque aparecen clientes fantasma)
cr0x@server:~$ sudo wg show wg0 latest-handshakes
7n9H...redacted 1735292801
j2Qa...redacted 0
Significado: un handshake “0” significa que ese peer nunca se ha conectado desde que la interfaz está arriba (o se rotaron claves). Los timestamps en epoch pueden convertirse a tiempo humano.
Decisión: Si usuarios dicen “la VPN está conectada” pero no ves handshake, estás depurando el cliente, NAT traversal o mismatch de claves—no el reenvío de puertos.
Tarea 15: Valida el registro de tráfico denegado (si no puedes ver drops, no puedes operarlo)
cr0x@server:~$ sudo iptables -A FORWARD -i wg0 -j LOG --log-prefix "VPN-FWD-DROP " --log-level 4
cr0x@server:~$ sudo iptables -A FORWARD -i wg0 -j DROP
cr0x@server:~$ sudo journalctl -k -n 3
Dec 27 12:08:01 vpn-gw kernel: VPN-FWD-DROP IN=wg0 OUT=eth1 SRC=10.66.0.50 DST=10.20.30.40 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=51422 DF PROTO=TCP SPT=51580 DPT=443 WINDOW=64240 RES=0x00 SYN URGP=0
Significado: el log del kernel muestra qué se denegó: quién (SRC), qué (DST/DPT) y hacia dónde intentó ir (interfaz OUT).
Decisión: Si activas logging, limita la tasa. De otro modo, un host ruidoso convertirá tus logs en una denegación de billetera.
Tarea 16: Rápida “¿funciona?” desde un cliente VPN: curl con SNI/Host intacto
cr0x@server:~$ curl -vk https://10.66.0.1:8443/health
* Trying 10.66.0.1:8443...
* Connected to 10.66.0.1 (10.66.0.1) port 8443
> GET /health HTTP/1.1
> Host: 10.66.0.1:8443
> User-Agent: curl/7.81.0
> Accept: */*
< HTTP/1.1 200 OK
< Content-Type: text/plain
ok
Significado: la conexión TCP tuvo éxito y obtuviste un HTTP 200. Si recibes alertas TLS, puede que estés golpeando el virtual host equivocado o haya un desajuste de nombre en el certificado.
Decisión: Para servicios basados en nombre, prueba con el hostname real mediante --resolve y SNI apropiado, o usa un proxy inverso que termine TLS de forma consistente.
Chiste #2: El reenvío de puertos es como “solo una excepción más” en finanzas—todos acuerdan que es pequeña hasta que las sumas aparecen.
Tres micro-historias corporativas desde la trinchera
Micro-historia 1: El incidente causado por una suposición equivocada (“los usuarios VPN son de confianza”)
Una empresa mediana operaba una VPN para empleados remotos y contratistas. El perfil VPN se compartía a través de un portal interno; la autenticación era “suficientemente fuerte” y el equipo de red consideraba a los clientes VPN equivalentes a estar en la oficina. Cuando un nuevo portal administrativo interno necesitó acceso remoto, lo reenviaron desde la puerta de enlace VPN al servidor de la aplicación. Sin autenticación extra. “Es interno”.
Meses después, el portátil de un contratista fue comprometido vía una extensión de navegador que no tenía que estar en una máquina de trabajo. El atacante no necesitó un zero-day contra la VPN. Simplemente esperó a que el contratista se conectara y luego escaneó el espacio de direcciones accesible por la VPN desde el cliente. El portal administrativo reenviado fue trivial de encontrar: puerto abierto, ruta predecible y confianza en cabeceras “LAN”.
El atacante usó el portal para crear una cuenta con permisos elevados y luego pivotó a otros sistemas usando credenciales cacheadas que el portal podía acceder. La brecha no fue “la VPN”. La brecha fue la suposición de que la ubicación de red implica identidad.
La solución no fue heroica. Añadieron autenticación a nivel de aplicación, requirieron MFA para funciones administrativas, estrecharon AllowedIPs en la VPN y reemplazaron el acceso amplio de “contratista” por acceso por servicio vía un proxy inverso. El cambio más efectivo fue cultural: cualquier cosa alcanzable desde la VPN se trató como un servicio expuesto a internet, con logs y límites de tasa.
Micro-historia 2: La optimización que salió mal (MASQUERADE en todas partes)
Otra organización quería evitar tocar el enrutamiento interno. El equipo VPN decidió MASQUERADE todo el tráfico cliente VPN al entrar en la red interna. Funcionó de inmediato: no hubo cambios en routers internos, no cambios en servidores legacy y los tickets de helpdesk bajaron.
Entonces seguridad pidió una auditoría: “¿Qué usuario accedió a la app de finanzas el martes pasado?” Los logs de la app solo mostraban la IP de la puerta de enlace VPN. Cada usuario parecía idéntico. El equipo intentó compensar subiendo el logging en la puerta de enlace, pero ahora tenían dos problemas: logs enormes y aún no suficiente contexto a nivel de aplicación.
Un fallo diferente apareció en silencio: límites de tasa en algunos servicios internos se activaron inesperadamente. Desde el punto de vista del servicio, todo el tráfico venía de un host. El servicio comenzó a limitar al gateway, y de pronto “la VPN va lenta” se volvió una queja diaria. Habían optimizado fuera los cambios de rutas—y optimizado hacia un problema de observabilidad y equidad.
El rollback fue parcial. Mantuvieron MASQUERADE solo para la subred legacy que no podía aceptar rutas. Para todo lo demás, añadieron rutas para que los servicios internos vieran las IPs reales de cliente. El proxy inverso frente a apps sensibles también inyectó identidad de usuario autenticada en cabeceras (con validación estricta) para que las auditorías volvieran a tener sentido.
Micro-historia 3: La práctica aburrida pero correcta que salvó el día (denegar por defecto + revisión de cambios)
Una empresa con reputación de ser “lenta” tenía un hábito que parecía molesto hasta que no lo fue: cada cambio al cortafuegos de la puerta de enlace VPN se hacía vía repositorio, revisado por pares y desplegado por automatización. Su cortafuegos de gateway era denegar por defecto. Sus reenvíos de puertos eran explícitos y cada uno tenía una referencia de ticket en un comentario.
Una tarde, un desarrollador pidió un reenvío rápido para que un proveedor alcanzara un endpoint de staging. Un operador apresurado abrió una regla—en el puerto equivocado—y la subió. La pipeline de despliegue la detectó porque los tests unitarios de políticas de cortafuegos verificaban que solo existieran puertos de destino aprobados para esa clase de servicio. El cambio fue rechazado antes de llegar a producción.
El operador corrigió la regla e intentó de nuevo. Esta vez pasó y se desplegó, y el proveedor obtuvo acceso. Dos semanas después, un scanner automatizado del proveedor empezó a fallar y a golpear el endpoint agresivamente. Las métricas del gateway mostraron el pico; los límites de tasa por defecto del proxy inverso lo absorbieron; y los logs del cortafuegos dejaron claro qué servicio reenviado era ruidoso.
Sin heroísmos. Sin sala de crisis. Solo control disciplinado de cambios, denegar por defecto e instrumentación. El equipo “lento” entregó más rápido porque no vivían deshaciendo errores evitables.
Cita de fiabilidad (idea parafraseada): John Allspaw ha enfatizado que los incidentes vienen de interacciones del sistema, no de “error humano”, y aprender vence culpar.
Guion de diagnóstico rápido
Este es el flujo de “no pierdas una hora”. El objetivo es encontrar el cuello de botella—enrutamiento, cortafuegos, NAT, servicio o MTU—en el menor número de pasos.
Primero: prueba que el cliente está realmente en la VPN y apunta a lo correcto
- En la puerta de enlace: comprueba el handshake (
wg show wg0) y paquetes recientes en wg0 (tcpdump -ni wg0). - En el cliente: confirma la ruta hacia la dirección/puerto de reenvío VPN (cliente-side
ip route get). - Si no hay handshake ni paquetes: no es reenvío de puertos. Es configuración del cliente, claves o NAT traversal.
Segundo: verifica que el punto de decisión de reenvío (DNAT + filtro) se esté golpeando
- Comprueba contadores NAT:
iptables -t nat -L PREROUTING -n -v. - Comprueba contadores/logs de FORWARD:
iptables -L FORWARD -n -vy logs del kernel por drops. - Si los contadores no se mueven: interfaz equivocada, puerto equivocado, protocolo equivocado o tráfico que no llega.
Tercero: verifica la ruta de retorno (la causa más común de “funciona a medias”)
- Captura en la interfaz interna: ¿sale tráfico desde la puerta de enlace hacia el servicio?
- Captura en retorno: ¿vuelven las respuestas?
- Si las respuestas no vuelven: ruta de retorno faltante hacia la subred cliente VPN, rp_filter que descarta, o problema de state tracking.
Cuarto: comprueba MTU si los síntomas son “conexión funciona, transferencias se cuelgan”
- Ejecuta pruebas PMTU (Tarea 11).
- Busca stalls en handshake TLS, colgues en subidas grandes o comportamiento inconsistente según redes.
Quinto: comprueba capacidad y tablas de estado
- Conntrack drops, saturación CPU o cola en la puerta de enlace pueden simular “problemas de red”.
- Empieza con:
conntrack -S,topy contadores de errores de interfaz (ip -s link).
Errores comunes (síntoma → causa raíz → arreglo)
1) “Funciona para mí en Wi‑Fi, falla en móvil”
Síntoma: algunos clientes conectan, otros se cuelgan en TLS o en transferencias grandes.
Causa raíz: MTU demasiado alta para algunos caminos; ICMP fragmentation needed bloqueado; overhead de encapsulación VPN empuja paquetes por encima del límite.
Arreglo: reduce MTU de la interfaz VPN (WireGuard: poner MTU=1380), asegura que ICMP esté permitido, valida con PMTU pings y transferencias reales.
2) “El puerto está abierto en la puerta de enlace pero el servicio es inalcanzable”
Síntoma: SYN llega a la interfaz VPN; sin respuesta; contadores NAT incrementan pero el servicio interno nunca ve tráfico.
Causa raíz: la cadena FORWARD descarta tráfico; falta regla para conexiones NEW; regla de cortafuegos con interfaz equivocada; o IP forwarding deshabilitado.
Arreglo: habilita net.ipv4.ip_forward=1, añade permit en FORWARD con estado conntrack, y valida con contadores y tcpdump en ambas interfaces.
3) “Reenvía, pero el servicio interno registra solo la IP de la puerta de enlace”
Síntoma: auditorías de la aplicación muestran una sola IP cliente (la puerta de enlace).
Causa raíz: MASQUERADE/SNAT oculta la IP cliente para evitar añadir rutas.
Arreglo: añade rutas adecuadas para que el servicio responda a subredes cliente VPN sin SNAT, o termina en un proxy inverso que pase identidad autenticada (y la registre).
4) “El reenvío funciona por un tiempo, luego muere bajo carga”
Síntoma: caídas intermitentes, nuevas conexiones fallan, existentes funcionan mal.
Causa raíz: agotamiento de conntrack o saturación CPU en la puerta de enlace; demasiadas reglas stateful; logging agresivo.
Arreglo: dimensiona límites de conntrack, reduce logging o limita su tasa, escala la puerta de enlace y evita convertirla en un appliance NAT para todo.
5) “El usuario puede alcanzar mucho más de lo previsto”
Síntoma: un cliente VPN puede escanear subredes internas o alcanzar servicios no relacionados.
Causa raíz: AllowedIPs/push routes demasiado amplias; reglas FORWARD permisivas; políticas por defecto ACCEPT.
Arreglo: estrecha AllowedIPs, implementa denegar por defecto en FORWARD, añade reglas por destino y prueba desde el cliente con escaneos explícitos de lo que debería bloquearse.
6) “Nombre DNS funciona internamente pero no por VPN (o viceversa)”
Síntoma: por IP funciona; por nombre falla; o solo algunos usuarios resuelven la dirección correcta.
Causa raíz: split DNS no configurado; el cliente usa DNS público; el servicio requiere SNI/Host header; hairpin NAT no gestionado.
Arreglo: provee DNS en la VPN, usa hostnames consistentes y prefiere terminación por proxy inverso donde TLS/SNI sea determinista.
Listas de verificación / plan paso a paso
Plan paso a paso: exponer un servicio HTTPS interno a usuarios VPN de forma segura
- Decide el patrón de exposición. Si es HTTP(S) orientado a usuarios, usa un proxy inverso en el borde VPN. Si es un protocolo crudo, considera un bastión en lugar de un reenvío de puertos.
- Define la audiencia mínima. Usuarios específicos, dispositivos o una pequeña subred cliente VPN. Escríbelo antes de tocar iptables.
- Define el destino mínimo. Una IP:puerto interna, no una subred.
- Bloquea la postura de la puerta de enlace. Denegar por defecto en INPUT y FORWARD. Permitir established/related. Permitir solo el puerto VPN entrante desde la interfaz orientada a internet.
- Implementa reenvío con reglas de filtro explícitas. DNAT solo no es política. Añade reglas FORWARD que casen exactamente lo que pretendes.
- Decide SNAT vs retorno enrutado. Prefiere retorno enrutado (preserva IP cliente). Usa SNAT solo cuando debas, y registra las implicaciones de auditoría.
- Exige autenticación a nivel de aplicación. Si tu app asume “LAN = confiable”, arregla la app o colócala detrás de algo que haga cumplir identidad.
- Instrumenta los puntos de estrangulamiento. Contadores de cortafuegos, logs de drops del kernel (limitados), métricas de handshake VPN y logs de solicitudes en el proxy.
- Prueba modos de fallo. Desde un cliente VPN: prueba acceso permitido, acceso bloqueado y destinos que “no deberían enrutar”.
- Operativiza el cambio. Pon config de cortafuegos/VPN en control de versiones, exige revisión y asegura que el rollback esté documentado.
Checklist de seguridad: “no conviertas la VPN en un agujero”
- AllowedIPs/pushed routes son mínimos por peer.
- La política FORWARD es DROP; existen allow explícitos por cada servicio expuesto.
- No hay reenvío desde VPN a “toda la red interna” salvo justificación y segmentación.
- Protocolos administrativos pasan por bastión; no hay reenvíos SSH/RDP aleatorios.
- Existe registro para: conexiones VPN, drops de cortafuegos y acceso a servicios expuestos.
- Existen límites de tasa en endpoints expuestos (mejor proxy).
- Rotación de claves y revocación de credenciales se practican, no son teóricas.
Checklist de confiabilidad: mantenlo depurable
- Un diagrama que muestre interfaces, subredes y dirección del flujo.
- Un lugar para comprobar “¿está el usuario realmente conectado?” (handshake).
- Puntos de captura de paquetes identificados (interfaz wg, interfaz interna).
- Decisiones MTU documentadas.
- Control de cambios: quién cambió qué, cuándo y por qué.
Preguntas frecuentes (FAQ)
1) ¿Poner un servicio “detrás de la VPN” es automáticamente seguro?
No. Cambia la audiencia de “internet” a “cualquiera que pueda autenticarse en la VPN (o comprometer un cliente VPN)”. Aún necesitas autenticación a nivel de aplicación, segmentación y registro.
2) ¿Debo usar reenvío de puertos o un proxy inverso?
Proxy inverso para HTTP(S) casi siempre. El reenvío de puertos es aceptable para protocolos estrechos y bien entendidos, pero es más difícil autenticar y observar limpiamente.
3) ¿Cuál es el mayor error con WireGuard al exponer servicios?
AllowedIPs demasiado amplios y asumir que sustituye la política de cortafuegos. WireGuard es intencionalmente minimalista; debes imponer acceso con enrutamiento y reglas de cortafuegos.
4) ¿Puedo evitar SNAT/MASQUERADE y aun así hacer que el reenvío funcione?
Sí, si el servicio interno (o su gateway por defecto) tiene ruta de regreso a la subred cliente VPN vía la puerta de enlace VPN. Ese es el diseño limpio. SNAT es el atajo con costes de auditoría.
5) ¿Cómo evito que contratistas escaneen toda la red una vez en la VPN?
Dales acceso por servicio: AllowedIPs estrictos, denegar por defecto en FORWARD y reglas explícitas solo a los servicios que necesitan. Para apps web, colócalos detrás de un proxy inverso autenticado.
6) ¿Split tunnel o túnel completo?
Split tunnel reduce radio de blast y dolores de soporte, pero requiere buena higiene de enrutamiento. Túnel completo centraliza control de egress pero aumenta dependencia en la VPN y hace las caídas más ruidosas. Elige según tu modelo de amenazas y madurez operativa.
7) ¿Por qué “SYN llega a la puerta de enlace” no garantiza que el servicio sea alcanzable?
Porque puede que DNAT ocurra pero las reglas FORWARD lo descarten, el IP forwarding esté apagado, la puerta de enlace lo enruté mal o el tráfico de retorno no sepa devolver la ruta.
8) ¿Cómo hago esto auditable?
Prefiere diseños enrutados para que los servicios internos vean las IPs reales de cliente. Usa un proxy inverso que registre identidad autenticada. Centraliza logs fuera de la puerta de enlace. No confíes solo en logs NAT como único rastro de auditoría.
9) ¿Necesito hairpin NAT?
Sólo si los clientes VPN usan un hostname público que resuelve a una IP pública que vuelve a pasar por la misma puerta de enlace. Si controlas DNS, split DNS suele ser más limpio que hacks de hairpin NAT.
10) ¿Cuál es la manera correcta de desplegar cambios sin romperlo todo?
Etapa reglas con contadores y logging primero, prueba con un peer piloto, luego expande. Usa config como código y un plan de rollback. La puerta de enlace no es lugar para “deploys cowboy”.
Conclusión: próximos pasos que puedes entregar
VPN más reenvío de puertos no es inherentemente imprudente. Se vuelve imprudente cuando permites que “en la VPN” sustituya a una política real, o cuando tratas el reenvío como una casilla de router en lugar de como un servicio de borde en producción.
Haz esto a continuación:
- Escoge un patrón de exposición por servicio: proxy inverso para HTTP(S), bastión para administración, reenvío estrecho solo cuando sea necesario.
- Estrecha la alcance: AllowedIPs mínimos, FORWARD denegar por defecto, reglas explícitas por destino.
- Decide SNAT vs retorno enrutado intencionalmente y documenta las implicaciones de auditoría.
- Añade visibilidad: contadores, logs de drops (limitados), monitorización de handshakes y logs de solicitudes.
- Practica el guion de diagnóstico rápido una vez mientras no estás en llamas.
Si no puedes explicar quién puede llegar a qué, por qué, a través de qué interfaz y por qué el tráfico de retorno vuelve correctamente—sigue trabajando. Eso no es perfeccionismo. Es operar una red sin convertir tu VPN en un generador de incidentes.