Los invitados de la red libvirt predeterminada resuelven nombres perfectamente hasta que sube la interfaz WireGuard, y entonces cada consulta se atasca en el mismo punto. dnsmasq sigue escuchando en 192.168.122.1:53, el invitado sigue teniendo esa dirección como resolutor, y la consulta sigue llegando. Lo que ha cambiado es que la propia consulta ascendente del anfitrión, o la respuesta a ella, ahora la descarta una regla que se evalúa antes que cualquier cadena de filtrado que se te ocurriría editar. La salida es una marca aplicada con suficiente antelación, en una conexión que la respuesta hereda.

Los invitados pierden el DNS en el momento en que sube el túnel

Confirma la forma antes de cambiar nada. Baja el túnel, ejecuta dig @192.168.122.1 example.com desde un invitado y míralo responder. Sube el túnel, repite y míralo agotar el tiempo. Ese par de resultados descarta una red libvirt rota, una dirección de resolutor incorrecta y un dnsmasq muerto en un solo paso.

Luego mira el lado del anfitrión. Si dnsmasq registra la consulta y su reenvío ascendente, el paquete llegó y el fallo está en la salida. Si dnsmasq no registra nada, la consulta del invitado se está descartando en la entrada y la excepción pertenece a un hook distinto del que marca este artículo.

Por qué una regla accept en una cadena posterior nunca se dispara

Un cortafuegos VPN basado en marcas decide mirando la marca del paquete o la marca de la conexión, no tu dirección de origen. Todo lo que llega a la interfaz física sin la marca esperada se rechaza, y ese rechazo ocurre en el conjunto de reglas que posee la prueba de marca. Una línea ip saddr 192.168.122.0/24 accept añadida a alguna cadena posterior simplemente nunca se consulta para ese paquete, por eso la regla obvia parece correcta y no cambia nada.

Ampliarla hasta que algo funcione es la segunda trampa. Aceptar toda la subred libvirt en la ruta de entrada del anfitrión abre todos los servicios del anfitrión a los invitados, cuando la necesidad real es un solo puerto.

El mecanismo que hace posible una excepción estrecha es el seguimiento de conexiones. Cuando estableces ct mark en un paquete, el valor se guarda en la entrada de conntrack y no solo en el paquete, así que cada paquete de esa conexión lo lleva después, incluida la respuesta del anfitrión de vuelta al invitado. Ese es todo el truco: marca la petición una vez y la ruta de vuelta ya está marcada.

Marca la consulta antes de que la tabla VPN la vea

Pon la excepción en su propia tabla para que un lector posterior pueda encontrarla sin analizar las reglas VPN:

table inet allowedLocal {
  chain guest_dns {
    type filter hook input priority mangle; policy accept;
    ip saddr 192.168.122.0/24 meta l4proto { tcp, udp } \
      th dport 53 ct mark set 0x00000f41
  }
}

priority mangle es negativo, lo que coloca esta cadena delante de las cadenas de filtrado ordinarias que el paquete VPN instala con prioridad cero. El orden de los hooks es lo que hace efectiva la regla; la misma regla en una cadena que se ordena después de la cadena VPN es decoración.

El número de marca en sí no es portable. Toma el valor que las reglas VPN instaladas aceptan para su propio tráfico, léelo del conjunto de reglas vivo y úsalo. Una marca incorrecta produce una regla que se carga limpiamente, coincide con cada consulta y no admite nada.

Mantén el agujero del ancho del puerto 53

Tal como está escrito, esto permite DNS desde la subred libvirt al anfitrión por TCP o UDP al puerto 53 y nada más. No deja que los invitados lleguen a internet fuera del túnel, y no deja que el anfitrión abra conexiones hacia los invitados. Si un invitado necesita más adelante otro servicio del anfitrión, añade una regla separada que nombre ese puerto de destino en lugar de relajar esta.

Sé honesto sobre lo que estás intercambiando. Un invitado que puede alcanzar un resolutor también puede tunelizar datos arbitrarios a través de consultas DNS, y esta excepción es un hueco deliberado en la frontera VPN, no una afirmación de que la red local sea de confianza. Restringir el origen a 192.168.122.0/24 mantiene el hueco lejos de cualquier otra subred local, y contar consultas contra ese origen es barato si la amenaza te importa.

Haz que sobreviva a un reinicio y demuestra ambas mitades

Una regla escrita en un indicador de shell desaparece en el próximo arranque, y una regla cargada después de que la interfaz VPN ya pase tráfico pierde la carrera en la primera conexión. Pon la tabla en la configuración persistente de nftables del anfitrión, o en una unidad ordenada antes del servicio VPN, y comprueba el orden en lugar de suponerlo.

La verificación necesita tres respuestas separadas. Confirma que la cadena está cargada y ordenada primero, confirma que la entrada de conntrack muestra la marca en ambas direcciones y confirma que una búsqueda del invitado devuelve una dirección. Luego confirma la otra mitad: el tráfico web ordinario del invitado a un anfitrión público sigue fallando mientras el túnel está caído o bloqueando. Si el DNS funciona y todo lo demás se filtra, tu regla es más amplia que la de arriba.

Si las búsquedas siguen fallando después de que la marca esté en su sitio, resiste el impulso de ampliar el origen. Comprueba hacia dónde reenvía dnsmasq, si el resolutor del invitado apunta a 192.168.122.1 o a una dirección pública que alguien tecleó, y si la consulta llega siquiera al anfitrión. Marcar admite el paquete y nada más, así que un mal ascendente o una red virtual rota siguen rotos por muchas reglas que añadas.

Artículos relacionados