Dos máquinas virtuales en el mismo host llegan a la LAN a través de un puente, y una regla colocada en la cadena ip forward muestra un contador que nunca se mueve. Las tramas son reales, el tráfico pasa y la regla simplemente no está en su camino. Comparar las dos formas en que Linux expone el tráfico puenteado explica ese silencio, y también explica por qué cargar un módulo antiguo es una respuesta peor de lo que parece.

Dos caminos a través de un solo host

Un paquete puede salir de este host de dos maneras muy distintas, y la diferencia decide qué hooks lo ven. Si el destino está más allá de un puerto físico y la trama se conmuta entre dos puertos del puente, el host reenvía una trama Ethernet; no se consulta el código de enrutamiento y no se produce ningún salto enrutado. Si el destino es el propio host, o una red alcanzada por una interfaz de túnel, el paquete se enruta y los hooks de la capa IP sí se aplican. Ten presente esa bifurcación, porque cada pregunta posterior sobre cadenas y familias depende de cuál de los dos caminos toma una trama.

Esa distinción es toda la historia detrás de una regla que no cuenta nada. Una trama puenteada de veth9a1 a enp3s0 cruza el puente, no la pila IP, así que una cadena ip forward no ve nada con lo que coincidir. Los nombres de interfaz de un ejemplo más antiguo no determinan qué camino tienes, y por eso el primer paso es mirar la topología y no el conjunto de reglas.

Un túnel añade un tercer caso que merece un nombre. Un dispositivo TUN entrega paquetes IP al host, así que se enrutan y sí atraviesan cadenas IP, mientras que un dispositivo TAP conectado a un puente entrega tramas y se comporta como el caso puenteado. El tipo de dispositivo, no el nombre del producto, es lo que decide.

Compara las dos familias que pueden ver una trama puenteada

Linux admite filtrado de puente nativo mediante la familia bridge de nftables, y no necesita ningún módulo antiguo para inspeccionar y descartar tramas en vuelo. La propia documentación del puente del kernel hace esa recomendación directamente, algo que conviene saber antes de que un resultado de búsqueda te diga que cargues un módulo.

Observation pointWhat it seesWhat it costs
nftables bridge family chainsEthernet frames forwarded between bridge ports, in both directionsRules must be written in bridge syntax with link-layer matches
Legacy br_netfilter plus an ip chainBridged IPv4 and IPv6 packets, re-exposed through IP-layer hooksExisting host rules may begin matching traffic they never saw before
inet chain for routed trafficPackets the host routes, including traffic arriving from a TUN deviceNo visibility into purely switched frames

Usar el comando nft en lugar de iptables no coloca, por sí solo, una regla en la familia correcta. Una cadena declarada en la familia bridge ve tramas; una cadena declarada en ip, ip6 o inet no las ve, sin importar qué binario la creó. La familia es una propiedad de la cadena, no de la herramienta que la escribió.

El camino antiguo funciona de otra manera, y por eso conviene comparar en lugar de elegir un bando por costumbre. Cargar br_netfilter y activar los ajustes bridge-nf-call vuelve a exponer el tráfico IPv4 e IPv6 puenteado a través de los hooks de la capa IP, de modo que una regla normal de iptables por fin puede coincidir con él. Las tramas no cambian; lo que cambia es el conjunto de hooks que atraviesan, lo que significa que cada regla de host existente tiene ahora un público nuevo.

Lee el camino efectivo antes de añadir una regla

Tres comandos establecen dónde estás: a qué está conectado el puente, si el módulo antiguo está activo y qué cadenas existen ya en la familia bridge. Ejecútalos antes de escribir nada, porque la respuesta decide cuál de los dos diseños estás ampliando. Saltarse este paso es cómo una regla correcta acaba en una cadena que nada atraviesa.

bridge link show
lsmod | grep br_netfilter
nft list ruleset | grep -A4 "chain forward"

La salida separa los casos con claridad. Los puertos listados bajo el puente te dicen qué interfaces se conmutan; un resultado vacío de lsmod significa ninguna visibilidad en la capa IP de las tramas puenteadas; una cadena forward existente de la familia bridge significa que ya hay un propietario de la política y que tu regla pertenece allí en lugar de a una cadena nueva propia.

Luego añade una regla fácil de releer, con un contador y sin cambiar el veredicto, y haz pasar un único flujo representativo por el puente. Un contador que se mueve demuestra que la trama llegó a la regla. Eso es todo lo que demuestra, así que continúa también con el camino denegado, ya que una política que lo acepta todo también produce un contador en movimiento.

nft add rule bridge filter forward iifname "veth9a1" oifname "enp3s0" counter accept

Dónde cambia el comportamiento el módulo antiguo

Activar el camino antiguo en un puente en funcionamiento no es un acto neutro de añadir visibilidad. Las reglas que antes eran inalcanzables para el tráfico puenteado pasan a ser alcanzables, incluidas reglas de host escritas para otra interfaz, y una política drop predeterminada en la cadena ip forward puede aplicarse de pronto a tramas que antes pasaban intactas. En un host administrado a través de ese puente, el resultado es un bloqueo sin consola. Ese no es un modo de fallo hipotético; es la consecuencia ordinaria de ampliar un conjunto de hooks en una máquina a la que llegas por el camino que acabas de ampliar.

La secuencia más segura es decidir qué familia posee la política, escribir allí las reglas y mantener un camino de recuperación independiente antes de cambiar cualquier sysctl. Si dos familias tienen reglas, documenta cuál es la autoridad; dos políticas superpuestas son la forma en que un paquete se acepta en un lugar y se descarta en otro sin un solo archivo que leer.

El aislamiento en sí todavía necesita un diseño completo. Permitir un origen hacia un destino solo demuestra que un flujo funciona, mientras que el requisito suele ser que una VM no pueda alcanzar a sus vecinos ni al host. Los contadores de las reglas de denegación importan más que el contador de la regla de aceptación, porque el contador de aceptación es el que ya esperabas que se moviera.

Por último, mantén separado el caso de entrada del host. El tráfico dirigido a la propia IP del puente llega a input, no a forward, y una regla en forward nunca lo verá, elijas la familia que elijas. Tres casos, dos familias, una lección: el camino decide el hook, y el hook decide si tu regla existe siquiera.

Artículos relacionados