Añades una regla para el tráfico VPN en la cadena FORWARD, ejecutas la petición desde la misma máquina Linux y el contador se queda en cero. La regla probablemente sea correcta. El paquete nunca tomó ese camino, porque una petición generada en la propia máquina no la reenvía ella misma. Recorrer la vida del paquete desde el socket hasta el cable explica por qué, y dónde debería ir la regla en su lugar.

Averigua dónde nació el paquete

El orden de hooks de Netfilter separa tres casos, y solo uno de ellos implica FORWARD:

OriginPathHook that sees it
Local processOUTPUT then POSTROUTINGOUTPUT, POSTROUTING
Addressed to a local servicePREROUTING then INPUTPREROUTING, INPUT
Received for another hostPREROUTING, FORWARD, POSTROUTINGFORWARD

Una aplicación local empieza en la ruta OUTPUT, porque el núcleo ya ha establecido que el paquete se origina aquí y nunca es candidato a reenvío. Crear un túnel no cambia esa clasificación; el túnel es un dispositivo por el que el paquete puede salir, no una etapa que convierta la salida local en tránsito.

Dos paquetes, una historia

Una vez levantado el túnel, el paquete interno de la aplicación y el paquete externo cifrado son objetos distintos. El paquete interno lleva el destino y la carga que eligió la app. El paquete externo lleva texto cifrado a la dirección y el puerto del par, y es el que cruza realmente la interfaz física.

Tu política afecta a uno de ellos, y elegir el equivocado es una causa habitual de que una regla parezca no hacer nada. Una regla que coincide con la dirección externa del par ve todos los paquetes del túnel por igual, haga lo que haga la aplicación de dentro. Una regla que coincide con un destino interno ve el tráfico que te importa, y solo se activará si ese paquete llega al hook donde instalaste la regla.

Los espacios de nombres mueven la frontera

Un contenedor lo hace más difícil sin cambiar el principio. La petición de la aplicación es salida local dentro del espacio de nombres de red del contenedor. El host recibe ese tráfico en una interfaz Ethernet virtual y puede reenviarlo, así que una regla FORWARD en el host puede tener sentido aunque el proceso que generó la petición nunca tocara la cadena OUTPUT del host.

Antes de elegir un hook, establece dónde viven realmente el conjunto de reglas y el túnel. Un túnel dentro del contenedor, un túnel en el host con el contenedor enrutado a través de él y un túnel en un espacio de nombres aparte son tres topologías distintas con tres ubicaciones de reglas distintas. Lee las reglas dentro del espacio de nombres que posee el dispositivo, no solo en el predeterminado.

Pregúntate si necesitas una marca

Si el objetivo es enviar un prefijo de destino por el túnel, puede que baste una ruta para ese prefijo. Comprueba primero las rutas efectivas, incluido todo lo que haya empujado el servidor: una ruta predeterminada redirigida envía mucho más tráfico por la VPN que la política estrecha que tenías en mente, y ninguna cantidad de marcado hará que el resultado coincida con la intención.

La clasificación hace falta cuando la decisión depende de algo que una ruta no puede expresar, como el origen, el usuario o el proceso. Para el tráfico recibido, el marcado en PREROUTING funciona. Para el tráfico local, el marcado debe ocurrir en una etapa de salida que pueda desencadenar una nueva consulta de ruta después de establecer la marca. Con nftables eso es una cadena de tipo route en el hook de salida; una cadena de filtro de salida ordinaria establecerá el valor y dejará la ruta intacta.

Con iptables, el equivalente vive en la disposición mangle OUTPUT, y se aplica el mismo requisito: la decisión de enrutamiento debe revisarse después de que exista la marca. Luego una regla de política tiene que consumir la marca y apuntar a una tabla que contenga una ruta utilizable. Establecer una marca de conntrack es una tercera operación, separada; guarda un valor en el flujo y no pone por sí misma ese valor en el paquete actual para que lo lea el enrutamiento.

Verifica la consulta y el contador a la vez

nft list ruleset
ip route get 198.51.100.25
ip route get 198.51.100.25 mark 0x1

La dirección y la marca son ilustrativas, y las dos consultas de ruta responden a preguntas distintas. La segunda pregunta qué haría el núcleo si un paquete llevara esa marca; no demuestra que tu conjunto de reglas asigne alguna. Trátala como una prueba de hipótesis, no como evidencia de que la política funciona.

Luego ejecuta una petición inocua y observa dos cosas a la vez: el contador del hook que elegiste y la salida que el paquete tomó realmente. Si el contador se mueve y el paquete sale por otro sitio, la marca o la tabla están mal. Si no se mueve ninguno, el paquete no llega a ese hook en absoluto, y el espacio de nombres o la ruta son la siguiente pregunta.

Por último, limita la prueba a lo que el mecanismo puede expresar. Una ruta para una dirección no se convierte en una política permanente para un servicio cuyas direcciones rotan. Decide primero el alcance de los paquetes y luego comprueba si el diseño de enrutamiento y marcado puede mantener ese alcance tras una reconexión.

Artículos relacionados