Un contenedor que no llega a nada detrás de la VPN corporativa suele vivir en un espacio de nombres de red distinto al del túnel. Las rutas, los servidores DNS y las marcas del cortafuegos del cliente del host pertenecen a su pila; un contenedor en red de puente tiene la suya. Ese único hecho explica la mayoría de los informes que llegan a un equipo de plataforma, y también es la razón por la que «la VPN está rota» y «Docker se salta la VPN» pueden ser ambas falsas a la vez. Dos configuraciones muy distintas se esconden tras un mismo síntoma, así que identifique cuál tiene antes de cambiar cualquier ajuste.

Averigüe a qué espacio de nombres pertenece el túnel

En Docker Desktop para macOS o Windows, los contenedores se ejecutan dentro de una máquina virtual Linux. Un cliente VPN instalado en el escritorio crea un túnel en el sistema operativo del escritorio, y la máquina virtual nunca lo ve. Ninguna configuración del contenedor lo arregla, porque la interfaz que necesitaría el contenedor no existe en absoluto en su espacio de nombres de red.

En un host Linux el túnel vive en el espacio de nombres del host, y los contenedores en puente suelen llegar a él a través de la tabla de enrutamiento del host con NAT de origen aplicado a la salida. Cuando esa ruta falla, la causa suele ser la política de reenvío, el filtrado de ruta inversa o una subred superpuesta más que una ruta ausente. Confirme en cuál de los dos mundos está antes de seguir leyendo:

docker info --format '{{.OperatingSystem}}'
docker run --rm --net=host alpine ip route | head -5
docker run --rm alpine ip route | head -5

La diferencia entre esas dos tablas de enrutamiento es todo el problema en una pantalla. Si la vista del host contiene la interfaz del túnel y la vista del puente no, está viendo aislamiento de espacios de nombres, y todo lo demás es una decisión sobre cómo cruzarlo.

La red del host es una prueba, no un diseño

Ejecutar un contenedor con la red del host, que Docker documenta como compartir el espacio de nombres de red del host, hace que herede directamente la interfaz del túnel y sus rutas. Si la misma petición entonces tiene éxito, la teoría de las rutas queda confirmada y el fallo es aislamiento de espacios de nombres, no credenciales, DNS ni una regla de acceso.

docker run --rm --net=host curl -sS -o /dev/null -w '%{http_code}\n' https://api.internal/health

Manténgalo como diagnóstico. La red del host renuncia a la publicación de puertos y a la mayor parte del aislamiento que quería de un contenedor, y en Docker Desktop «host» significa la máquina virtual, no el escritorio, así que un éxito o un fallo allí puede engañarle si olvida a qué host se dirigía.

Un dispositivo tun y los privilegios que conlleva

Un cliente VPN dentro del contenedor necesita un dispositivo de túnel y permiso para configurarlo. El atajo habitual es --privileged, que concede todos los dispositivos y relaja la política de seguridad en todo el contenedor. Eso es mucho más de lo que exige esta tarea, y cuesta justificarlo en una revisión.

sudo modprobe tun
docker run --rm -it --device /dev/net/tun --cap-add NET_ADMIN myvpn-client

La forma más estrecha mapea el único nodo de dispositivo y añade solo la capacidad de administración de red. Cargue primero el módulo en el host para que el nodo exista. Si el contenedor arranca y el cliente informa de que no puede abrir el dispositivo de túnel, revise el mapeo antes de sospechar del perfil, porque ese error suele ser literal.

Este diseño también significa que el cliente se ejecuta por contenedor. Es la respuesta correcta cuando cada carga de trabajo necesita su propio túnel, y la incorrecta cuando solo quería que el túnel del host fuera visible, que es lo que el equipo de plataforma probablemente suponía que hacía.

El NAT del puente cambia la fuente que ve la VPN

Con el puente predeterminado, el tráfico saliente del contenedor se traduce a la dirección del host. Detrás de una VPN, el lado corporativo ve por tanto la dirección del túnel del host y no la del contenedor, las reglas de acceso por origen se comportan como si el host hubiera hecho la petición, y dos contenedores se vuelven indistinguibles para el servidor VPN.

macvlan o ipvlan entrega al contenedor una dirección LAN en su lugar, lo que ayuda al descubrimiento en la LAN y hace que el contenedor parezca un par en el segmento. También evita por completo el túnel del host, así que ese contenedor no alcanzará prefijos solo-VPN a menos que la VPN también sea accesible desde esa LAN.

Ambas formas son legítimas; responden a requisitos distintos. Si el requisito es «este contenedor debe llegar a un servicio solo-VPN», elige entre enrutar a través del host y terminar el túnel dentro del contenedor. Escriba esa elección antes del despliegue, no después de la primera petición fallida. Elija lo que elija, anote la dirección de origen que verá el extremo remoto, porque es lo que mostrarán sus reglas de acceso y sus registros. Un diseño que no puede declarar esa dirección no está terminado.

El DNS sigue al demonio, no al túnel

Un contenedor recibe su configuración de resolución al arrancar, copiada del demonio o de la imagen. Las direcciones que la VPN empuja tras conectarse llegan demasiado tarde para esa copia, y se empujan al resolutor del host y no al contenedor.

Defina el resolutor explícitamente para el servicio, o apúntelo a un resolutor interno accesible a través del túnel. Un contenedor que resuelve un nombre privado a una dirección pública suele usar un resolutor público, no sufre una ruta rota, y la corrección corresponde al archivo compose o a la configuración del demonio.

El mismo razonamiento se aplica a la cuestión de la dirección de salida. Si cada contenedor debe aparecer desde una dirección VPN distinta, un solo túnel del host no puede entregarlo porque el NAT los colapsa en una única fuente. Las formas viables son un cliente en el espacio de nombres de cada contenedor o un sidecar que posee el túnel y comparte su pila, y ambas cambian cómo se direcciona la aplicación.

Lista de comprobación antes de cerrar el tíquet: identifique el espacio de nombres que posee el túnel, demuestre la ruta con la red del host, mapee solo el dispositivo tun necesario, recuerde la dirección de origen tras el NAT, defina el resolutor explícitamente y trate las direcciones de salida por contenedor como una decisión de arquitectura y no como una bandera.

Artículos relacionados