NET_ADMIN en un contenedor VPN: qué puede cambiar y dónde
La capacidad permite cambios de interfaz, ruta y cortafuegos dentro de un solo espacio de nombres de red. Con red de host, ese espacio es la propia pila del host.
NET_ADMIN es la capacidad de Linux que permite a un proceso realizar administración de red, y en un contenedor hace exactamente eso dentro del espacio de nombres de red en el que se ejecuta el proceso. No es una licencia para abrir un socket ni un sustituto de un dispositivo o de una ruta. La pregunta interesante nunca es si se ha concedido la capacidad, sino qué espacio de nombres recibe el cambio.
Qué cubre la capacidad
Dentro de su espacio de nombres, un proceso con NET_ADMIN puede levantar y bajar interfaces, asignar direcciones, añadir y quitar rutas y escribir reglas de cortafuegos, que es el grupo de operaciones que capabilities(7) reúne bajo esta capacidad. También puede ajustar parámetros a nivel de interfaz que controlan cómo el núcleo encola y filtra el tráfico. Un cliente VPN normalmente necesita unas cuantas al arrancar y nada más después. Por eso la mayoría de las imágenes piden más alcance del que usan.
Las operaciones fuera de ese espacio de nombres no están cubiertas, y los privilegios adyacentes son separados. Leer y escribir paquetes crudos pertenece a NET_RAW, y crear un dispositivo tun necesita tanto la capacidad como acceso al nodo del dispositivo. Un proceso sin el dispositivo recibe un error de permisos que parece un problema de red y no lo es.
El espacio de nombres decide el radio de daño
Un contenedor en su propia red puente alcanza su propio loopback, sus propias interfaces y su propia tabla de enrutamiento. Conceder NET_ADMIN allí permite al cliente VPN construir un túnel sin tocar las decisiones de enrutamiento del host, que es la disposición que asumen la mayoría de las imágenes de contenedor.
Cambie ese contenedor a red de host y la misma concesión ahora edita las rutas del host y su cortafuegos, porque no queda ningún espacio de nombres separado. El cliente que debía gestionar un solo túnel puede entonces redirigir el tráfico de toda la máquina, y un error en su script de desmontaje deja al host reglas que nadie escribió. Nada en la capacidad cambió; cambió el contexto. Por eso el mismo archivo compose se comporta de forma distinta en dos hosts.
Tres requisitos previos que se funden en uno
Los fallos de arranque en contenedores VPN suelen implicar una de tres cosas separadas: la capacidad, el dispositivo de túnel y el soporte del núcleo para el protocolo. Conceder las tres a la vez funciona, y también hace imposible atribuir el siguiente fallo. Un fragmento mínimo de compose concede la capacidad y pasa el nodo del dispositivo explícitamente:
services:
vpn:
image: example/vpn-client:latest
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
sysctls:
- net.ipv4.conf.all.src_valid_mark=1Lea la documentación de la propia imagen para saber qué sysctls necesita, porque un sysctl dentro de un contenedor puede requerir un privilegio adicional o un ajuste a nivel de host. Donde la imagen admite solo modo de espacio de usuario, no hace falta ningún dispositivo y la lista de capacidades se reduce en consecuencia.
Conceda la operación estrecha, no el modo
El modo privilegiado entrega todas las capacidades y amplía el acceso a dispositivos al mismo tiempo, así que oculta cuál de los tres requisitos previos faltaba. También hace indistinguibles los modos de fallo del contenedor de los cambios del host. Prefiera una lista explícita aunque sea más larga de escribir.
Los despliegues rootless y con espacios de nombres de usuario cambian qué significa una capacidad en la práctica, ya que el proceso puede tenerla solo dentro de un espacio de nombres mapeado. Copiar una lista de capacidades de un ejemplo rootful a un entorno rootless y esperar el mismo alcance es una forma habitual de perder una tarde.
Los secretos pertenecen a una decisión aparte. Tener NET_ADMIN no dice nada sobre qué identidad de par presenta el cliente, qué credenciales carga ni cómo se rotan. La administración de red no aporta confianza.
Verifique el cambio y registre por qué existe la concesión
Confirme qué recibió realmente el contenedor antes de depurar el túnel. La inspección siguiente informa de las capacidades añadidas y del modo de red, y luego muestra cómo se ve la lista de interfaces desde dentro:
docker inspect --format '{{.HostConfig.CapAdd}} {{.HostConfig.NetworkMode}} {{.HostConfig.Privileged}}' vpn
docker exec vpn sh -c 'grep CapEff /proc/self/status'
docker exec vpn ip -br addr
docker exec vpn ip routeSi la capacidad está presente y la lista de interfaces sigue vacía, el cliente falló antes de poder crear nada, y los registros del contenedor son el siguiente lugar donde mirar. Si el túnel existe pero el tráfico no fluye, la tabla de enrutamiento dentro del contenedor responde la siguiente pregunta.
Pruebe también la ruta de desmontaje, porque un cliente que escribe reglas de cortafuegos puede dejarlas atrás. Detenga el contenedor y vuelva a comprobar el conjunto de reglas del host si se usa red de host. Una concesión que solo se necesita dos segundos al arrancar no debería describirse en el archivo compose como un requisito permanente sin una nota que lo explique.
Escriba el motivo junto a cada capacidad: qué operación la necesitaba y qué falla sin ella. Esa nota sobrevive a las actualizaciones de imagen, y es la diferencia entre una lista de privilegios revisada y una que creció a base de copiar y pegar.