¿Contenedor Docker inaccesible en la VPN? Compare las subredes
Docker entrega una subred que la VPN también reclama. Compare los dos planes de direcciones y luego elija una reparación que sobreviva a una reconexión.
Los contenedores responden en la LAN de la oficina y dejan de responder en el momento en que se conecta la VPN de la empresa. Nada del contenedor ha cambiado: ni reinicio, ni actualización de imagen, ni edición de configuración. Lo que ha cambiado es la tabla de enrutamiento del host, donde una ruta que añadió el túnel ahora cubre la dirección que Docker asignó. Antes de editar una subred o pedir una exclusión de la VPN, ponga los dos planes de direcciones uno al lado del otro, porque las reparaciones cuestan cantidades de tiempo muy distintas.
Lea la ruta antes de cambiar la configuración
Empiece por la red que Docker construyó realmente. El bloque IPAM es el plan de direcciones, y la subred es la línea que importa:
docker network inspect project_default --format '{{json .IPAM.Config}}'
# [{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]Compose asigna por defecto una /16 a cada proyecto nuevo, así que dos servicios pueden caber dentro de un rango de 65,536 direcciones. Esa anchura es la razón de que los solapamientos sean habituales: una /16 elegida al azar es lo bastante grande para tragarse un sitio al que llega por el túnel, y nadie lo nota hasta que el túnel se levanta.
Después compare la selección de ruta para una dirección de contenedor, una vez con el túnel bajado y otra con el túnel subido:
ip route get 172.18.0.7
# 172.18.0.7 dev br-3f2a9c src 172.18.0.1Dos formas de respuesta llevan a lugares distintos. Si la salida nombra tun0, wg0 u otro dispositivo de túnel, un prefijo de VPN es al menos tan específico como la ruta del puente y el paquete nunca llega al contenedor. Si sigue nombrando el puente, el host puede alcanzar el contenedor, y su fallo es filtrado, DNS o una ruta de retorno que falla solo en una dirección.
Por qué una colisión de /16 es fácil de encontrar
Docker toma las redes de puente de los grupos privados, y el grupo por defecto sale del bloque 172.16.0.0/12 en porciones de /16. Las redes corporativas suelen usar el mismo espacio privado, y una VPN de acceso remoto empuja esos prefijos a cada cliente que se conecta. Cuando ambos lados creen que poseen 172.18.0.0/16, una tabla de enrutamiento sostiene dos afirmaciones contradictorias.
La longitud del prefijo decide al ganador, no el orden en que aparecen las rutas. Un túnel que empuja 10.0.0.0/8 no vence a una ruta de puente 172.18.0.0/16, porque /8 es menos específico. Un túnel que empuja 172.18.0.0/16, o 172.18.5.0/24 dentro de él, sí vence. Por eso un portátil funciona en la red de la oficina y falla en el Wi-Fi del hotel con la misma VPN: el cliente recibe prefijos distintos.
La misma tabla gobierna la dirección contraria. Un contenedor que necesita un host interno en 10.8.4.20 envía el paquete a su puerta de enlace de puente, y el host lo enruta después hacia el túnel. Esa ruta normalmente funciona porque el host hace el NAT, pero falla cuando el lado corporativo acepta solo la dirección VPN del portátil, o cuando el filtrado de ruta inversa descarta la respuesta asimétrica.
Compare las tres reparaciones
Solo hay tres salidas, y difieren en quién debe aprobarlas y qué se rompe mientras aplica una.
| Repair | Who owns it | What it costs |
|---|---|---|
| Renumber the container network | You | Recreates the network, restarts services, invalidates literal addresses in configs and scripts |
| Exclude your range from the tunnel | Network team | Changes what every laptop sees, needs a change request and a client profile update |
| Reach the service through a published port | You and the client | One port only, no direct container-to-container routing across the tunnel |
Renumerar es la única reparación que puede terminar sin un ticket, y por eso la mayoría de los artículos se detienen ahí. Es barata en un proyecto joven y cara en cuanto una herramienta de migración o una cadena de conexión guardada apunta a una dirección literal. Cuente esas referencias antes de editar el YAML, no después.
Una exclusión del túnel es la respuesta más limpia cuando el solapamiento está en un rango que su empresa posee de verdad. También es la más lenta, y es inútil para un contratista que no puede cambiar el perfil del cliente. Un puerto publicado o un pequeño proxy inverso evitan la discusión: el cliente habla con una dirección que el túnel ya enruta correctamente, y solo ese puerto tiene que ser accesible.
Fije un rango a propósito
Para un solo proyecto, declare la subred en el archivo compose para que el proyecto deje de tomar del grupo compartido:
networks:
default:
ipam:
config:
- subnet: 10.201.7.0/24Tome ese rango de un registro que mantenga su equipo, no de un ejemplo que encontró buscando. Compruébelo contra los prefijos que empuja la VPN, las LAN domésticas desde las que trabaja la gente y las demás redes de contenedores del mismo host. Luego planifique la recreación, porque una red existente conserva su subred antigua: docker compose down, luego up -d. docker network rm se niega mientras haya puntos finales conectados, y cualquier ipv4_address entrada del archivo tiene que caer dentro del rango nuevo.
Para las redes que Docker crea por su cuenta, fije un grupo de demonio en /etc/docker/daemon.json:
{
"default-address-pools": [
{ "base": "10.201.0.0/16", "size": 24 },
{ "base": "10.202.0.0/16", "size": 24 }
]
}El grupo se aplica a las redes creadas después de que el demonio se reinicie, y los puentes que ya existen conservan sus direcciones. Eso es cómodo y fácil de olvidar, así que trate un proyecto antiguo como todavía solapado hasta que alguien recree su red. La documentación de Docker sobre redes del motor describe las reglas de asignación si necesita defender el grupo en una revisión.
El puente de Linux y Docker Desktop fallan de forma distinta
En un host Linux, los contenedores se sientan en puentes dentro del espacio de nombres del host. Una tabla lo decide todo, así que la comparación anterior es toda la historia: lea la ruta del puente, lea la ruta del túnel y vea cuál gana para una dirección real de contenedor.
Docker Desktop pone los contenedores detrás de una VM con su propio NAT. El host no tiene ninguna ruta a la dirección del contenedor; llega al servicio por un puerto publicado, normalmente vinculado a 127.0.0.1. Un cliente de VPN puede, por tanto, romper el servicio sin ningún solapamiento de subredes, ya sea instalando una ruta para el rango interno de la VM o bloqueando el tráfico de loopback mientras el túnel está conectado. Si ip route get en el host informa de que no hay ruta para la dirección del contenedor, eso es lo esperado y no el fallo.
La consecuencia práctica es dónde mira primero. En Linux, empiece por la tabla de enrutamiento. En Desktop, empiece por el puerto publicado y las reglas de firewall del cliente de VPN, y luego compruebe si la subred interna de la VM choca con algo que empuja el túnel.
Verifique con el túnel subido
Reconecte la VPN dos veces antes de darlo por arreglado, porque un perfil que empuja rutas al conectar y las retira al desconectar puede parecer correcto tras el primer intento. Luego ejecute las comprobaciones que el cliente ejecuta de verdad:
ip route getdesde el host, usando la dirección real del contenedor.- Una petición desde otro contenedor, para demostrar que el servicio en sí está sano.
curl -sv http://127.0.0.1:8080/desde el cliente con el túnel subido, luegotraceroute -na la dirección del contenedor desde una máquina de la LAN.sysctl net.ipv4.conf.all.rp_filtersi la petición llega al host pero la respuesta desaparece.
Por último, escriba el rango elegido en el mismo registro que usó para elegirlo, con la fecha y el proyecto que lo posee. El siguiente solapamiento vendrá de un proyecto que nadie documentó, y la única defensa es que el rango se reservó a propósito en lugar de sacarlo al azar.