Problema

En entornos donde WireGuard se usa como puente entre una máquina cliente y un servidor de retransmisión, es frecuente encontrarse con que el cliente envía paquetes pero el servidor nunca los contabiliza como tráfico recibido. El túnel parece “up”, los handshakes aparecen en el cliente, pero en el servidor la estadística de transferencia permanece en 0 B y la conexión nunca se establece. El síntoma típico es:

  • wg show muestra la interfaz activa en ambos extremos.
  • tcpdump confirma que los paquetes UDP llegan al puerto 51820 del servidor.
  • No hay handshakes visibles en el servidor para el peer problemático.
  • El tráfico de retorno (respuesta del servidor al cliente) tampoco llega.

Este comportamiento se traduce en una VPN que solo permite tráfico en una dirección o, peor aún, que parece estar operativa pero no transporta datos. El problema puede aparecer en despliegues con máquinas virtuales, entornos de nube, o redes con NAT y reglas de firewall complejas.

Causa

Los fallos de tráfico unidireccional en WireGuard suelen deberse a una combinación de configuraciones de red y firewall. Las causas más habituales son:

  1. Rutas y AllowedIPs mal alineadas

    • Si el cliente declara como AllowedIPs una subred que no coincide con la ruta que el servidor tiene hacia esa subred, el servidor descartará los paquetes.
    • Lo mismo ocurre al revés: el servidor necesita una ruta de regreso que incluya la IP del cliente o la subred origen.
  2. Reglas de iptables que bloquean el tráfico de retorno

    • La cadena FORWARD o la política por defecto (DROP) pueden impedir que los paquetes salgan por la interfaz wg0.
    • La regla de MASQUERADE aplicada al origen equivocado (por ejemplo, a la subred del túnel en vez de la subred interna) genera respuestas con direcciones que no coinciden con la tabla de peers.
  3. Desactivación del reenvío IPv4

    • net.ipv4.ip_forward=0 impide que el kernel reenvíe paquetes entre interfaces, dejando los paquetes del cliente sin salida.
  4. MTU y fragmentación

    • Un MTU demasiado bajo en la interfaz virtual o en la capa subyacente (por ejemplo, en una red VMware) provoca que los paquetes se fragmenten y sean descartados por el kernel de WireGuard.
  5. Asimetría de rutas (asymmetric routing)

    • Cuando el cliente envía a través del túnel pero la respuesta vuelve por una ruta diferente (por ejemplo, directamente a Internet), el servidor no reconoce la sesión y la descarta.
  6. Problemas de NAT y conntrack

    • El estado de la conexión puede quedar “ESTABLISHED” en una dirección y nunca completarse en la otra, especialmente si se usan reglas de NAT en la cadena POSTROUTING sin la correspondiente regla de PREROUTING para el tráfico entrante.
  7. Entorno de virtualización (VMware, VirtualBox, etc.)

    • Los adaptadores “promiscuous mode” desactivados o la falta de soporte para tráfico UDP de alta velocidad pueden hacer que los paquetes lleguen al hipervisor pero nunca se entreguen a la VM.

Solución

Una estrategia estructurada permite aislar rápidamente la causa y aplicar la corrección adecuada.

1. Verificar la configuración de peers y rutas

  • En ambos extremos, revisa que AllowedIPs incluya exactamente la subred que debe atravesar el túnel.
  • Añade rutas estáticas si la tabla de enrutamiento del servidor no contiene una ruta hacia la subred del cliente.
# En el servidor
ip route add 10.10.0.0/24 dev wg0

# En el cliente
ip route add 192.168.100.0/24 dev wg0

2. Asegurar el reenvío IPv4 y IPv6

sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

Persistir en /etc/sysctl.d/99-wireguard.conf:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

3. Normalizar las reglas de iptables

Una configuración mínima que funciona en la mayoría de los casos:

# Borrar reglas existentes (solo en entornos de prueba)
iptables -F
iptables -t nat -F
iptables -X

# Permitir tráfico en wg0
iptables -A INPUT -i wg0 -j ACCEPT
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT

# NAT para la subred interna que debe salir por eth0
iptables -t nat -A POSTROUTING -s 10.10.0.0/24 -o eth0 -j MASQUERADE

Si el servidor también actúa como gateway para otras subredes, añade reglas de POSTROUTING específicas para cada rango.

4. Comprobar MTU

WireGuard recomienda un MTU de 1420 bytes en la mayoría de los enlaces UDP. Ajusta la interfaz si la capa subyacente tiene un MTU menor (por ejemplo, 1500 en Ethernet pero 1492 en PPPoE).

ip link set dev wg0 mtu 1420

Luego verifica con ping -M do -s 1380 <peer> que los paquetes no se fragmentan.

5. Detectar asimetría de rutas

Ejecuta traceroute desde el cliente hacia una IP del servidor y viceversa. Si la respuesta sigue un camino distinto al túnel, agrega una ruta estática o modifica la tabla de rutas del hipervisor para forzar el retorno por wg0.

6. Revisar la configuración de la VM

  • Habilita “Promiscuous Mode” y “Forged Transmits” en el adaptador virtual.
  • Asegúrate de que el adaptador está en modo “Bridged” si necesita exponer la IP pública directamente.
  • Verifica que no haya políticas de seguridad del host que bloqueen el puerto UDP 51820.

7. Reiniciar y observar los logs

Después de aplicar los cambios, reinicia la interfaz:

systemctl restart wg-quick@wg0

Observa los logs de WireGuard:

journalctl -u wg-quick@wg0 -f

Los mensajes “handshake completed” deben aparecer en ambos extremos.

Cuándo aplicar esta solución

Utiliza este procedimiento cuando:

  • wg show indica que la interfaz está up pero transfer muestra 0 B en uno de los peers.
  • tcpdump confirma la llegada de paquetes UDP al puerto 51820 del servidor.
  • No hay handshakes registrados en el servidor para el peer problemático.
  • El entorno incluye NAT, firewalls o máquinas virtuales.

No es necesario si:

  • El túnel muestra tráfico bidireccional sin problemas.
  • Los peers están en la misma red física y no hay reglas de firewall personalizadas.

Código

# Habilitar reenvío IPv4/IPv6
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1

# Guardar de forma persistente
cat <<EOF > /etc/sysctl.d/99-wireguard.conf
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
EOF

# Configuración mínima de iptables
iptables -F
iptables -t nat -F
iptables -A INPUT -i wg0 -j ACCEPT
iptables -A FORWARD -i wg0 -j ACCEPT
iptables -A FORWARD -o wg0 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.10.0.0/24 -o eth0 -j MASQUERADE

# Ajustar MTU de la interfaz WireGuard
ip link set dev wg0 mtu 1420

# Reiniciar la interfaz
systemctl restart wg-quick@wg0

Verificación

  1. Handshake

    wg show wg0
    

    Busca latest handshake con una marca de tiempo reciente en ambos peers.

  2. Transferencia
    Ejecuta ping desde el cliente a una IP dentro de la subred del servidor y verifica que transfer aumenta.

  3. tcpdump

    tcpdump -i wg0 udp port 51820 -vv
    

    Confirma que los paquetes fluyen en ambas direcciones.

  4. Ruta

    ip route get <IP_del_peer>
    

    La salida debe indicar dev wg0.

  5. MTU

    ping -M do -s 1380 <peer_ip>
    

    No debe haber fragmentación.

Notas adicionales

  • En entornos con varios peers, revisa que cada PublicKey sea único y que no haya duplicados en la tabla de peers del servidor.
  • Si utilizas iptables con políticas DROP por defecto, recuerda añadir reglas explícitas para ESTABLISHED,RELATED.
  • Cuando el servidor está detrás de un balanceador de carga, asegúrate de que el puerto UDP 51820 está abierto y que el balanceador preserve la dirección IP origen.
  • En caso de usar firewalld o nftables, traduce las reglas anteriores al backend correspondiente; la lógica de aceptar wg0 y aplicar MASQUERADE sigue siendo la misma.

Con estos pasos deberías poder transformar un túnel WireGuard que solo envía paquetes en una conexión completamente funcional, capaz de transportar tráfico en ambas direcciones sin pérdidas.