Contactar →
← Todas las entradas
Arquitectura2026.06.17

Aislar el plano de gestión

Por este homelab circulan dos tipos de tráfico de red muy distintos. Uno son peticiones que llegan a una aplicación: alguien cargando una página, una llamada a la API, una comprobación de salud. El otro es tráfico capaz de reiniciar un hipervisor, reconfigurar un switch o meterse en la consola de una VM como una mano que entra por la parte de atrás de la máquina. Antes, esos dos tipos de tráfico compartían más camino del que me resultaba cómodo, y la solución no fue nada ingeniosa: simplemente, dejar de permitir que se tocaran.

El plano de gestión de este entorno (la capa de control capaz de reiniciar un host, cambiar una asignación de VLAN o, en general, llegar a la infraestructura que hay debajo de las aplicaciones) vive ahora en su propia red, accesible únicamente a través de su propio túnel VPN. Esa red no transporta nada más. Ningún tráfico de aplicación circula por ella, nunca, y no existe puente, ruta ni segmento compartido entre ella y la red que sirve cualquier cosa de cara al público. Si necesito llegar al plano de gestión, levanto un túnel específico para ese único propósito y nada más lo usa.

El modo de fallo que esto cierra

El escenario que de verdad me preocupaba es de lo más mundano: algún servicio de cara a la aplicación resulta comprometido. Puede que una dependencia tenga un CVE grave, puede que yo mismo configure algo mal, puede que un endpoint expuesto tenga un fallo que todavía nadie ha encontrado. Es un riesgo asumido de tener cosas expuestas en internet: aplico parches, superviso, intento reducir el radio de impacto de que un servicio concreto se vea comprometido. Pero hay una diferencia de categoría entre «un atacante consigue una shell dentro de un contenedor» y «un atacante puede llegar al hipervisor sobre el que corre ese contenedor». Lo primero es un mal día. Lo segundo es todas las VM de ese host, más el movimiento lateral que permita la interfaz de gestión: manipulación de snapshots, acceso a la consola de otras VM, la propia infraestructura de conmutación.

Si la red que da servicio a esa aplicación puede enrutar hasta el plano de gestión (aunque sea a través de dos o tres saltos, aunque sea a través de una regla de firewall que se supone estrecha), entonces comprometer la aplicación es, potencialmente, comprometer la infraestructura. El aislamiento elimina esa ruta de forma estructural. No es «hay una regla de firewall que bloquea esto» (las reglas se pueden configurar mal, o tener una excepción que nadie recuerda haber añadido). Es «no existe ninguna ruta a nivel de red de una a otra, punto». Un atacante situado en la red de aplicaciones no tiene interfaz, ni puerta de enlace, ni entrada ARP, nada contra lo que siquiera intentar una conexión. No hay forma de configurar mal algo que, directamente, no existe.

Dos túneles VPN independientes, dos redes independientes, sin puente entre ellas.

Esto no es una idea nueva

Quiero ser honesto: esto no es algo que haya inventado yo, es el mismo principio que los equipos de redes y de cloud llevan usando desde hace mucho tiempo, normalmente bajo el nombre de gestión fuera de banda o, en términos más amplios, aislamiento entre plano de control y plano de datos. El patrón aparece a cualquier escala. La propia guía de Cisco sobre gestión fuera de banda para proveedores de servicios describe cómo enrutar el tráfico de gestión por interfaces dedicadas, precisamente para que un atacante que entra en la ruta de datos de producción no tenga forma de pivotar hacia los dispositivos que gestionan esa ruta: véase su documento de buenas prácticas de gestión fuera de banda. La versión más fuerte de esto es lo que a veces se llama Isolated Management Infrastructure (infraestructura de gestión aislada): no solo una VLAN separada, sino puertos de gestión que terminan en switches dedicados fuera de banda, de modo que ni siquiera la infraestructura física de conmutación del tráfico de gestión llega a tocar la que transporta el tráfico de producción (un buen resumen es el explicativo de ZPE Systems sobre gestión OOB).

Las nubes públicas funcionan con la misma lógica a una escala mucho mayor: el plano de control que aprovisiona y gestiona el compute (las API que crean VM, adjuntan discos, reescriben security groups) está separado arquitectónicamente del plano de datos que transporta el tráfico de los clientes, precisamente para que nada de lo que un workload de un tenant haga en el plano de datos pueda llegar a la capa que gestiona la flota subyacente. La versión de homelab de esto es más pequeña y más tosca, pero tiene la misma forma: lo que sea capaz de actuar sobre la infraestructura en sí se sitúa en una ruta a la que el tráfico de aplicación, estructuralmente, no puede llegar.

Lo que tengo yo está más cerca del extremo ligero de ese espectro: aislamiento lógico mediante un túnel VPN dedicado y una red separada, no hardware de conmutación fuera de banda dedicado. Esa es una diferencia real en cuanto a solidez (una infraestructura física compartida sigue siendo un dominio de fallo compartido, aunque las rutas lógicas nunca se crucen), pero a escala de homelab es el aislamiento que realmente importa: no existe ninguna ruta desde la red de aplicaciones hasta la red de gestión, y entrar en la red de gestión exige levantar un túnel específico que no tiene ningún otro propósito.

Qué significa «sin puente» en la práctica

En concreto: la VPN de gestión es una instancia de WireGuard separada de la que (si la hay) toca infraestructura adyacente a las aplicaciones (la misma separación en dos túneles por nivel de privilegio que esta plataforma usa en otros sitios, aplicada aquí al caso de mayor privilegio que existe). Reparte direcciones en un rango que no usa nada más. El firewall del host no tiene ninguna regla que permita tráfico desde la subred de aplicaciones hacia ese rango: no hay subred a la que enrutar, porque la interfaz simplemente no es accesible desde ningún sitio que no sean los propios peers de ese túnel. Cuando necesito administrar un hipervisor, conecto ese cliente VPN, hago el trabajo y desconecto. No hay ningún túnel persistente abierto, ningún servicio en el lado de aplicaciones que haga de proxy hacia gestión, ninguna excepción del tipo «este script necesita las dos cosas» que acabe convirtiéndose, sin darme cuenta, en un puente permanente.

Ese último punto es en el que he tenido que ser disciplinado. La tentación con cualquier red aislada es construir una integración «de conveniencia» que la atraviese: un panel de monitorización que quiere consultar tanto la salud de la aplicación como las estadísticas del hipervisor, un script de deploy que quiere tanto publicar un container como comprobar el espacio en disco del host. Cada una de esas cosas, por separado, parece inofensiva. Juntas, son la forma en que el aislamiento se erosiona: no por un único error dramático, sino por pequeñas comodidades que van abriendo, cada una, un agujerito, hasta que el límite es más teórico que real. He mantenido la monitorización dividida de la misma manera: las métricas del lado de aplicación se quedan en el lado de aplicación, y las métricas de host/hipervisor se recogen desde dentro de la red de gestión mediante algo que vive ahí, no mediante algo que entra desde fuera.

Lo que esto no resuelve

Aislar el plano de gestión no hace que las aplicaciones sean más seguras: hace que su compromiso sea menos catastrófico. Una aplicación sigue pudiendo ser vulnerada, los datos que hay detrás de ella siguen pudiendo estar en riesgo, y yo sigo teniendo que hacer el trabajo habitual de parchear, supervisar y reducir la exposición en el lado de aplicaciones. Lo que cambia es el techo de lo mal que puede llegar a ir un único compromiso. Sin esta separación, el peor caso para cualquier servicio expuesto es «el peor caso para todo el homelab». Con ella, el peor caso para un servicio expuesto queda contenido a ese servicio y a lo que realmente pueda alcanzar, lo cual, por diseño, no incluye la capa capaz de reiniciar o reconfigurar la máquina que hay debajo.

También hay un coste, que prefiero decir claramente en vez de pasar por alto: dos túneles en lugar de uno son dos cosas que mantener funcionando, dos juegos de credenciales, un paso más de login cada vez que necesito tocar infraestructura en lugar de una aplicación. Para un homelab de una sola persona, esa sobrecarga es trivial. El cálculo sería distinto a un tamaño en el que «quién tiene acceso al túnel de gestión» se convierte en un auténtico problema de control de acceso y no en el cliente VPN de una sola persona, pero ese es un problema para una versión posterior y más grande de este montaje, no para la que funciona hoy.

Cómo me enteraría realmente si esto se rompiera

Un límite que nunca se pone a prueba es un límite que simplemente se está dando por hecho, así que he intentado tratar el propio aislamiento como algo que verificar periódicamente, no como algo que se configura una vez y en lo que se confía para siempre. La comprobación no tiene nada de glamurosa: desde un host de la red de aplicaciones, intentar llegar a una dirección del rango de gestión y confirmar que falla igual que fallaría un intento de llegar a una red que no existe: sin ruta, no un objetivo bloqueado pero visible. La diferencia importa. Una regla de firewall que rechaza activamente una conexión sigue confirmando que el objetivo existe y está escuchando algo; la ausencia de ruta ni siquiera llega a eso. Prefiero que el modo de fallo sea «aquí no hay nada que encontrar» a «aquí hay algo, pero no tienes permiso para hablar con ello», porque la segunda formulación implica una regla que más adelante se podría relajar, mientras que la primera implica que, directamente, no hay ninguna ruta que relajar.

Lo otro que merece la pena revisar periódicamente es si algo ha ido echando, sin que nadie se dé cuenta, un pie en cada mundo. Es un error fácil de cometer sin notarlo: un agente de monitorización que se despliega en todas partes mediante la misma automatización, incluidos hosts de ambas redes, acaba siendo una única pieza de software que resulta tener interfaces hacia las dos (no un puente enrutado, pero sí un proceso a caballo sobre el límite, de una forma funcionalmente parecida si ese proceso llega a comprometerse o a configurarse mal). No tengo una respuesta totalmente automatizada para detectar esto más allá de preguntar periódicamente, host por host, «qué está corriendo aquí en realidad, y con qué red habla». Eso es una auditoría manual, no un sistema, y prefiero admitirlo antes que dar a entender que existe una herramienta que hace esto por mí cuando, en su mayor parte, todavía no existe.

Por qué no tenía esto desde el principio

Vale la pena admitir que este no fue el diseño original: es una corrección. Al principio, las interfaces de gestión estaban en la misma red general que todo lo demás, accesibles a través de la misma VPN porque en aquel momento era la única VPN que existía, protegidas por reglas de firewall que se suponía que eran estrechas. No pasó nada malo como resultado directo de ese montaje, y esa es exactamente la trampa: una arquitectura con un único punto latente de fallo catastrófico puede funcionar mucho tiempo sin que ese fallo llegue a dispararse nunca, y la ausencia de un incidente no es prueba de que el diseño estuviera bien. Lo que realmente provocó el cambio no fue tanto un susto concreto como sentarme y preguntarme, sin rodeos, «qué es lo peor que pasa si mañana comprometen lo más expuesto que tengo corriendo», y que no me gustara la respuesta honesta bajo el diseño antiguo. Levantar un segundo túnel VPN y una segunda red fue una pequeña cantidad de trabajo puntual frente a un modo de fallo que, de otra forma, habría ido creciendo con todo lo demás que fui añadiendo a este homelab con el tiempo.

La parte que defendería sin matices es la forma central de esto: nada que dé servicio a tráfico de aplicación debería estar en una red que tenga una ruta, cualquier ruta, hacia la capa que controla la infraestructura que hay debajo. Todo lo demás aquí es detalle sobre esa única decisión estructural.

← Todas las entradas