Imagine un host Linux que termina una VPN y además ejecuta un contenedor en una red macvlan. La LAN es 192.168.60.0/24, el contenedor tiene 192.168.60.210 y los clientes VPN llegan desde 10.95.0.0/24. El cliente llega al servicio, la respuesta nunca vuelve y todas las reglas de cortafuegos del host parecen correctas. Dos restricciones separadas producen ese síntoma, y corregir una deja la otra en su sitio.

Dos restricciones, un síntoma

La primera restricción es el aislamiento: el controlador macvlan de Docker no permite que un contenedor hable con su propio host a través de la interfaz padre. El tráfico entre la pila del host y el contenedor no tiene camino, por mucho que se escriban las rutas del host.

La segunda restricción es el camino de vuelta. La puerta de enlace predeterminada del contenedor suele ser el router de la LAN, así que una respuesta dirigida a un cliente VPN sale por ese router. Si el router no tiene ruta de vuelta al grupo de VPN, la respuesta se descarta en algún punto intermedio.

Los dos fallos se ven idénticos desde el cliente: una petición que llega y una respuesta que nunca llega. Necesitan reparaciones distintas, y una regla masquerade amplia puede ocultar cuál de las dos sigue rota. Por eso la primera prueba es una captura en el lado del contenedor y no otro cambio de cortafuegos. Si la petición nunca aparece allí, la restricción que está en juego es el aislamiento.

Construya el shim del host, de forma estrecha

Una segunda interfaz macvlan en el host, conectada al mismo padre en modo puente, da a la pila del host una identidad propia en ese segmento de la LAN. Resérvele una dirección fuera del grupo DHCP y fuera del rango del contenedor, y encamine solo el contenedor a través de ella.

ip link add macvlan-vpn link eth0 type macvlan mode bridge
ip address add 192.168.60.250/32 dev macvlan-vpn
ip link set macvlan-vpn up
ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250

El primer comando crea la interfaz en modo puente, que es el valor predeterminado documentado para este controlador y el modo que se quiere para el tráfico entre host y contenedor. El segundo asigna un /32 para que la dirección no choque con el prefijo de la LAN, y el cuarto envía solo la dirección del contenedor a través del shim.

No redirija toda la LAN por la interfaz nueva. La ruta conectada ordinaria se queda como está, y la ruta del host es deliberadamente estrecha para que un contenedor gane un camino sin que el resto del segmento cambie de comportamiento. Una ruta predeterminada apuntando al shim sería otro diseño con otras consecuencias. Manténgala específica y el radio de impacto sigue siendo pequeño.

Estos comandos cambian la configuración de red en un host en funcionamiento. En un dispositivo o una plataforma gestionada, use el mecanismo de configuración compatible de esa plataforma, porque un cambio interactivo en un intérprete de órdenes root puede no sobrevivir a una actualización.

Decida cómo se conserva el origen

Con el shim en su sitio, el contenedor puede llegar al host, y la pregunta pasa a ser qué dirección de origen lleva la respuesta. Conservar el origen VPN original es el modelo más limpio: el contenedor ve la dirección real del cliente y los registros y las reglas de acceso del servicio pueden usarla.

Para que eso funcione, la configuración de red del contenedor debe enviar para este camino el tráfico de 10.95.0.0/24 a 192.168.60.250 como su puerta de enlace. Eso es un ajuste de ruta o de puerta de enlace compatible dentro de la propia configuración del contenedor, no un truco del lado del host. Confírmelo desde dentro del contenedor en lugar de suponer que el ajuste ya surtió efecto. Una puerta de enlace predeterminada que todavía apunta al router de la LAN seguirá enviando respuestas al mismo agujero.

Si el diseño aprobado, en cambio, oculta los orígenes VPN, limite la traducción de forma estrecha: el grupo VPN real, el shim como interfaz de salida y el contenedor y el servicio concretos.

iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250

Haga coincidir el shim como interfaz de salida, no el túnel. Una regla que nombra el túnel como interfaz de salida no coincidirá con un paquete dirigido hacia el contenedor, y ese es el error que suele contener este tipo de montaje. Mantenga la regla tan estrecha como la frase anterior y revísela cuando cambie el grupo.

Verifique desde el cliente, no desde el host

Una petición del propio host, ligada a la dirección del shim, demuestra que el shim puede llegar al contenedor. No demuestra que el contenedor pueda devolver tráfico a un origen conservado 10.95.0.x, porque la dirección de origen en esa prueba es la del propio shim.

curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210

El primer comando prueba el tramo del host al contenedor, y el segundo muestra qué cruza realmente el shim mientras un cliente VPN real hace la petición. Mire la dirección de origen a la entrada y si aparece una respuesta con el mismo flujo.

El reenvío debe estar habilitado en el host, y el camino de reenvío necesita un permiso para el grupo VPN hacia el shim en el puerto del servicio, además de las respuestas establecidas. Una regla INPUT del host no autoriza el tráfico reenviado, y esa es una causa habitual de que el paquete se descarte después de que el enrutamiento parezca correcto.

Ejecute la aplicación real con credenciales reales y luego compruebe que un segundo servicio no relacionado en el mismo contenedor todavía lo rechaza. Si la única forma de hacerlo funcionar era abrir todas las reglas de reenvío, el diseño no está terminado. Anote también qué dirección de origen registró el servicio, porque es la que usarán sus propias reglas de acceso de ahora en adelante.

Artículos relacionados