El túnel dividido es lo que haces cuando «encriptar todo» con VPN rompe algo que realmente usas: tu impresora local, el portal cautivo del Wi‑Fi de la oficina,
tus videollamadas, tu IDE en la nube, tu presupuesto de latencia o tu cordura. La clave es hacer que WireGuard lleve solo el tráfico que necesita ser privado o accesible,
mientras que todo lo demás permanece en tu red normal—sin crear fugas, agujeros negros o DNS medio rotos por accidente.
Si alguna vez has visto a un desarrollador «arreglar» un túnel dividido poniendo AllowedIPs = 0.0.0.0/0 y dando por terminado el trabajo, ya sabes cómo acaba eso:
un incidente el lunes por la mañana con muchas encogidas de hombros y una suposición muy segura y equivocada.
El modelo mental: qué es realmente el túnel dividido en WireGuard
WireGuard es una VPN, pero se comporta más como un «cable Ethernet virtual seguro con cerebro de enrutamiento» que como un aparato clásico de túnel completo.
No hay negociación de «empujar rutas» como en algunas pilas VPN legadas; WireGuard hace mayormente lo que le indicas localmente: creas una interfaz,
añades peers, y luego tu SO enruta paquetes a esa interfaz según las reglas normales de enrutamiento.
El túnel dividido no es tanto una característica de WireGuard como una decisión de enrutamiento:
- Túnel completo: la mayor parte o todo el tráfico usa la interfaz VPN (ruta por defecto vía
wg0). - Túnel dividido: solo ciertos prefijos de destino (subredes/IPs) usan la VPN; todo lo demás usa la ruta por defecto normal.
- Enrutamiento selectivo y por políticas: cierto tráfico por origen/aplicación/usuario/marks usa la VPN; otros no (más avanzado, muy útil).
La configuración de WireGuard enlaza identidad y enrutamiento mediante AllowedIPs en la sección del peer. Ese parámetro tanto:
(1) define qué IPs de destino deben enviarse a ese peer, como (2) define qué IPs de origen se consideran válidas desde ese peer.
Es elegante. También es la razón por la que un cambio «pequeño» puede reescribir silenciosamente tu tabla de rutas.
La forma fiable de pensarlo es:
“Cuando envío un paquete a X, ¿qué peer reclama X en AllowedIPs?”
Si la respuesta es «ninguno», sale por tu interfaz normal. Si la respuesta es «un peer», entra en WireGuard.
Si la respuesta es «más de uno», te construiste un arma de pulgar y el kernel elegirá la «mejor coincidencia» que quizá no sea lo que pretendías.
Una verdad seca: el túnel dividido suele fallar no porque WireGuard sea difícil, sino porque el enrutamiento no perdona y el DNS es quisquilloso.
Hechos interesantes y un poco de historia (porque importa)
Puntos de contexto concretos que explican por qué el túnel dividido en WireGuard se ve como se ve:
- WireGuard fue diseñado para ser pequeño. La implementación en el kernel de Linux es famosamente compacta frente a pilas VPN antiguas, lo que reduce superficie de ataque y sorpresas.
- Usa opciones criptográficas modernas por defecto. No pasas el día debatiendo suites de cifrado; lo pasas enrutando y operando en su lugar (un mejor uso del oxígeno).
- «AllowedIPs» es a la vez enrutamiento y control de acceso. Eso no es típico en muchas VPN, donde la inyección de rutas y los ACL están separados. Es poderoso y cortante.
- WireGuard se basa en UDP. Genial para el rendimiento; ocasionalmente molesto en redes que «amistosamente» bloquean o deforman UDP.
- No hay concepto integrado de «servidor» vs «cliente». Cada peer es solo un peer. Tu organigrama no impresiona al protocolo.
- La traversía NAT es prioridad. Los clientes que se mueven funcionan bien porque WireGuard rastrea endpoints y puede actualizarlos sobre la marcha tras un paquete válido.
- wg-quick es intencionalmente opinado. Añade rutas, ajusta bits de firewall (según tus hooks de configuración) y trata de dejarte «funcionando» rápidamente—a veces demasiado rápido para túneles divididos complejos.
- El UX de túnel dividido en Android/iOS llegó después del protocolo. Al protocolo no le importó; los clientes tuvieron que añadir toggles y listas de exclusión con el tiempo.
- El túnel dividido es anterior a WireGuard. Las empresas han hecho «enrutar solo subredes corporativas» desde los días tempranos de IPsec; la diferencia es que WireGuard hace la lista de rutas explícita y local.
AllowedIPs: la palanca que mueve rutas (y a veces tu alma)
En el lado del cliente, el túnel dividido suele ser simplemente «no instalar una ruta por defecto vía wg0».
Traducción: no pongas 0.0.0.0/0 (y ::/0) en AllowedIPs.
Pon solo las subredes que realmente necesitas.
Ejemplo: quieres acceso a servicios internos en 10.40.0.0/16 y una base de datos privada en 172.20.10.5/32.
Tu config de peer queda así:
cr0x@server:~$ cat /etc/wireguard/wg0.conf
[Interface]
Address = 10.99.0.2/32
PrivateKey = <client-private-key>
DNS = 10.40.0.53
[Peer]
PublicKey = <server-public-key>
Endpoint = vpn-gw.example:51820
AllowedIPs = 10.40.0.0/16, 172.20.10.5/32
PersistentKeepalive = 25
Lo importante es lo que wg-quick hace con esto: instala rutas del kernel para esos prefijos vía wg0.
Todo lo demás usa tu ruta por defecto (normalmente la puerta de enlace de tu Wi‑Fi o Ethernet).
¿Y qué pasa con «AllowedIPs = 10.99.0.0/24» en el servidor?
El AllowedIPs en el servidor se trata de qué IPs aceptará el servidor de un peer y qué enviará de regreso a ese peer.
Para un despliegue típico de road-warrior, cada cliente obtiene una /32 dentro de la VPN (como 10.99.0.2/32) y la sección de peer del servidor lista esa /32.
Así, el servidor sabe a dónde enviar el tráfico de retorno para la dirección VPN de ese cliente.
Para sitio-a-sitio, el AllowedIPs del servidor puede incluir subredes LAN enteras detrás del peer, pero entonces estás construyendo una red realmente enrutada.
Hazlo intencionalmente. Documentalo. Trátalo como enrutamiento de producción, porque lo es.
Broma #1 (corta, relevante): El enrutamiento es como la política de oficina—todo funciona hasta que alguien reclama que es dueño de todo el edificio.
Patrones de diseño para túneles divididos reales
Patrón A: «Solo subredes corporativas» (túnel dividido clásico)
Enrutas solo los rangos RFC1918 internos que realmente usan los servicios corporativos. No 10.0.0.0/8 a menos que lo quieras de verdad.
Sé preciso. A la gente le encanta ocupar espacio IP como si fuera un bien raíz gratis.
Bueno:
AllowedIPs = 10.40.0.0/16, 10.41.12.0/24
Sospechoso:
AllowedIPs = 10.0.0.0/8(probablemente no posees todo eso)AllowedIPs = 0.0.0.0/0(eso es túnel completo, llámalo como quieras)
Patrón B: «Un solo servicio» (túnel dividido más estricto)
Enrutas un puñado de /32s (o subredes pequeñas) para los servicios exactos necesarios: un host Git, un gestor de secretos, una API interna.
Ideal para contratistas, runners de CI y situaciones de «no confío en esa laptop».
El inconveniente: debes mantener la lista actualizada. Las IPs cambian, los servicios se mueven, alguien añade una nueva región y de repente «la VPN está caída».
No está caída. Tu enrutamiento está obsoleto.
Patrón C: «Túnel dividido por política» (basado en origen)
A veces quieres que el tráfico de un usuario específico o de una red de contenedores vaya por WireGuard, mientras el resto del host permanece local.
Eso no es principalmente AllowedIPs; eso es enrutamiento por políticas en Linux (ip rule + tablas personalizadas) y tal vez fwmarks.
wg-quick puede hacer algo de esto, pero muchos despliegues de producción son explícitos.
Patrón D: «Excluir LAN local» (túnel casi completo con excepciones)
Algunos clientes (especialmente móviles) quieren túnel completo por privacidad, pero aún necesitan acceso a la LAN local (impresoras, Chromecasts, NAS, lo que sea).
Eso es «ruta por defecto vía VPN, pero añade rutas explícitas para subredes locales vía la gateway local.»
Puede funcionar. También puede crear asimetría rara cuando dispositivos locales intentan responder a tu IP asignada por la VPN. Si haces esto,
usa NAT en el cliente o evita originar tráfico LAN desde la dirección VPN.
DNS en túneles divididos: no filtrarlo, no romperlo
El DNS es donde los túneles divididos van a morir silenciosamente. Enrutas 10.40.0.0/16 correctamente, pero tu cliente sigue preguntando al resolvedor del café
por jira.corp. Por supuesto falla. O peor: el resolvedor público devuelve algo inesperado y te conectas a lo incorrecto.
Estrategias de DNS en túneles divididos, en orden creciente de madurez operativa:
1) «Simplemente configura DNS = resolvedor corporativo»
Sencillo: DNS = 10.40.0.53 en la configuración de la interfaz WireGuard. Cuando el túnel está arriba, tu resolvedor pasa a ser el corporativo.
Inconveniente: puede romper la resolución de nombres local (dominios de portal cautivo del hotel, peculiaridades de split-horizon), y puede ralentizar todo si el resolvedor corporativo está lejos.
2) DNS dividido (enrutar solo ciertos dominios al corporativo)
En Linux con systemd-resolved, puedes configurar dominios de enrutamiento por interfaz. Eso significa que *.corp va al resolvedor VPN,
y todo lo demás permanece local. Este es el punto óptimo para muchas organizaciones.
3) Resolvedor local que reenvía zonas corporativas vía VPN
Ejecutas un resolvedor local (o usas uno existente) y reenvías las zonas internas al servidor DNS de la VPN, con caché y timeouts sensatos.
Es aburrido. Funciona. También hace que la depuración sea menos teatral.
Una idea de fiabilidad parafraseada de John Allspaw: «No obtienes fiabilidad deseando; la obtienes diseñando y practicando para la falla.»
El DNS en túnel dividido es un ejemplo perfecto—diseñalo, no lo desees.
Tareas prácticas (comandos, salidas, decisiones)
Esta es la parte donde dejamos de admirar el protocolo y empezamos a interrogar al sistema.
Cada tarea abajo incluye: un comando, salida realista, lo que significa y qué decides después.
Tarea 1: Confirmar que el túnel realmente está activo (y no «configurado pero muerto»)
cr0x@server:~$ sudo wg show
interface: wg0
public key: 2pQ2c2fWmGm6l5qgkq8n8fZ4xX9o7u1nJt4XxR9gQhE=
private key: (hidden)
listening port: 51820
peer: Hx2e1F0rQyQH7cQqX2o3v9KQ0m7E4uE3r4Y8z8u4L0w=
endpoint: 203.0.113.50:53211
allowed ips: 10.99.0.2/32
latest handshake: 42 seconds ago
transfer: 88.31 MiB received, 12.04 MiB sent
persistent keepalive: every 25 seconds
Significado: El handshake es reciente y bytes se están moviendo. La criptografía está bien; céntrate en enrutamiento/DNS/MTU si las aplicaciones aún fallan.
Decisión: Si latest handshake es «never» o muy antiguo, salta a comprobaciones de firewall/NAT/endpoint antes de tocar rutas.
Tarea 2: Inspeccionar qué rutas instaló wg-quick
cr0x@server:~$ ip route show table main | grep wg0
10.40.0.0/16 dev wg0 proto static scope link
172.20.10.5 dev wg0 proto static scope link
Significado: Solo los prefijos planeados enrutan vía wg0. Ese es un túnel dividido limpio.
Decisión: Si ves default dev wg0 y no querías túnel completo, corrige AllowedIPs inmediatamente.
Tarea 3: Verificar que la ruta por defecto permanece local
cr0x@server:~$ ip route show default
default via 192.168.1.1 dev wlan0 proto dhcp metric 600
Significado: El tráfico de Internet permanece por wlan0. Ese es todo el punto del túnel dividido.
Decisión: Si la ruta por defecto apunta a wg0, confirma si realmente querías túnel completo y si existen excepciones para la LAN local.
Tarea 4: Comprobar qué ruta elegirá el kernel para un destino específico
cr0x@server:~$ ip route get 10.40.12.34
10.40.12.34 dev wg0 src 10.99.0.2 uid 1000
cache
Significado: Los paquetes a 10.40.12.34 irán por wg0, con origen 10.99.0.2.
Decisión: Si muestra dev wlan0, tu túnel dividido no está instalado, o la ruta está siendo sobrescrita por una ruta más específica.
Tarea 5: Validar la configuración DNS en sistemas con systemd-resolved
cr0x@server:~$ resolvectl status wg0
Link 8 (wg0)
Current Scopes: DNS
Protocols: +DefaultRoute
Current DNS Server: 10.40.0.53
DNS Servers: 10.40.0.53
Significado: wg0 tiene un servidor DNS asignado. Dependiendo de tu configuración, puede convertirse en el predeterminado para todas las consultas.
Decisión: Si los nombres internos fallan mientras las rutas son correctas, configura DNS dividido (dominios de enrutamiento) en lugar de forzar todo el DNS por el corporativo.
Tarea 6: Confirmar que la resolución de nombres internos va donde esperas
cr0x@server:~$ resolvectl query jira.corp
jira.corp: 10.40.12.80 -- link: wg0
-- Information acquired via protocol DNS in 22.4ms.
-- Data is authenticated: no
Significado: La consulta fue respondida vía DNS de wg0, devolviendo una IP interna.
Decisión: Si resuelve vía wlan0 a una IP pública o NXDOMAIN, tienes un problema de enrutamiento DNS, no de WireGuard.
Tarea 7: Probar la ruta con un curl dirigido y enlazado a la interfaz
cr0x@server:~$ curl -sS --interface wg0 -o /dev/null -w "HTTP %{http_code}\n" http://10.40.12.80/
HTTP 200
Significado: El servicio es accesible por wg0 y responde. El problema de la app probablemente sea selección de nombre DNS, ajustes de proxy o autenticación.
Decisión: Si enlazar a wg0 falla pero sin enlazar funciona (o viceversa), has descubierto una asimetría de enrutamiento o comportamiento de proxy local.
Tarea 8: Comprobar dolor por MTU (el asesino silencioso de «funciona para cosas pequeñas»)
cr0x@server:~$ ping -M do -s 1420 -c 3 10.40.12.80
PING 10.40.12.80 (10.40.12.80) 1420(1448) bytes of data.
1428 bytes from 10.40.12.80: icmp_seq=1 ttl=63 time=38.2 ms
1428 bytes from 10.40.12.80: icmp_seq=2 ttl=63 time=38.6 ms
1428 bytes from 10.40.12.80: icmp_seq=3 ttl=63 time=38.1 ms
--- 10.40.12.80 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
Significado: Un payload de 1420 bytes con DF establecido funciona. Probablemente MTU no sea el problema a ese tamaño.
Decisión: Si ves «Frag needed», reduce la MTU de la interfaz WireGuard (valores comunes: 1280–1420) y vuelve a probar.
Tarea 9: Inspeccionar MTU y contadores de la interfaz
cr0x@server:~$ ip -s link show dev wg0
8: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/none
RX: bytes packets errors dropped missed mcast
98123456 74231 0 12 0 0
TX: bytes packets errors dropped carrier collsns
13200456 52122 0 3 0 0
Significado: Existen algunas pérdidas. Unas pocas caídas pueden ser normales; crecimiento persistente bajo carga puede señalar MTU, colas o problemas de firewall.
Decisión: Si las pérdidas aumentan rápido mientras las transferencias se estancan, prueba reducir MTU y revisa filtrado UDP.
Tarea 10: Confirmar reenvío de IP y NAT en la gateway (sitio-a-sitio o road-warrior vía servidor)
cr0x@server:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
Significado: El servidor puede enrutar entre interfaces.
Decisión: Si es 0, los clientes pueden hacer handshake pero no alcanzarán redes internas detrás del servidor. Actívalo y hazlo persistente.
Tarea 11: Validar reglas NAT/forward (ejemplo iptables)
cr0x@server:~$ sudo iptables -t nat -S | grep -E "POSTROUTING|wg0"
-A POSTROUTING -s 10.99.0.0/24 -o eth0 -j MASQUERADE
Significado: Los clientes VPN (10.99.0.0/24) se NATean al salir por eth0. Esto es común para acceso road-warrior a redes privadas.
Decisión: Si esperas comportamiento enrutado (sin NAT), elimina MASQUERADE y asegúrate de que los routers internos sepan cómo llegar a la subred VPN.
Tarea 12: Ver si hay enrutamiento por políticas o marcas (túnel dividido avanzado en Linux)
cr0x@server:~$ ip rule show
0: from all lookup local
32764: from all fwmark 0xca6c lookup 51820
32766: from all lookup main
32767: from all lookup default
Significado: El tráfico marcado con 0xca6c usa la tabla de enrutamiento 51820 (comportamiento común de wg-quick en algunas configuraciones).
Decisión: Si solo algunas aplicaciones deben usar el túnel, marca esos flujos intencionalmente (cgroups, iptables mangle) y deja el resto sin marcar.
Tarea 13: Inspeccionar AllowedIPs y endpoints del peer en el cliente
cr0x@server:~$ sudo wg show wg0 peers
Hx2e1F0rQyQH7cQqX2o3v9KQ0m7E4uE3r4Y8z8u4L0w=
cr0x@server:~$ sudo wg show wg0 peer Hx2e1F0rQyQH7cQqX2o3v9KQ0m7E4uE3r4Y8z8u4L0w=
peer: Hx2e1F0rQyQH7cQqX2o3v9KQ0m7E4uE3r4Y8z8u4L0w=
endpoint: 198.51.100.22:51820
allowed ips: 10.40.0.0/16, 172.20.10.5/32
latest handshake: 1 minute, 10 seconds ago
transfer: 12.04 MiB received, 88.31 MiB sent
Significado: Tus prefijos divididos están presentes. El endpoint es conocido y el handshake está activo.
Decisión: Si AllowedIPs contiene un rango amplio que no pretendías, corrige la configuración primero. Depurar otra cosa sería perder tiempo.
Tarea 14: Capturar fugas y tráfico por ruta equivocada con tcpdump (verdad rápida)
cr0x@server:~$ sudo tcpdump -ni wg0 host 10.40.12.80 and port 443 -c 3
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.99.0.2.54422 > 10.40.12.80.443: Flags [S], seq 18273612, win 64240, options [mss 1360,sackOK,TS val 102030 ecr 0,nop,wscale 7], length 0
IP 10.40.12.80.443 > 10.99.0.2.54422: Flags [S.], seq 23011222, ack 18273613, win 65160, options [mss 1360,sackOK,TS val 556677 ecr 102030,nop,wscale 7], length 0
IP 10.99.0.2.54422 > 10.40.12.80.443: Flags [.], ack 1, win 502, options [nop,nop,TS val 102031 ecr 556677], length 0
3 packets captured
Significado: El handshake TCP ocurre sobre wg0. El enrutamiento es correcto para ese flujo.
Decisión: Si no ves paquetes en wg0 pero los esperas, revisa ip route get y las reglas de enrutamiento por políticas.
Tarea 15: Detectar cuando la red subyacente bloquea UDP (síntoma: nunca hay handshake)
cr0x@server:~$ sudo tcpdump -ni eth0 udp port 51820 -c 5
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
IP 203.0.113.50.53211 > 198.51.100.22.51820: UDP, length 148
IP 203.0.113.50.53211 > 198.51.100.22.51820: UDP, length 148
IP 203.0.113.50.53211 > 198.51.100.22.51820: UDP, length 148
5 packets captured
Significado: Los paquetes llegan al servidor. Si los handshakes aún no ocurren, el servidor puede estar descartando respuestas o las claves no coinciden.
Decisión: Si no ves nada llegando, la ruta de red bloquea UDP o el endpoint/puerto es incorrecto. Arregla la alcanzabilidad antes de tocar el enrutamiento.
Tarea 16: Confirmar que el enrutamiento de vuelta no está descartando respuestas (rp_filter en Linux)
cr0x@server:~$ sysctl net.ipv4.conf.all.rp_filter
net.ipv4.conf.all.rp_filter = 1
Significado: El filtrado de ruta inversa estricto puede descartar tráfico asimétrico (común al mezclar VPN y múltiples uplinks).
Decisión: Si haces enrutamiento por políticas avanzado, considera establecer rp_filter en modo suelto (2) en las interfaces relevantes tras entender el trade-off de seguridad.
Guía rápida de diagnóstico
Cuando el túnel dividido «más o menos funciona», tu tiempo se come por la capa equivocada. Aquí está el orden que normalmente encuentra el cuello de botella más rápido.
Está sesgado hacia la realidad de producción: la mayoría de fallos son deriva de configuración, sorpresas de enrutamiento, DNS o MTU—no criptografía.
Primero: ¿está vivo el túnel?
- Comprobar:
wg showen ambos extremos. - Señal: Handshake reciente + contadores de transferencia en aumento.
- Si está mal: verifica alcanzabilidad del endpoint, reglas de firewall, camino UDP, claves correctas y hora (la deriva de reloj no suele ser fatal aquí, pero no uses NTP anticuado).
Segundo: ¿el enrutamiento hace lo que crees?
- Comprobar:
ip routeyip route get <target>. - Señal: Los destinos que te importan van vía wg0; la ruta por defecto permanece local.
- Si está mal: corrige
AllowedIPsprimero; luego considera reglas de enrutamiento por políticas o rutas competidoras desde NetworkManager/otros clientes VPN.
Tercero: ¿el DNS sigue el split?
- Comprobar:
resolvectl querypara nombres internos, y qué enlace respondió. - Señal: Zonas internas resuelven vía DNS de wg0 o reglas de DNS dividido; nombres públicos resuelven localmente como se pretende.
- Si está mal: implementa DNS dividido (dominios de enrutamiento) o ejecuta un resolvedor local que reenvíe zonas internas.
Cuarto: ¿el MTU hace fallar transferencias grandes?
- Comprobar: Pings DF a 1280/1380/1420 y compara «pequeño funciona, grande se atasca».
- Señal: Sin errores de «fragmentation-needed»; rendimiento estable.
- Si está mal: baja MTU de wg0; verifica path MTU en el underlay; busca PPPoE o sobrecarga de encapsulación.
Quinto: ¿firewalls y reglas NAT son consistentes con tu historia?
- Comprobar: forwarding, NAT (si se usa), y que los routers internos conozcan rutas de retorno (si no se NATea).
- Señal: el tráfico de retorno alcanza clientes; no hay descartes asimétricos por rp_filter.
- Si está mal: o bien NATea intencionalmente, o añade rutas correctas en la red interna; no hagas las dos cosas a medias.
Tres microhistorias corporativas desde las trincheras
1) Incidente causado por una suposición equivocada: «AllowedIPs es solo un ACL»
Una empresa mediana desplegó WireGuard para reemplazar una VPN de acceso remoto antigua. El grupo piloto eran en su mayoría desarrolladores,
y todo fue bien—hasta que se integró el equipo de finanzas, junto con unas cuantas integraciones SaaS de terceros que usaban listas de permitidos por IP.
Un ingeniero supuso que AllowedIPs era puramente una «lista de control de acceso» en el peer—como «qué puede alcanzar el cliente».
Añadieron 0.0.0.0/0 en el cliente porque «es seguro; de todas formas hago NAT a subredes corporativas.»
El resultado fue un túnel completo accidental: todo el tráfico saliente pasó por el egress corporativo.
No falló ruidosamente. Falló socialmente: la latencia a sitios comunes aumentó, comprobaciones de geolocalización empezaron a marcar inicios de sesión,
y un IDS interno vio patrones de tráfico para los que no estaba dimensionado. El sistema de contabilidad web del equipo de finanzas empezó a limitar peticiones
porque las solicitudes ahora venían de un conjunto reducido de IPs NAT compartidas.
El diagnóstico técnico fue sencillo: la ruta por defecto apuntaba a wg0, y el DNS se había configurado al resolvedor interno.
La queja «la VPN está lenta» era real, pero la causa raíz no fue el rendimiento de WireGuard—fue un cambio arquitectónico no intencional.
La solución fue aburrida: quitar 0.0.0.0/0, enrutar solo prefijos corporativos y mantener el tráfico SaaS local.
La lección perdurable: en WireGuard, AllowedIPs es enrutamiento. Trátalo como si editaras la tabla de enrutamiento en cada laptop—porque lo estás haciendo.
2) Optimización que salió mal: «Reduzcamos MTU por velocidad»
Otra organización tenía fuerza laboral global y una gateway WireGuard en una región. Notaron uploads inestables a un almacén de artefactos interno.
Alguien recordó «problemas de MTU» de una VPN antigua y decidió «optimizar» bajando agresivamente la MTU a 1200 en todos los clientes.
La razón: paquetes más pequeños, menos fragmentación, menos retransmisiones. Sonó plausible en una reunión.
Lo que pasó: el tráfico interactivo mejoró ligeramente, pero el rendimiento en transferencias masivas se hundió, especialmente en enlaces de alta latencia.
El uso de CPU en clientes y gateway aumentó por más paquetes por megabyte. Algunos endpoints tocaron límites de tasa o pérdidas en colas porque la tasa de paquetes fue mayor.
El almacén de artefactos no solo se sentía más lento—empezó a agotar tiempos en publishes grandes.
Lo complicado fue que «funciona» seguía siendo verdad para pruebas pequeñas: podías curl un endpoint pequeño, ping funcionaba, SSH iba bien.
Solo cuando un pipeline de build subía cientos de megabytes apareció el problema.
La solución: dejar de adivinar. Ejecutaron pings DF para encontrar una MTU que funcionara end-to-end (a menudo 1380–1420 según el underlay),
establecieron una MTU sensata y luego redujeron reintentos de subida mejorando timeouts en vez de comprimir la red en paquetes diminutos.
La «optimización» quedó como una nota postmortem sobre tuning por culto de los rituales.
3) Práctica aburrida pero correcta que salvó el día: «Mantenemos un inventario de rutas»
Una empresa regulada con varias subsidiarias mantenía una capa de acceso basada en WireGuard para alcanzar un puñado de subredes internas.
Su red era un collage: rangos RFC1918 solapados, fusiones y algunos NAT «temporales» que habían sobrevivido a varios managers.
Era el tipo de lugar donde «simplemente enruta 10/8» limita tu carrera.
El equipo de operaciones mantenía un inventario simple de rutas: qué prefijos internos existen, quién los posee, cuáles son alcanzables vía VPN,
y cuáles nunca deben enrutarse por acceso remoto por clasificación de datos.
No era glamuroso. Vivía en control de versiones. Se revisaba como código.
Cuando una nueva unidad de negocio solicitó acceso, el equipo añadió dos /24 específicas a AllowedIPs y actualizó dominios de enrutamiento DNS.
Dos semanas después, otro equipo introdujo accidentalmente una subred solapada en un laboratorio que habría secuestrado tráfico si se usaran prefijos amplios.
Debido a que el enrutamiento de la VPN era estrecho y documentado, nada se filtró y nada se rompió.
El incidente que pudo haber ocurrido, no ocurrió. Las mejores victorias operativas suelen ser invisibles y profundamente poco sexys.
Además, el equipo durmió normalmente, que es un objetivo SRE olvidado.
Errores comunes: síntomas → causa raíz → solución
1) Síntoma: El tráfico de Internet inesperadamente pasa por la VPN
Causa raíz: El AllowedIPs del cliente incluye 0.0.0.0/0 y/o ::/0, instalando una ruta por defecto vía wg0.
Solución: Reemplaza por prefijos específicos. Si necesitas «casi todo por VPN», añade excepciones explícitas para la LAN local y verifica las rutas de retorno.
2) Síntoma: «El handshake funciona, pero no alcanzo servicios internos»
Causa raíz: El servidor no está reenviando paquetes (ip_forward=0), o la red interna no tiene rutas de regreso a la subred VPN.
Solución: Activa el reenvío y o bien NAT en la gateway o bien añade rutas correctas en los routers internos. Elige un diseño y cúmplelo.
3) Síntoma: Los nombres internos no resuelven, pero las IPs sí
Causa raíz: El DNS aún apunta a resolvedores locales; las zonas internas no se reenvían vía VPN.
Solución: Configura DNS dividido (dominios de enrutamiento por interfaz) o establece DNS de VPN al conectarte. Verifica con resolvectl query.
4) Síntoma: Algunos sitios internos cargan, otros se quedan colgados en login o descargas grandes
Causa raíz: Problemas de MTU/PMTUD, a menudo por encapsulación en el underlay o ICMP «fragmentation needed» bloqueado.
Solución: Baja MTU de wg0; prueba con pings DF; si controlas firewalls, permite los tipos ICMP necesarios.
5) Síntoma: Dispositivos de la LAN local dejan de funcionar cuando la VPN está activa
Causa raíz: Túnel completo sin excepciones LAN, o cambios de DNS que causan que los nombres locales se resuelvan distinto, o rp_filter descartando en sistemas multi-homed.
Solución: Mantén el túnel dividido estrecho; añade rutas LAN explícitas vía la gateway local si es necesario; considera rp_filter en modo suelto en escenarios avanzados de enrutamiento.
6) Síntoma: Dos peers «pelean» y el tráfico va al sitio equivocado
Causa raíz: AllowedIPs solapados entre peers. La coincidencia más larga elige un peer que no pretendías, o la ruta entra en flapping cuando cambian configuraciones.
Solución: Haz que AllowedIPs no se solapen; si debes solaparlos, usa prefijos más específicos deliberadamente y documenta la propiedad.
7) Síntoma: La VPN funciona en Wi‑Fi doméstico pero no en redes de hotel/aeropuerto
Causa raíz: UDP bloqueado o portal cautivo interfiriendo; el endpoint no es alcanzable hasta aceptar el portal.
Solución: Mantén un camino no VPN para alcanzar el portal; considera un puerto o estrategia de transporte de fallback en tu gateway; depura con tcpdump en el servidor.
Broma #2 (corta, relevante): Los portales cautivos son los únicos sistemas capaces de derribar tanto la red como el optimismo con la misma página de inicio.
Listas de verificación / plan paso a paso
Plan 1: Construir un túnel dividido limpio para «solo subredes corporativas»
-
Inventaria lo que realmente necesitas.
Lista prefijos internos y zonas DNS internas. Si no puedes listarlos, no estás listo para hacerlo de forma segura. -
Asigna direcciones VPN cliente estables.
Prefiere /32 por cliente (IPv4) y /128 por cliente (IPv6) para mantener el enrutamiento sin ambigüedades. -
Configuración del cliente: mantén AllowedIPs estrecho.
Incluye solo subredes de servicios internos y/o /32s concretos. -
Configuración del servidor: acepta solo la(s) IP(s) VPN del cliente.
En la sección peer del servidor, usa la /32 del cliente. No aceptes rangos amplios a menos que sea sitio-a-sitio. -
Enrutamiento en el servidor: elige NAT o rutas de retorno enrutadas.
- Si NAT: MASQUERADE a la interfaz interna para la subred VPN.
- Si enrutado: anuncia la subred VPN en el dominio de enrutamiento interno.
-
DNS: decide entre «todo DNS vía VPN» o DNS dividido.
Si los usuarios necesitan navegación local sin afectar, implementa DNS dividido. Si no, recibirás tickets de «la VPN rompe mi portal de impresora» para siempre. -
MTU: establece valores sensatos y prueba.
Empieza con 1420. Si estás en PPPoE o túneles anidados, espera bajar más. -
Registra y observa.
Vigila tiempos de handshake, contadores de transferencia y drops de interfaz durante el despliegue.
Plan 2: Túnel dividido por políticas (avanzado, vale la pena para hosts compartidos)
- Crea wg0 sin instalar rutas amplias. Usa AllowedIPs estrechos o gestión de rutas manual.
- Crea una tabla de enrutamiento dedicada para tráfico VPN. Ejemplo: tabla 51820.
- Añade rutas a la tabla 51820 para prefijos corporativos vía wg0.
- Marca el tráfico que debe usar la VPN. Usa iptables/nftables mangle o marcado basado en cgroups.
- Añade ip rules que mapeen fwmark a la tabla VPN.
- Prueba con ip route get y tcpdump. No «supongas» que marcaste lo que crees que marcaste.
- Documenta la política. Seis meses después olvidarás por qué parte del tráfico evita el túnel, y tu yo futuro se molestará.
Plan 3: «Casi túnel completo pero mantener LAN local» (hazlo con cuidado)
- Usa AllowedIPs de túnel completo (
0.0.0.0/0,::/0) solo si realmente lo quieres. - Añade rutas explícitas para subredes locales (como
192.168.0.0/16o tu LAN real) vía la gateway local. - Verifica rutas de retorno. Algunos dispositivos locales no responderán a tu IP origen VPN; puede que necesites NAT para tráfico hacia LAN o una selección de origen cuidadosa.
- Prueba impresión, casting y descubrimiento local. El descubrimiento por multicast/broadcast normalmente no atraviesa la VPN; gestiona expectativas.
Preguntas frecuentes
1) ¿El túnel dividido es «menos seguro» que el túnel completo?
Depende de tu modelo de amenaza. El túnel dividido mantiene el tráfico no corporativo fuera de tu VPN, reduciendo carga y radio de impacto.
Pero también significa que el cliente está simultáneamente en la red pública y en la red corporativa.
Si necesitas control de egress fuerte, DLP o inspección consistente, el túnel completo puede justificarse—solo hazlo intencionalmente.
2) ¿Qué hace exactamente AllowedIPs en el cliente?
Es el selector de enrutamiento: los destinos que coinciden con AllowedIPs van al túnel WireGuard hacia ese peer.
También actúa como filtro de qué direcciones de origen son aceptables desde ese peer. No es «solo un ACL».
3) ¿Por qué mi túnel se conecta pero no alcanzo nada detrás del servidor?
Usualmente reenvío o enrutamiento de retorno. El handshake prueba claves y alcanzabilidad al endpoint, no que tu red interna sepa cómo volver.
Revisa net.ipv4.ip_forward, reglas NAT (si haces NAT) o rutas internas hacia la subred VPN.
4) ¿Cómo mantengo el tráfico de Internet local pero sigo usando DNS interno?
Usa DNS dividido: enruta solo zonas internas al resolvedor VPN y deja lo demás en el resolvedor local.
En systemd-resolved se hace con servidores DNS por enlace y dominios de enrutamiento.
5) ¿Puedo dividir el túnel por aplicación (solo mi navegador por VPN)?
No nativamente solo con WireGuard. Se hace con funciones del SO: enrutamiento por políticas, marcado de paquetes y a veces VPN por aplicación en móviles.
En Linux combina ip rule con fwmarks y rutas en una tabla personalizada.
6) ¿Por qué algunas apps corporativas rompen solo cuando la VPN está activa?
Causas comunes: cambios de DNS (split-horizon), comportamiento de proxy auto-config, o solapamiento de rutas (tus rutas VPN secuestran una subred usada por una red local).
Verifica con ip route get al endpoint de la app y revisa qué enlace respondió la consulta DNS.
7) ¿Necesito PersistentKeepalive para túnel dividido?
Si el cliente está detrás de NAT (común), sí—por lo general. Keepalive ayuda a mantener la asignación NAT para que paquetes entrantes desde el servidor lleguen al cliente.
Para sitio-a-sitio siempre activo con endpoints estables, puede que no lo necesites. Para laptops en Wi‑Fi de cafetería, sí.
8) ¿Debo enrutar todos los rangos RFC1918 por la VPN?
Evítalo a menos que realmente los controles. Enrutar 10.0.0.0/8 por tu VPN suele colisionar con redes domésticas, VPCs en la nube y entornos de laboratorio.
Enruta solo lo que posees y necesitas. Sé específico; tu yo futuro te lo agradecerá.
9) ¿Cómo depuro «funciona con ping pero no con HTTPS»?
Empieza por MTU y firewall. ICMP puede tener éxito mientras TCP se atasca por problemas de fragmentación. Prueba con pings DF e inspecciona con tcpdump.
También verifica que la IP del servicio que alcanzas realmente sea accesible y no cambie vía DNS.
Conclusión: próximos pasos que no arruinarán tu semana
El túnel dividido con WireGuard es simple en concepto y sorprendentemente fácil de arruinar en producción, mayormente porque los humanos son optimistas respecto al enrutamiento.
La estrategia ganadora no es la astucia. Es la claridad: prefijos estrechos, comportamiento DNS explícito y verificación con herramientas reales.
Pasos prácticos siguientes:
- Decide el objetivo de enrutamiento en una frase («solo estas subredes via VPN» o «todo via VPN excepto LAN»). Escríbelo.
- Audita AllowedIPs en cada perfil de cliente. Elimina rangos amplios que no puedas justificar.
- Valida con dos comandos:
wg show(vivo) yip route get(verdad de la ruta). - Arregla DNS deliberadamente: o aceptas «todo DNS via VPN» o implementas DNS dividido; no dejes que suceda por deriva.
- Prueba MTU una vez en redes representativas y fija un valor sensato; no «optimices» a ciegas.
- Documenta los prefijos como lo harías con reglas de firewall. Porque lo son, con mejor PR.