Alguien pide que el navegador use el túnel, y la solicitud vuelve como una regla de cortafuegos que coincide con los puertos de destino 80 y 443. Parece precisa y no lo es. Una coincidencia de puerto selecciona paquetes por su cabecera de transporte, no por qué programa abrió el socket, y la navegación moderna no se limita a esos dos puertos sobre TCP. La regla omitirá tráfico que usted quería incluir y capturará tráfico que nunca pensó tocar. Antes de escribirla, decida cuál de tres fronteras distintas quiere en realidad.

La regla describe una clase de transporte, no una aplicación

En Linux, una coincidencia de puerto de destino inspecciona la cabecera TCP y nada por encima. Marcar esos paquetes y dirigirlos con una ruta de política funciona exactamente como está documentado, y ninguna de esas maquinarias sabe qué significa la carga útil ni qué proceso la envió. La marca es un número pegado a un paquete, no una identidad pegada a una aplicación.

nft add rule inet mangle output tcp dport { 80, 443 } meta mark set 0x1
ip rule add fwmark 0x1 table 100
ip route add default dev wg0 table 100

Se siguen dos consecuencias de inmediato. Un actualizador de software que contacta TCP 443 recibe el mismo trato que el navegador, lo que puede estar bien o puede ser una caída que espera el siguiente ciclo de actualización. Y un servicio web publicado a propósito en otro puerto, digamos 8443, queda por completo fuera de la regla aunque siga siendo el tráfico web que le importaba al usuario.

Los números son selectores legítimos cuando el requisito trata realmente de esos puertos. Se vuelven ficción cuando en el ticket está escrito «navegador» y en el conjunto de reglas se implementa un rango de puertos. Esa brecha no es un detalle de documentación. Es la diferencia entre una regla que usted puede defender en una revisión y una que nadie puede probar.

HTTP/3 abandona en silencio su regla de TCP

HTTP/3 funciona sobre QUIC, y QUIC viaja en UDP. Una regla que solo coincide con TCP no puede verlo, así que el mismo navegador que aprueba su página de prueba puede enviar una solicitud posterior por UDP y saltarse el túnel sin que nadie cambie un ajuste. RFC 9114 describe HTTP/3 como un protocolo basado en QUIC, y QUIC usa UDP con un puerto predeterminado 443 en el despliegue habitual.

Que un navegador concreto pruebe HTTP/3 depende de su configuración, del sitio y de si un intento anterior tuvo éxito. Eso lo hace mal asunto para razonar de memoria. Pregúntele a la herramienta:

curl --http3 -sS -o /dev/null -w '%{http_version} %{time_total}\n' https://example.com
ss -tunp | grep -E ':443\b'

La línea de curl imprime la versión negociada, así que un 3 confirma que se usó el camino UDP. El listado de sockets muestra luego si esa conexión está ligada a la interfaz del túnel o a la física. Si HTTP/3 no está disponible en su compilación de curl, la opción falla ruidosamente en lugar de retroceder en silencio, lo cual es su propia pequeña misericordia.

El DNS es una decisión aparte que debe tomar

Una regla de puerto para tráfico web no dice nada sobre la resolución de nombres. El navegador puede usar el resolutor del sistema, un resolutor configurado dentro del navegador o uno que haya empujado la última conexión. Cada uno puede enviar consultas por un camino distinto del que selecciona su regla, lo que produce la escisión clásica: la página carga, el nombre se resuelve en un lugar que usted no esperaba y el sitio interno resuelve a una dirección pública o no resuelve en absoluto.

Decídalo explícitamente. Si los nombres internos deben resolverse a través del túnel, el resolutor tiene que estar dentro de él, y el conjunto de reglas debe permitir DNS hacia ese resolutor mientras deja fuera las demás consultas. Si el navegador usa DNS over HTTPS hacia un proveedor público, la consulta evita por completo su resolutor y la regla de puerto no puede ayudar. Escriba la elección en el mismo registro de cambio que la regla de enrutamiento, porque quien depure el próximo fallo leerá ambos juntos.

Luego verifique con el resolutor y no con la página:

resolvectl query intranet.example.internal
resolvectl status | grep -A3 'Current DNS Server'

Una respuesta ausente es un problema de resolución incluso cuando el mensaje de error del navegador culpa a la red. Esos dos fallos se ven idénticos para un usuario y son tickets completamente distintos.

Tres fronteras, tres mecanismos distintos

La mayor parte de la confusión desaparece en cuanto nombra la frontera que quiere. No son intercambiables, y cada una tiene un modo de fallo distinto durante una caída del túnel.

What you actually wantMechanism that fitsWhat it does not cover
These transport ports use this exitFirewall mark plus policy routeApplications, HTTP/3 over UDP, DNS
This browsing session stays separateApplication-aware VPN, or a separate network namespace plus a proxyOther applications in the same session
Only these private sites are reachableDestination-based routes with private DNSPublic sites on the same address family

Un perfil de navegador separado es la trampa de la fila central. Separa cookies e historial, y no cambia nada de la tabla de enrutamiento del equipo, así que ambos perfiles toman el mismo camino. El aislamiento requiere algo que imponga el núcleo, es decir, un espacio de nombres, un contenedor o una aplicación que posea su propia interfaz de túnel.

Sea cual sea la fila que aplique, escriba qué debe ocurrir cuando el túnel caiga. Una ruta basada en marca que desaparece con la interfaz suele volver a la ruta predeterminada física, que es un comportamiento fail-open. Puede ser aceptable para navegar e inaceptable para cualquier otra cosa, y es una decisión, no un detalle de implementación.

Pruebe los flujos que dice cubrir

La prueba de aceptación debe seguir la frontera que usted escribió, no los números de puerto que resultaban cómodos. Elija un flujo que deba ir por el túnel, uno que no deba y uno que use un transporte en el que no pensó:

ip route get 203.0.113.40
curl -sS -o /dev/null -w 'v4 %{http_version} %{remote_ip}\n' https://example.com
nft list ruleset | grep -A2 'dport'

La consulta de ruta le dice qué interfaz usa realmente un destino, y ese es el hecho que más informes equivocan. La línea de curl confirma la versión negociada y la familia de direcciones. El volcado del conjunto de reglas atrapa la regla que añadió durante las pruebas y olvidó acotar, y así es como una marca temporal se convierte en enrutamiento fail-open permanente.

Registre las tres salidas con una marca de tiempo y guárdelas junto con el cambio. Cuando más tarde alguien informe de que «la VPN rompió la intranet», la diferencia entre la frontera prevista y la implementada será visible en ese registro, y la solución será un cambio de regla y no una discusión.

Artículos relacionados