WireGuard en el router: tuneliza tu LAN detras del tunel sin abrir puertos
Hay una decision que cambia el problema entero, y casi nadie la piensa bien: en vez de que cada equipo de tu casa se conecte por su cuenta a un VPN, pones el tunel una sola vez en el router y toda la LAN queda detrás. El router habla WireGuard con el servidor remoto; tus laptops, el television y el NAS no saben que existe un tunel.
El beneficio practico es que no abres ningun puerto en la WAN. Tu router sale hacia internet con una conexion UDP saliente, igual que un navegador. Eso resuelve el caso clasico del ISP con CGNAT, donde en la practica no puedes abrir puertos ni aunque quieras, y tambien te da un punto unico donde aplicar reglas: si el tunel se cae, cae todo y lo ves en un solo lugar.
El detalle incomodo es que OpenWrt no se comporta como un Linux de escritorio. No hay wg-quick, no hay archivos .conf que editar a mano, y hay una opcion que si te la saltas el tunel queda arriba pero no enruta nada. Este post es la ruta que a mi me funciono, con los comandos exactos y la trampa de route_allowed_ips explicada antes de que teemplace.
TL;DR — Lo que vas a tener al final
- Tiempo de setup: 25-40 minutos en el router: 5 para instalar los paquetes, 10 para generar las claves, 15 para la configuracion por
uciy el resto en verificar el handshake y el DNS. - Requisitos: OpenWrt 25.12.6 en un router con soporte de WireGuard en kernel, salida UDP saliente hacia el servidor y un servidor WireGuard remoto que ya acepte tu router como peer.
- Resultado: un
wg showconlatest handshakereciente y0.0.0.0/0en las allowed IPs del peer, con toda la LAN saliendo por el tunel y sin un solo puerto abierto en la WAN. - Troubleshooting: los dos fallos mas frecuentes son
route_allowed_ipsausente (netifd lo deja en 0 por defecto) y una direccion de interfaz sin mascara, que netifd interpreta como/32y no enruta hacia el otro extremo.
Por que tunelizar en el router y no en cada equipo
Las dos arquitecturas son validas, pero resuelven problemas distintos. El VPN por equipo sirve cuando quieres que una laptop especifica tenga salida por otro pais. El VPN en el router sirve para otra cosa: convertir el router en la puerta de salida de toda la red local.
La diferencia se nota en tres puntos concretos:
- La IP de salida cambia para todos. La laptop, el smart TV y la camara de seguridad salen por la misma IP publica del servidor remoto. No necesitas instalar un cliente en un aparato que no tiene sistema operativo.
- No hay puertos abiertos en la WAN. El router inicia la conexion UDP saliente. Tu ISP no necesita darte IP publica y tu router no expone un puerto a internet.
- El control queda centralizado. Las reglas de firewall se escriben una vez, en el router, y apliquen a todo lo que cuelgue de el.
El caso de uso que mas se repite en LATAM es el CGNAT: los proveedores de fibra y cable en Colombia, Mexico, Argentina y Chile entregan cada vez mas conexiones con IP publica compartida, y el puerto 51820 UDP sencillamente no se puede abrir. Un cliente WireGuard atras de esa conexion si funciona, porque la conexion se inicia desde adentro hacia afuera.
Prepara el router: OpenWrt 25.12 y el cambio de gestor de paquetes
Antes de tocar la configuracion, un dato que cambia comandos viejos: OpenWrt 25.12 sustituyo opkg por apk (Alpine Package Keeper). La version estable actual es 25.12.6, publicada el 18 de octubre de 2026. Si estas leyendo un tutorial que te dice opkg install wireguard, estas copiando comandos de la rama 24.10 o anterior y no te van a funcionar tal cual.
Las notas oficiales de la rama 25.12 son explicitas: OpenWrt paso del gestor opkg al apk (Alpine Package Keeper). Segun el propio announce, apk soporta casi todas las funciones de opkg, solo cambiaron los nombres de unos pocos paquetes y los argumentos de linea de comandos son distintos. Por eso la diferencia practica es esta:
# 25.12 y posteriores
apk update
apk add wireguard-tools luci-proto-wireguard
El nucleo lo hace wireguard-tools por ti: su Makefile declara DEPENDS:= +kmod-wireguard, asi que el modulo de kernel se instala como dependencia automatica. El paquete del modulo se llama kmod-wireguard y se genera desde la configuracion del kernel, por eso aparece en el feed kmods/ del target y no en el feed de paquetes normal.
El segundo paquete, luci-proto-wireguard, es el que te habilita la interfaz web: sin el, LuCI no tiene la pantalla de WireGuard y solo puedes configurarlo por consola. Si lo que quieres es ver el estado del tunel y los contadores desde el navegador, ese paquete ademas arrastra rpcd-mod-wireguard, que es el que expone los datos al panel.
La confirmacion de que quedo instalado se ve en el binario y en el helper de netifd:
wg --version
ls -l /lib/netifd/proto/wireguard.sh
Un detalle que sorprende viniendo de un servidor Linux: el paquete wireguard-tools de OpenWrt no instala wg-quick. Su seccion de instalacion en el Makefile copia unicamente el binario wg, el script wireguard_watchdog y el helper de netifd. En un servidor normal tu creas un wg0.conf y corres wg-quick up; en el router la interfaz la administra netifd y tu la describes en /etc/config/network. Si vienes de un servidor Linux y buscas wg-quick, no lo vas a encontrar, y no es que este roto.
Genera las claves del lado del router
WireGuard usa Curve25519 para las claves de identidad y ChaCha20-Poly1305 para cifrar el trafico. Cada extremo tiene su par de claves: la privada nunca sale del equipo y la publica es la que le entregas al otro.
El umask en la primera linea no es decorativo. Sin el, el archivo de clave privada se crea con permisos que cualquier usuario del sistema puede leer, y una clave privada de WireGuard robada es un tunel abierto para quien la tenga.
umask go=
wg genkey | tee /etc/wireguard/client.key | wg pubkey > /etc/wireguard/client.pub
wg genpsk > /etc/wireguard/client.psk
El pre-shared key es una capa extra de autenticacion sobre la clave publica. No es obligatorio, pero es recomendado: con el, un atacante que consiga capturar un handshake tiene que superar tambien el PSK. Es la misma razon por la que OpenVPN lo usa.
Ahora tienes tres archivos que nunca se van de tu router. La clave publica del router y el PSK se los entregas al administrador del servidor remoto; la clave privada del servidor te la entrega el. La publica de tu router va en el bloque [Peer] del servidor, y la publica del servidor va en el bloque [Peer] del router.
cat /etc/wireguard/client.pub
Configura la interfaz con uci
Aqui es donde OpenWrt se separa de un Linux normal. Todo se declara con uci en /etc/config/network y netifd lo traduce a la configuracion real de WireGuard. La interfaz se declara con option proto 'wireguard', y cada peer es una seccion de tipo wireguard_ seguida del nombre de la interfaz.
Este bloque declara la interfaz vpn y su peer. Lo vas a escribir con uci set para no editar el archivo a mano y dejar el formato roto:
uci -q delete network.vpn
uci set network.vpn="interface"
uci set network.vpn.proto="wireguard"
uci set network.vpn.private_key="$(cat /etc/wireguard/client.key)"
uci add_list network.vpn.addresses="10.8.0.2/24"
uci add_list network.vpn.addresses="fd00:8::2/64"
uci -q delete network.wgpeer
uci set network.wgpeer="wireguard_vpn"
uci set network.wgpeer.public_key="CLAVE_PUBLICA_DEL_SERVIDOR"
uci set network.wgpeer.preshared_key="$(cat /etc/wireguard/client.psk)"
uci set network.wgpeer.endpoint_host="DIRECCION_DEL_SERVIDOR"
uci set network.wgpeer.endpoint_port="51820"
uci set network.wgpeer.persistent_keepalive="25"
uci set network.wgpeer.route_allowed_ips="1"
uci add_list network.wgpeer.allowed_ips="0.0.0.0/0"
uci add_list network.wgpeer.allowed_ips="::/0"
uci commit network
service network restart
Cuatro valores de ese bloque merecen explicarse uno por uno, porque son los que separan un tunel que funciona de uno que parece funcionar.
route_allowed_ips: la trampa numero uno
El helper de netifd lee esa opcion con config_get_bool route_allowed_ips "$section" "route_allowed_ips" 0. El valor por defecto es 0. Es decir: si declaras allowed_ips 0.0.0.0/0 pero no pones route_allowed_ips 1, netifd no crea ninguna ruta. El handshake se completa, wg show muestra un peer conectado, y el trafico sigue saliendo por tu WAN normal. Es el fallo mas confuso que existe en esto, porque todo parece estar bien.
La razon de que el valor por defecto sea 0 es que las rutas para los allowed IPs de un peer compiten con la tabla de rutas principal del router. netifd no las crea salvo que se lo pidas explicitamente.
persistent_keepalive 25 en el cliente
WireGuard no mantiene conexiones TCP equivalentes: solo manda paquetes cuando hay algo que enviar. Si el trafico de la LAN es intermitente, el router puede quedarse mas de 180 segundos sin enviar nada, y para entonces la sesion del peer ya esta vencida: el servidor remoto descarta las claves de sesion y el tunel necesita renegociar desde cero. El resultado es una conexion que se cae sola cada pocos minutos en los momentos de inactividad.
El persistent_keepalive envia un paquete vacio cada 25 segundos para mantener viva la sesion. En el cliente es obligatorio para este escenario. En el servidor no hace falta, porque el servidor mantiene la sesion abierta hacia el cliente.
Las direcciones de interfaz necesitan mascara
uci add_list network.vpn.addresses="10.8.0.2/24" lleva la mascara porque el guia oficial de OpenWrt es explicito: sin mascara, netifd la interpreta como un /32 y el trafico no encuentra camino hacia el otro extremo del tunel. Si cambias la IP de la interfaz del peer remoto, ajusta la mascara aqui para que coincidan los dos lados.
El AllowedIPs del servidor es otro valor distinto
En el router, allowed_ips 0.0.0.0/0 significa “todo el trafico que salga de aqui va por el tunel”. En el servidor, el AllowedIPs del peer que representa a tu router debe incluir la subred de tu LAN (por ejemplo 192.168.1.0/24), porque el servidor necesita saber que destino tiene el trafico que le llega del tunel. Si lo dejas como la IP del router, el servidor no sabe como responder a tus dispositivos de la LAN.
Mueve la interfaz a la zona wan del firewall
Este paso lo salta mucha gente y es el que hace que el tunel de verdad transporta el trafico de la LAN. OpenWrt organiza el firewall en zonas, y por defecto la zona lan reenvia hacia la zona wan con masquerading activado.
La guia oficial de WireGuard de OpenWrt resuelve esto de forma elegante: agrega la interfaz VPN a la zona wan y ya esta. Como la zona wan es la que tiene option masq 1 y el reenvio lan hacia wan ya existe, todo el trafico de la LAN pasa por el tunel y sale enmascarado con la direccion de la interfaz VPN.
uci rename firewall.@zone[0]="lan"
uci rename firewall.@zone[1]="wan"
uci del_list firewall.wan.network="vpn"
uci add_list firewall.wan.network="vpn"
uci commit firewall
service firewall restart
Las dos lineas del rename no son decorativas: le ponen nombre a las zonas por indice, de modo que los comandos siguientes puedan referirse a firewall.wan sin depender de como las nombraste al configurar el router. Si tu ya tienes las zonas con esos nombres, el rename es idempotente y no cambia nada.
La logica de por que esto funciona: la zona wan tiene option masq 1, o sea que hace NAT de todo lo que sale por ella, y el reenvio lan hacia wan ya existe de serie. Si tu creas una zona nueva para el tunel, tendrias que configurar el masquerading y el reenvio a mano, sin ganarte nada.
Con esto ya tienes el tunel entero: el router negocia con el servidor, la LAN sale por el tunel, y no hay ningun puerto abierto en la WAN. El servidor remoto es quien escucha el 51820 UDP, y tu router se conecta hacia el.
Verifica que el tunel esta de verdad arriba
No declares exito por el hecho de que el comando no dio error. El handshake se puede negociar y aun asi el trafico seguir yendo por la WAN si las rutas no se crearon. La verificacion se hace en tres niveles.
El primero es el estado del propio tunel:
wg show
Lo que quieres ver es un latest handshake reciente, con menos de dos minutos de antiguedad. Si aparece none, el problema esta en las claves o en el endpoint, no en las rutas.
El segundo nivel son las rutas. Aqui es donde se ve si route_allowed_ips quedo bien:
ip route show table all | grep -E "default|10.8.0"
ip rule show
Si no hay una ruta default que apunte a la interfaz vpn, el handshake puede estar perfecto y el trafico igual se escapa por la WAN. Esa es exactamente la firma del fallo de route_allowed_ips.
El tercero es la prueba desde la perspectiva de la LAN, que es la que de verdad importa. Conéctate por WiFi con una laptop y revisa el camino que toma el trafico:
traceroute openwrt.org
traceroute6 openwrt.org
El primer salto deberia ser el tunel, no tu gateway del ISP. Y desde un equipo de la LAN, la comprobacion de la IP publica es la que te dice sin ambiguedad si funciono. OpenWrt no trae curl instalado, pero si trae wget, que es uclient-fetch con otro nombre, y funciona igual para esto:
wget -qO- https://api.ipify.org
Si esa IP es la del servidor VPN y no la de tu ISP, la LAN esta saliendo por el tunel.
Cierra el tema del DNS o se te escapa por un lado
Este es el detalle que se olvida con mas frecuencia, y el que mas incomoda a la gente: puedes tener el tunel perfecto y aun asi las consultas DNS salen por tu ISP. El trafico HTTP va cifrado por el tunel, pero la resolucion de nombres se escapa.
La razon es que en OpenWrt el servidor DNS local es dnsmasq, y por defecto usa los servidores que entrega el DHCP del WAN. Para que el DNS tambien viaje por el tunel, declara los servidores DNS en la propia interfaz VPN:
uci add_list network.vpn.dns="1.1.1.1"
uci add_list network.vpn.dns="1.0.0.1"
uci commit network
service network restart
Con eso, dnsmasq resuelve hacia los servidores DNS del tunel. La forma de comprobarlo es comparar la resolucion con y sin el tunel activo: si el nombre resuelve a la misma IP publica en ambos casos, tu DNS sigue saliendo por la WAN.
Cuando algo falla: la lista de sintomas y causas
Los fallos de WireGuard en un router tienen siempre el mismo puñado de causas. Las ordeno por frecuencia real.
| Sintoma | Causa probable | Como se corrige |
|---|---|---|
wg show con handshake en none |
Claves publicas cruzadas, PSK distinto en los dos extremos o endpoint inaccesible | Revisa que la clave publica del router este en el peer del servidor y viceversa |
| Handshake ok pero la IP publica no cambia | Falta route_allowed_ips 1, el valor por defecto de netifd es 0 |
Agrega uci set network.wgpeer.route_allowed_ips="1" y reinicia la red |
| El tunel se cae solo tras un par de minutos sin trafico | Sin persistent_keepalive en el cliente, la sesion del peer vence a los 180 segundos y el servidor descarta sus claves |
Pon persistent_keepalive 25 en la seccion del peer |
| El handshake funciona pero no hay salida a internet | La interfaz VPN no esta en la zona wan, falta el masquerading | uci add_list firewall.wan.network="vpn" y reinicia el firewall |
| El trafico sale pero las consultas DNS no | dnsmasq sigue usando los DNS del WAN | Declara list dns en la interfaz VPN |
| El ping al otro extremo da timeout | La direccion de la interfaz se declaro sin mascara y netifd laUso como /32 | Escribe la direccion con su mascara, por ejemplo 10.8.0.2/24 |
Para la recoleccion de datos cuando nada de esto te dice nada, el comando que mas informacion da es este, y sale del propio manual oficial de WireGuard para OpenWrt:
service log restart; service network restart; sleep 10
logread -e vpn; netstat -l -n -p | grep -e "^udp\s.*\s-$"
pgrep -f -a wg; wg show; wg showconf vpn
ip address show; ip route show table all
ip rule show; ip -6 rule show; nft list ruleset
uci show network; uci show firewall
Con eso tienes el log del tunel, los procesos, la configuracion que netifd le entrego a WireGuard, las direcciones, las rutas, las reglas y la configuracion persistente. Es el mismo bloque que usa la guia oficial de OpenWrt para depurar un tunel, y con esa informacion se resuelve la practica totalidad de los casos sin adivinar.
WireGuard o Tailscale en el router
La comparacion vale la pena porque es la pregunta que me hacen seguido: si ya existe Tailscale, por que WireGuard. La respuesta corta es que resuelven problemas distintos y la eleccion depende de una sola variable: necesitas que el tunel funcione sin depender de un tercero.
| Criterio | WireGuard nativo | Tailscale |
|---|---|---|
| Servidor de coordinacion | Ninguno, todo es peer a peer | Si, el servidor de control de Tailscale reparte las claves y la lista de relays |
| Si el servidor de control se cae | No aplica, no existe | Las conexiones ya establecidas siguen vivas, pero no se pueden añadir nodos ni rotar claves |
| Configuracion | Claves, PSK y rutas a mano | Login con navegador y listo |
| Depuracion | Tienes que leer wg show y las rutas |
Panel web con el estado de cada nodo |
| Si la conexion directa falla | No hay tunel y hay que corregir el NAT | Recurre a relay DERP, mas lento pero funcional |
| Salida por un servidor remoto concreto | Tu eliges el servidor y su IP de salida | Exit node, con su propia configuracion de salida |
Mi criterio: si el router va a ser la salida de toda tu LAN en produccion y dependes de esa salida para trabajar, WireGuard nativo es la opcion con menos dependencias. Tailscale es mas comodo para el caso de uso personal y para redes con devices moviles que entran y salen. Para el homelab, WireGuard nativo.
Y ojo con el punto que mas se repite mal: Tailscale no necesita abrir puertos en la WAN tampoco, y no es porque el tunel directo sea magico. Lo que hace Tailscale es mantener una conexion saliente permanente contra sus servidores DERP, y si la perforacion de NAT no funciona, el trafico sigue via relay. WireGuard nativo no tiene esa red de seguridad: si no hay camino directo entre el router y el servidor, no hay tunel y hay que corregir el NAT o cambiar de servidor. Esa es la diferencia real, y la que importa cuando el router es la salida de tu LAN.
Lo que este post deja fuera
Dos cosas que dejo deliberadamente fuera y que conviene que sepas si vas mas alla:
El modo servidor en el router. Este post es del router como cliente, con la LAN detras del tunel. Si lo que quieres es exponer un servicio de tu LAN hacia internet, el modelo es el contrario y el problema tecnico es distinto: ahi el servidor remoto tiene que aprender a reenrutar hacia tu subred, y es el escenario que ya cubrimos en los posts de WireGuard como servidor.
El cifrado de disco o el backup del estado. Un tunel WireGuard no protege lo que ya esta en tus discos ni lo que viaja por la LAN antes de entrar al tunel. El trafico entre la laptop y el router viaja en claro sobre la red local. Si necesitas confidencialidad dentro de la casa, WireGuard en el router no es la herramienta; es una capa distinta.
Con eso, lo que te queda es un router que hace de pasarela para toda tu LAN, con salida por la IP que elijas y sin un solo puerto abierto en tu casa. El resto es configuracion.
Preguntas frecuentes
¿Por qué no encuentro el comando wg-quick en mi router?
Porque el paquete wireguard-tools de OpenWrt no lo incluye. Su seccion de instalacion copia solo el binario wg, el watchdog y el helper /lib/netifd/proto/wireguard.sh. En OpenWrt la interfaz la administra netifd y se describe con uci en /etc/config/network, no con archivos .conf ni con wg-quick up. Ese comando pertenece a la instalacion estandar de WireGuard en un servidor Linux, no al firmware del router.
¿El handshake aparece activo pero mi IP pública no cambia, qué hago?
El sintoma clasico de route_allowed_ips ausente. netifd lee esa opcion con valor por defecto 0, asi que declarar allowed_ips 0.0.0.0/0 sin poner route_allowed_ips 1 deja el peer negotiating pero sin rutas creadas. El trafico sigue saliendo por la WAN. Se corrige con uci set network.wgpeer.route_allowed_ips="1" y un reinicio de la red.
¿Puedo usar esto si mi ISP me da CGNAT?
Si, y es precisamente uno de los motivos principales para hacerlo. El router no necesita abrir puertos: es el cliente y abre la conexion UDP saliente hacia el servidor remoto. El unico requisito es que la salida UDP 51820 no este bloqueada por el ISP, condicion que se cumple en la practica. Lo que si exige es que del lado del servidor haya alguien con IP publica que acepte tu router como peer.
¿Cómo separo el tráfico del trabajo del tráfico personal?
Con dos tuneles y dos interfaces WireGuard distintas, cada una con su peer y su tabla de rutas. La via simple es dejar el trafico de la LAN en la ruta por defecto y enviar solo las subredes o el rango de IPs que te interesa por el tunel, ajustando los allowed_ips del peer a ese rango en vez de 0.0.0.0/0. Para separar por dispositivo, en cambio, la regla va en el router: la IP de origen de ese equipo decide por que tunel sale.
¿Cuánto overhead agrega WireGuard al tráfico de mi LAN?
El sobrecoste total por paquete es de 60 bytes en IPv4: 32 bytes del propio protocolo WireGuard (16 de cabecera mas el tag de autenticacion Poly1305 de 16), 8 del encabezado UDP y 20 del encabezado IP exterior. En IPv6 son 80 bytes, porque el encabezado IP exterior pasa de 20 a 40 bytes. Sobre un paquete de 1500 bytes el costo real ronda el 4%. El impacto que si se nota es en el MTU: el paquete util se reduce a unos 1440 bytes, y por eso la zona wan trae option mtu_fix 1 para aplicar clamping de MSS y evitar que las conexiones grandes se queden colgadas.
Lee también
- Guía definitiva: monta tu servidor WireGuard en Linux paso a paso
- Configura Tailscale en Linux: mesh VPN para sysadmins
- PiVPN detrás de CGNAT: 3 métodos reales cuando tu ISP no te da IP pública
- Exponer servicios del home lab a internet: seis vías comparadas
- Acceso remoto seguro con WireGuard en OPNsense
