WireGuard DNS DNAT: mantén operativa la ruta de respuesta
DNAT reescribe el destino, no el origen. Decide cómo puede responder el resolutor superior antes de añadir la regla y mantén acotada cada coincidencia.
Apuntar la consulta DNS de un cliente de WireGuard a otro resolutor parece una sola regla y se comporta como tres decisiones. Hay que reescribir el destino, hay que reenviar el paquete y la respuesta tiene que encontrar el camino de vuelta a través del estado de traducción que creó la puerta de enlace. Si te saltas la tercera, la consulta sale limpia mientras el cliente espera para siempre.
Tomemos el ejemplo de clientes autorizados en 10.77.0.0/24 que llegan por wg0, consultan la dirección anunciada 10.77.0.1 y necesitan un resolutor en 203.0.113.53. La dirección superior es un marcador de documentación, no un servicio en funcionamiento.
Redirigir una consulta solo cambia su destino
Una regla de NAT de destino en PREROUTING reescribe la dirección antes de que se tome la decisión de enrutamiento, así que el paquete se enruta después hacia el nuevo destino en lugar del antiguo. La dirección de origen del cliente queda intacta por esa operación. Por eso una regla que parece completa puede seguir produciendo silencio: la petición viaja ahora a un resolutor que nunca ha oído hablar del rango privado del cliente. La puerta de enlace tradujo un campo y heredó un segundo problema.
Ambos transportes DNS necesitan reglas coincidentes, porque un cliente recurre a TCP cuando una respuesta se trunca.
Las reglas siguientes seleccionan una interfaz de entrada, un rango de clientes y una dirección de destino original. Nada más en la puerta de enlace se ve afectado, y una consulta de la propia puerta de enlace no coincide en absoluto.
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A PREROUTING -i wg0 -s 10.77.0.0/24 -d 10.77.0.1 -p udp --dport 53 -j DNAT --to-destination 203.0.113.53:53
iptables -t nat -A PREROUTING -i wg0 -s 10.77.0.0/24 -d 10.77.0.1 -p tcp --dport 53 -j DNAT --to-destination 203.0.113.53:53
La ruta de respuesta es una decisión aparte
Dos disposiciones permiten que la respuesta vuelva, y elegir una pronto ahorra una sesión de depuración. O bien el resolutor superior tiene una ruta de vuelta a 10.77.0.0/24 a través de esta puerta de enlace, o bien la puerta de enlace traduce el origen en la salida para que la respuesta llegue a una dirección que el superior ya conoce. Ambas funcionan; solo una encaja con el control que tienes sobre el superior.
El enrutamiento merece el primer intento, porque mantiene la dirección del cliente visible para el resolutor y evita una segunda capa de traducción. Cuando el superior queda fuera de tu control, la traducción de origen en la interfaz de salida concreta es la opción práctica.
Acota esa traducción con la misma estrechez que la redirección, o la regla se convierte en un NAT de propósito general para cualquier cosa que coincida con ella:
iptables -t nat -A POSTROUTING -s 10.77.0.0/24 -d 203.0.113.53 -o eth0 -p udp --dport 53 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 10.77.0.0/24 -d 203.0.113.53 -o eth0 -p tcp --dport 53 -j MASQUERADE
El seguimiento de conexiones mantiene la asignación emparejada, así que la respuesta se reescribe de vuelta a la tupla original del cliente a la vuelta. Sin la regla de salida, el resolutor envía su respuesta hacia una dirección privada que no puede alcanzar, y el cliente ve un tiempo de espera en lugar de un error.
Escribe las reglas más estrechas de lo que parece la tarea
El permiso de reenvío pertenece al mismo ámbito. Permite el flujo del cliente al resolutor y el tráfico de retorno que conntrack ya reconoce, en lugar de aceptar cada conexión DNAT de la máquina. Una aceptación global también autoriza redirecciones de puertos que no tienen nada que ver con DNS.
El resolutor propio de la puerta de enlace es una ruta de código distinta. Una consulta emitida localmente pasa por OUTPUT, así que probar desde el shell de la puerta de enlace no ejercita ni la regla PREROUTING ni la política de reenvío. Por eso una prueba local puede pasar mientras todos los clientes fallan, y lo contrario es igual de frecuente.
Nada de esto cubre DNS sobre HTTPS en el puerto 443 ni DNS sobre TLS en el puerto 853, y nada cubre IPv6. Un cliente con un resolutor IPv6 configurado ignorará alegremente toda la disposición.
Qué demuestra una consulta nueva
El seguimiento de conexiones recuerda asignaciones anteriores, así que una consulta enviada antes de un cambio de regla puede responderse desde el estado antiguo y hacer que la regla nueva parezca rota. Empieza con un puerto de origen nuevo y, donde el cliente cachea respuestas, con un nombre nuevo.
dig @10.77.0.1 example.com A +short
conntrack -L -p udp --dport 53 | head
El primer comando muestra si la ruta del cliente resuelve siquiera, y el segundo muestra la traducción que la puerta de enlace instaló realmente, incluidas ambas direcciones de la tupla. Una asignación que apunta al resolutor correcto con un contador de respuestas atascado en cero es un problema de ruta de retorno y no de filtrado.
Confirma que el resolutor conoce los nombres que esperas antes de redirigir nada. Un sustituto que responde a nombres públicos pero no a tu zona privada convierte una búsqueda que funciona en un NXDOMAIN que parece un túnel roto. Prueba el resolutor directamente, desde la puerta de enlace, antes de que intervenga la ruta del cliente. Y referencia de extensiones de iptables documenta la semántica de DNAT y masquerade de la que dependen estas reglas.