SSD Nodes Learn Hosting plans →
Guías Matt ConnorPor Matt Connor · Actualizado 2026-08-27

Cómo funciona WireGuard: enrutamiento con claves

AllowedIPs actúa como tabla de rutas y lista de acceso. Entienda el enrutamiento criptográfico, el handshake Noise y la rotación de claves en wg0.conf.

Cómo funciona WireGuard, en una idea

WireGuard vincula cada paquete a una clave pública. El mecanismo se denomina enrutamiento mediante claves criptográficas y constituye todo el diseño: la línea AllowedIPs situada junto a un peer es la tabla de enrutamiento para los paquetes que salen de su máquina y la lista de control de acceso para los paquetes que llegan desde ese peer. Un ajuste cumple dos funciones. Interprete AllowedIPs de esa forma y todos los archivos de configuración de WireGuard resultarán comprensibles.

No existe una tabla de sesiones indexada por dirección IP ni una base de datos de usuarios. Un peer es una clave pública junto con el conjunto de direcciones que esa clave puede usar. El handshake y los temporizadores mantienen válida esa asociación mientras cambia la red subyacente. Si quiere tener un túnel operativo antes de estudiar la teoría, créelo con una VPN WireGuard autohospedada en su propio VPS y vuelva aquí cuando una línea de configuración le resulte inesperada.

AllowedIPs es una tabla de enrutamiento y una lista de acceso

Comience por la dirección saliente. El kernel enruta un paquete al dispositivo wg0 de la forma habitual, mediante la tabla de enrutamiento principal. Después, WireGuard compara la dirección de destino del paquete con una tabla que contiene todos los prefijos permitidos de cada peer, empezando por el prefijo más específico. La coincidencia identifica un peer, que a su vez identifica una clave pública, una clave de sesión y un endpoint UDP. El paquete se cifra para ese peer y se envía allí.

Si ningún AllowedIPs de un peer cubre el destino, no se envía nada porque no existe ninguna clave con la que cifrarlo.

ping: sendmsg: Required key not available

Ese error sólo significa una cosa: la dirección que intentó alcanzar no figura en ningún peer. Otro error, ping: sendmsg: Destination address required, significa que sí se encontró un peer, pero WireGuard no tiene ningún endpoint para él porque no se configuró ninguno y todavía no se ha aprendido ninguno.

Ahora, la dirección entrante. Un paquete UDP llega al puerto de escucha. WireGuard obtiene la sesión a partir del índice del receptor incluido en la cabecera, comprueba el contador mediante una ventana deslizante contra repeticiones y, después, descifra y autentica la carga útil. Sólo entonces lee el paquete interno, y la dirección de origen de ese paquete debe estar dentro del AllowedIPs del peer emisor. Si no es así, el paquete se descarta. Con la depuración dinámica habilitada, el kernel imprime el motivo en una línea como esta:

wg0: Packet has unallowed src IP (10.8.0.9) from peer 2 (203.0.113.10:51820)

Por eso un peer en el servidor recibe un /32. Un peer configurado con AllowedIPs = 10.8.0.2/32 puede enviar paquetes desde 10.8.0.2 y desde ninguna otra dirección. Escriba 0.0.0.0/0 en su lugar y ese único cliente podrá inyectar paquetes que indiquen cualquier dirección de origen dentro de su túnel, incluida la de otro cliente.

Los prefijos solapados se resuelven según su especificidad, ya que la búsqueda utiliza la coincidencia del prefijo más largo. Los prefijos idénticos en dos peers se comportan de otra forma: la entrada pasa al peer que se configuró en último lugar, y el primer peer deja de recibir ese tráfico sin que se imprima ningún error. wg show wg0 allowed-ips muestra la tabla que está realmente en el kernel. Esa tabla es la que cuenta cuando el archivo del disco y el estado en ejecución han dejado de coincidir.

Lectura de un archivo de configuración teniendo en cuenta el enrutamiento mediante claves criptográficas

El lado del servidor:

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <server private key>

[Peer]
PublicKey = <laptop public key>
AllowedIPs = 10.8.0.2/32

El lado del cliente:

[Interface]
Address = 10.8.0.2/32
PrivateKey = <laptop private key>

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

La misma palabra clave tiene un efecto opuesto en cada lado. En el cliente indica «enviar todos los destinos a este peer». En el servidor indica «aceptar sólo esta dirección de este peer». La asimetría está en los valores, no en ningún rol.

La mitad de estas claves no pertenece al protocolo. Address, DNS, MTU, PostUp y SaveConfig pertenecen a wg-quick, el script de shell que activa la interfaz. El kernel nunca las ve. wg-quick strip wg0 muestra la configuración reducida que carga realmente la herramienta wg. Es la forma más rápida de comprobar esta separación.

Qué hace realmente el handshake

El handshake de WireGuard es Noise_IKpsk2, del Noise Protocol Framework. La IK es la parte útil para un sysadmin: la clave pública estática del responder ya es conocida por el initiator, porque es la PublicKey de tu bloque [Peer], y el initiator envía su propia clave pública estática dentro del primer mensaje, cifrada. Por tanto, no hay intercambio de certificados ni un intercambio de identidad de ida y vuelta. Un observador pasivo no puede saber qué clave está realizando la llamada, a menos que tenga la clave privada del responder.

El coste es un viaje de ida y vuelta. El mensaje de inicio tiene 148 bytes, la respuesta tiene 92 bytes y los datos empiezan a fluir inmediatamente después. Cada extremo genera un nuevo par de claves efímeras Curve25519 para cada handshake, y las claves de sesión se obtienen de una cadena de resultados Diffie-Hellman que combina las claves estáticas y efímeras. Después se descartan las claves privadas efímeras, lo que proporciona secreto hacia adelante: alguien que registre tu tráfico hoy y robe la clave privada del servidor el año próximo seguirá sin poder leer lo que registró.

El inicio de un handshake incluye una marca de tiempo TAI64N, y cada peer recuerda la marca de tiempo más grande que ha recibido del otro, por lo que se rechaza un inicio repetido. Los paquetes de datos incluyen un contador de 64 bits que se usa como nonce, y el receptor mantiene una ventana deslizante de contadores vistos recientemente. Así, las repeticiones y un reordenamiento importante se gestionan sin mantener un estado de conexión al estilo de TCP.

Las claves de sesión no duran mucho y los temporizadores están compilados, no se pueden configurar.

ChartWireGuard protocol timers, in seconds
The data behind this chart
[
  {
    "label": "REKEY_TIMEOUT",
    "seconds": 5,
    "notes": "resend a handshake initiation that got no answer"
  },
  {
    "label": "KEEPALIVE_TIMEOUT",
    "seconds": 10,
    "notes": "send a keepalive after receiving data and sending none back"
  },
  {
    "label": "REKEY_ATTEMPT_TIME",
    "seconds": 90,
    "notes": "give up on the handshake and report the peer as down"
  },
  {
    "label": "REKEY_AFTER_TIME",
    "seconds": 120,
    "notes": "sender begins a fresh handshake for a new session key"
  },
  {
    "label": "REJECT_AFTER_TIME",
    "seconds": 180,
    "notes": "the old session key is refused and traffic stops"
  }
]

Estos son valores constantes de la especificación del protocolo, no mediciones. Los 5 controlan todo el ciclo de vida de la sesión. Después de 120 segundos de uso, el emisor inicia un nuevo handshake. Después de 180 segundos, la clave antigua se rechaza directamente y el tráfico se detiene hasta que se completa un nuevo handshake. Un inicio que no recibe respuesta se reenvía cada 5 segundos y se abandona después de 90 segundos. Por eso wg show muestra latest handshake como una antigüedad relativa y por eso un túnel activo y saludable mantiene esa antigüedad pequeña. Si la antigüedad aumenta mientras envías tráfico activamente, significa que los handshakes están fallando, no que el túnel esté inactivo.

Por qué un peer no tiene un rol de cliente ni de servidor

Ambos extremos ejecutan el mismo código y usan el mismo formato de configuración. No existe un modo de servidor. La asimetría que se observa procede de Endpoint, y Endpoint es opcional.

Un peer con un endpoint configurado puede iniciar un handshake. Un peer sin endpoint espera y después aprende la dirección y el puerto del otro extremo a partir del primer paquete que se autentica correctamente. Ese endpoint aprendido se almacena y se actualiza cada vez que llega un paquete válido desde una dirección nueva. Así funciona el roaming: un portátil que cambia de Wi-Fi a una red móvil mantiene el mismo túnel, porque una sesión se identifica mediante la clave y el índice, no mediante la dirección IP. No se restablece ninguna conexión, porque nunca hubo una conexión en el sentido de TCP.

El mismo mecanismo genera un dato importante: el peer con la dirección pública siempre conserva la última IP pública conocida del otro extremo, y wg show la muestra.

Primitivas fijas, sin negociación

WireGuard no tiene una lista de conjuntos de cifrado. Usa ChaCha20-Poly1305 para el cifrado autenticado, Curve25519 para el acuerdo de claves, BLAKE2s para el hash y HKDF para la derivación de claves. Todas las implementaciones usan estas primitivas. Por tanto, no hay una fase de negociación que analizar ni una vía de degradación a una opción más débil. El coste es real: si una de estas primitivas se rompe, la solución es una nueva versión de todo el protocolo y una actualización en ambos extremos, no un cambio de configuración. Esta única decisión elimina la mayor parte del código y de los modos de fallo que incorpora un túnel basado en TLS. En eso se resume principalmente la comparación de WireGuard frente a OpenVPN.

Por qué el puerto no responde a un escáner

Cada mensaje de handshake contiene un campo llamado mac1. Es un código de autenticación de mensajes (MAC, por sus siglas en inglés) calculado sobre el mensaje con una clave derivada de la clave pública estática del responder. Un emisor que no conoce esa clave pública no puede generar un mac1 válido, por lo que el receptor descarta ese paquete sin responder. No envía ningún error, reset ni mensaje ICMP.

El resultado visible es un escaneo UDP que no recibe ninguna respuesta.

sudo nmap -sU -p 51820 vpn.example.com

nmap informa open|filtered, que es la misma respuesta que proporciona para un puerto cuyos paquetes un firewall descarta silenciosamente. El puerto se comporta igual tanto si WireGuard está escuchando como si no, al menos para cualquiera que no tenga ya su clave pública.

Un segundo campo, mac2, gestiona la presión de los ataques de denegación de servicio. Cuando el receptor está bajo carga, responde a una iniciación válida con una respuesta cookie de 64 bytes vinculada a la dirección de origen del emisor. Se niega a realizar operaciones costosas de clave pública hasta que el emisor devuelve esa cookie. Así demuestra que la dirección de origen es real antes de consumir CPU y sólo se activa bajo carga.

Por qué 0.0.0.0/0 convierte un peer en la ruta predeterminada

Como AllowedIPs es la tabla de enrutamiento, AllowedIPs = 0.0.0.0/0, ::/0 reclama todos los destinos para ese peer. Esa es toda la configuración del túnel completo.

El enrutamiento que hace que funcione es más interesante que la línea en sí. Una ruta predeterminada normal a través de wg0 entraría en un bucle, porque el paquete UDP cifrado que transporta el tráfico también tiene que salir de la máquina y coincidiría con su propia ruta predeterminada. wg-quick evita esto mediante el enrutamiento basado en políticas. Marca los paquetes salientes propios de WireGuard con un fwmark, coloca la ruta predeterminada del túnel en una tabla de enrutamiento independiente y añade reglas para que sólo el tráfico sin marca llegue a ella. Ejecute ip rule show para ver el resultado:

32764:	from all lookup main suppress_prefixlength 0
32765:	not from all fwmark 0xca6c lookup 51820
32766:	from all lookup main

0xca6c es 51820 en hexadecimal, y 51820 también es el número de la tabla. La regla suppress_prefixlength 0 hace que la tabla principal omita su propia ruta predeterminada. De este modo, las rutas específicas, como la de la subred local, siguen teniendo prioridad y todo lo demás pasa a la tabla del túnel. Un túnel dividido no necesita nada de esto: una lista más específica, como AllowedIPs = 10.8.0.0/24, 10.20.0.0/16, se convierte en rutas normales de la tabla principal.

Un túnel completo no resuelve por sí solo la resolución de nombres. El resolvedor que el cliente aprendió de la red local suele seguir configurado, y su ruta es más específica. Es una tarea independiente, que se explica en DNS que se filtra fuera de un túnel de WireGuard.

Para qué sirve realmente PersistentKeepalive

WireGuard no envía nada cuando no hay tráfico. No hay latidos, renovación de sesión ni ningún otro paquete en la red. Ese silencio ayuda a ahorrar batería y también al caso del escáner descrito arriba, pero impide una configuración concreta.

Un peer detrás de NAT (traducción de direcciones de red) o de un firewall con estado sólo es accesible desde el exterior mientras exista una asignación en ese dispositivo. Esa asignación se crea mediante un paquete saliente. Los tiempos de vida habituales de las asignaciones UDP empiezan en unos 30 segundos. Cuando la asignación caduca, el dispositivo intermedio descarta los paquetes procedentes del lado público y el túnel parece inactivo hasta que el peer detrás de NAT envía algo. PersistentKeepalive = 25 envía un paquete autenticado vacío cada 25 segundos. Ese intervalo es inferior al tiempo de vida habitual más corto, por lo que la asignación permanece abierta.

Configure este parámetro en el peer detrás de NAT. Un servidor con una dirección pública y un puerto UDP abierto no lo necesita. Configurarlo allí sólo añade tráfico. No lo confunda con el keepalive automático, que se ejecuta 10 segundos después de que un peer recibe datos y no tiene nada propio que enviar. Ese mecanismo está siempre activo y no se puede configurar.

Enrutar la LAN a través del túnel no es una función de WireGuard

Supongamos que el peer B está en una red doméstica 192.168.50.0/24 y que el peer A debe acceder a ella. Dos sistemas independientes tienen que estar configurados de forma coherente, y sólo uno de ellos es WireGuard.

La parte de WireGuard consiste en añadir 192.168.50.0/24 a AllowedIPs de B en A. Esto hace que A enrute el prefijo hacia B y que acepte desde B paquetes con esas direcciones de origen. Sin esta configuración, el enrutamiento mediante claves criptográficas no tiene una clave para el destino ni permiso para el origen.

La parte del kernel consiste en que, en B, net.ipv4.ip_forward debe ser 1. De lo contrario, el kernel descarta todos los paquetes descifrados que no estén destinados al propio B. La cadena de reenvío del firewall de B debe permitir el tráfico. Los hosts de la LAN necesitan una ruta de retorno hacia 10.8.0.0/24, o B debe aplicar NAT de origen para que las respuestas vuelvan a través de B.

El trabajo de WireGuard termina cuando entrega el paquete descifrado al kernel. Todo lo que ocurre después corresponde al enrutamiento y filtrado normal de Linux. Por eso este fallo aparece en los contadores de nft list ruleset o en ip -s link show wg0, y no en wg show. Si prefiere administrar los peers mediante una interfaz web, ejecutar wg-easy en Docker genera las entradas de los peers, aunque las reglas de reenvío siguen perteneciendo al host. La misma separación se mantiene cuando una capa de coordinación distribuye el prefijo por usted: anunciar una red privada desde un VPS con un router de subred de Tailscale sustituye la edición manual de AllowedIPs en cada peer, pero el sysctl de reenvío y las reglas del firewall del propio router siguen siendo responsabilidad suya.

Por qué WireGuard funciona en el kernel

wg0 es un controlador de dispositivo de red. Los paquetes llegan a él mediante la pila de enrutamiento normal, se cifran en el contexto de softirq y salen a través de un socket UDP sin pasar por userspace. De ahí procede el rendimiento, y por eso el módulo se mantiene en unas cuatro mil líneas de código: es lo bastante pequeño para revisarlo y para integrarlo en mainline Linux 5.6 en marzo de 2020. Ubuntu 24.04 y Debian 13 lo incluyen, por lo que sólo falta el paquete wireguard-tools.

Al ser una interfaz normal, tiene consecuencias prácticas. tcpdump -ni wg0 muestra los paquetes internos en texto plano, mientras que tcpdump -ni eth0 udp port 51820 muestra los paquetes externos cifrados. Compararlos permite identificar de inmediato qué dirección está fallando. netfilter y el control de tráfico tratan wg0 como cualquier otro enlace. Cuando el módulo del kernel no está disponible, por ejemplo en una virtualización de contenedores que comparte el kernel del host, wireguard-go implementa el mismo protocolo en userspace sobre un dispositivo TUN, con un coste real de rendimiento porque cada paquete cruza dos veces el límite entre el kernel y userspace.

Lo que WireGuard no protege

El modelo de amenazas es deliberadamente limitado, y un protocolo tan discreto puede generar falsas expectativas. Conviene dejarlo claro.

  • No oculta que usa WireGuard. Los mensajes del handshake tienen tamaños fijos, el primer byte indica el tipo de mensaje y el transporte es UDP. La inspección profunda de paquetes lo reconoce fácilmente, y una red que bloquea las VPN puede bloquearlo. La ofuscación se omitió de forma deliberada.
  • No oculta el volumen ni el momento del tráfico. Los datos sólo se rellenan hasta un límite de 16 bytes, por lo que un observador sigue viendo cuándo envía datos y aproximadamente cuánto.
  • Conserva el último endpoint conocido. El peer con la dirección pública almacena la IP pública actual del otro extremo, y wg show la muestra. Junto con una dirección del túnel fija en la configuración, esto forma un identificador estable que sigue al usuario entre redes. En su propio VPS esto no supone un problema. También por eso los servicios comerciales añaden una capa sobre el protocolo.
  • Autentica una clave, no una persona. Quien posee el archivo de clave privada es el peer. Mantenga /etc/wireguard con el modo 700 y los archivos de clave con el modo 600.
  • No existe una lista de revocación ni una fecha de caducidad. El acceso termina cuando elimina la entrada del peer de todos los servidores que la contienen, y las claves estáticas siguen activas hasta que las elimina.

Nada de esto hace que WireGuard sea débil. Lo hace pequeño, y ese es el objetivo: autentica y cifra, y deja la gestión de identidades y la asignación de direcciones en manos de lo que se construya sobre él. Una capa de coordinación del tipo descrito en WireGuard comparado con Tailscale existe precisamente para cubrir esa carencia y utiliza el mismo plano de datos que acaba de leer. Una vez instalada esa capa, la siguiente decisión es quién puede acceder a un servicio que se ejecuta dentro del túnel. Eso es lo que resuelve la elección entre Tailscale serve y funnel para un solo puerto.

FAQ

¿Qué es el enrutamiento mediante claves criptográficas en WireGuard?

El enrutamiento mediante claves criptográficas es la regla que vincula cada paquete a una clave pública. Cada entrada de peer contiene una lista de prefijos en AllowedIPs. Para el tráfico saliente, WireGuard selecciona el peer comparando el destino del paquete con la lista de cada peer, empezando por el prefijo más específico. Por tanto, la lista funciona como una tabla de enrutamiento. Para el tráfico entrante, una vez descifrado y autenticado el paquete, su dirección de origen interna debe estar incluida en la lista de ese mismo peer. De lo contrario, el paquete se descarta. Así, la lista funciona como una lista de control de acceso. WireGuard no tiene una configuración de enrutamiento independiente ni un firewall interno independiente, porque esa lista cumple ambas funciones.

¿Necesito PersistentKeepalive en ambos peers?

No. Configúrelo en el lado que está detrás de NAT (traducción de direcciones de red) o de un firewall con estado. Normalmente, ese lado es el cliente. WireGuard no envía nada mientras está inactivo. Por eso, la asignación que permite al otro extremo llegar a ese peer caduca, a menudo en menos de un minuto, y el túnel parece inactivo en una dirección. PersistentKeepalive = 25 envía un paquete autenticado vacío cada 25 segundos y mantiene abierta la asignación. Un peer con una dirección pública y un puerto UDP abierto no lo necesita.

¿Por qué ping a través del túnel muestra "Required key not available"?

Porque la dirección de destino no está incluida en el AllowedIPs de ningún peer. El enrutamiento mediante claves criptográficas no encontró una clave con la que cifrar el paquete y el kernel rechazó su envío. Ejecute wg show wg0 allowed-ips y compare esa salida con la dirección a la que está enviando ping. El error similar Destination address required indica otro problema: se encontró un peer coincidente, pero WireGuard no tiene un endpoint para él porque no se configuró ninguno y todavía no ha llegado ningún paquete autenticado de ese peer.

¿Puede un firewall detectar y bloquear WireGuard?

Sí. WireGuard autentica y cifra el tráfico, pero no intenta ocultar que es WireGuard. Los mensajes de handshake tienen un tamaño fijo de 148 y 92 bytes. El primer byte de cada mensaje identifica su tipo y el transporte usa UDP. Por tanto, la inspección profunda de paquetes identifica el protocolo sin dificultad. Las redes que bloquean UDP o que identifican protocolos mediante huellas digitales lo detendrán. Ocultar el túnel requiere encapsularlo en otro protocolo o herramienta. Esto es independiente de la configuración de WireGuard.