Volver a los write-ups

El túnel WireGuard que conectaba, pero no dejaba pasar tráfico

Levantar el handshake fue lo fácil. Lo difícil fue encontrar quién descartaba los paquetes tres capas más abajo de donde parecía.

El escenario

La instancia EC2 en AWS tiene IP pública y hace de servidor WireGuard. Mi equipo en casa está detrás de CGNAT, así que no puede recibir conexiones: es siempre el cliente y marca hacia afuera por UDP 51820. Al otro lado del túnel, las máquinas vulnerables corren en libvirt, cada proyecto en su propia red NAT aislada.

El síntoma

El túnel establecía el handshake sin problemas, pero las conexiones nuevas desde AWS hacia la VM nunca llegaban. No había errores visibles, solo silencio.

Las pistas falsas

Investigué primero UFW y Docker, que eran los sospechosos naturales. Ninguno tenía relación con el problema.

La causa

libvirt aplica su propio filtrado con nftables en las redes de tipo NAT (tabla libvirt_network, cadena guest_input). Por defecto rechaza cualquier conexión nueva entrante y solo deja pasar el tráfico de retorno de conexiones ya establecidas. Eso descartaba en silencio todo lo que llegaba por el túnel.

La solución

Un hook de red de libvirt (/etc/libvirt/hooks/network) que inserta una regla de excepción en nftables cada vez que arranca la red de destino. La regla usa oifname, que identifica la interfaz por nombre y se mantiene entre reinicios, y no oif, que usa el índice numérico y se rompe en el siguiente reinicio.

Lo que me llevo

  • Diagnosticar con evidencia, con tcpdump y los contadores de iptables ynft, y no por ensayo y error.
  • Todo lo que no está en el código de infraestructura se pierde cuando se recrea el entorno.
  • La causa real puede estar varias capas más abajo de donde aparece el síntoma.

El detalle completo está en elrepositorio de CloudLab.