El host sigue respondiendo por SSH después de que se levante una VPN de túnel completo, pero un servicio publicado con Docker en la misma máquina se queda mudo. El listener no tiene nada malo: el contenedor se ejecuta, la asignación de puertos existe y el paquete llega. El contenedor está sano y la petición sí lo alcanza. Lo que cambia es de dónde parte la respuesta cuando Linux elige su ruta, y esa diferencia decide cuál de los dos diseños siguientes necesita.

Siga la tupla a través del NAT de destino

Tome un host en 192.0.2.10 que publica TCP 2222 hacia un contenedor en 172.30.240.5:22. Una petición desde 198.51.100.25 se traduce antes de llegar al contenedor, y el contenedor responde como tal.

WAN request:      198.51.100.25 -> 192.0.2.10:2222
after DNAT:       198.51.100.25 -> 172.30.240.5:22
container reply:  172.30.240.5:22 -> 198.51.100.25

En la decisión de ruta del host, la respuesta aún lleva la dirección de origen del contenedor. La traducción inversa restaura más tarde la tupla publicada, y por eso el paquete parece incorrecto justo en el momento en que se elige la ruta.

Por qué una regla solo para el host no la ve

Una regla que selecciona la tabla WAN solo para paquetes de 192.0.2.10 cubre los propios demonios del host y pasa por alto por completo esta respuesta reenviada. La dirección de origen de la respuesta es 172.30.240.5, no la del host.

La corrección excesiva consiste en enrutar todo desde el contenedor por la WAN, lo que además exime de la VPN las conexiones salientes no relacionadas del contenedor. Es una política distinta de la que se le pidió, y normalmente sorprende a alguien más adelante.

La coincidencia posterior al DNAT es otro hook

La documentación de Docker sobre cortafuegos señala que el filtrado ordinario de usuario ve el destino posterior al DNAT, así que coincidir el puerto publicado 2222 en una regla normal no es lo mismo que coincidir el puerto 22 del contenedor. Si la tupla original importa, use el mecanismo de destino original admitido en lugar de adivinar qué puerto es visible.

Esta confusión de hooks produce reglas que parecen correctas y nunca coinciden. Revise los contadores de la propia regla antes de reescribir la política. Una regla sin ninguna coincidencia le dice que se está evaluando en un lugar al que el paquete nunca llega.

Diseño A: llevar la decisión como estado de conexión

Una marca de conexión puede llevar la decisión de entrada a través de la traducción, pero debe restaurarse en el paquete antes de la búsqueda de ruta que importa. Las etapas son:

  1. Reserve un campo de marca y una prioridad de regla que no choquen con Docker, la VPN ni otro propietario de política.
  2. Identifique solo la nueva conexión WAN prevista en un punto previo al DNAT donde el seguimiento de conexiones esté disponible.
  3. Registre la decisión en la marca de conexión, sin forzar la propia petición original hacia la tabla WAN.
  4. En la dirección de respuesta, restaure solo sus propios bits de marca en el paquete antes del enrutamiento.
  5. Seleccione una tabla WAN completa con la suficiente antelación para que una regla de la VPN no pueda ganar primero.

Esa tabla necesita las rutas conectadas reales y la puerta de enlace. También necesita un comportamiento definido cuando falta la ruta. La caída silenciosa al túnel es el peor resultado, porque la configuración sigue pareciendo que funciona. En su lugar, falle de forma cerrada y regístrelo.

Diseño B: terminar en el host

Un frontend configurado deliberadamente en el lado del host, como un proxy TCP o un proxy inverso delante del contenedor, mantiene la respuesta originada en la dirección del host. Entonces las reglas escritas para el host se comportan como se espera, y el contenedor permanece en su red privada.

El coste es otra pieza móvil con su propia configuración, manejo de direcciones de origen y controles de acceso. Normalmente es el límite admitido más sencillo, y a menudo es la respuesta correcta cuando la política de enrutamiento la mantendría una sola persona que podría marcharse.

Verifique el cambio, no la intención

Abra una conexión autorizada nueva desde el lado público y confirme que la respuesta sale por la interfaz prevista. Después compruebe que una petición no relacionada iniciada por el contenedor sigue siguiendo la VPN.

No vacíe la tabla de conexiones de la máquina para probar una regla: las entradas existentes conservan su asignación anterior, y el vaciado rompe todo lo demás en el host. Publicar un puerto define la accesibilidad. No define la ruta de la respuesta. Escriba el diseño elegido con sus nombres de tabla, para que la siguiente persona no tenga que redescubrirlo durante un incidente.

Artículos relacionados