OpenVPN en Docker no puede abrir /dev/net/tun: qué falta
Un nodo TUN y la capacidad de red son dos permisos separados. Abra ambos y luego lea el siguiente error en sus propios términos en lugar de repetir la misma solución.
Las imágenes de contenedor pueden llevar todos los binarios y archivos de configuración de OpenVPN que necesitan y aun así fallar en la primera llamada de red. El error menciona /dev/net/tun porque la aplicación pidió al núcleo una interfaz TUN y el contenedor no tenía ni el nodo de dispositivo ni la capacidad de crear uno. Son dos permisos separados, y arreglar uno deja el otro exactamente donde estaba.
Separarlos cuesta un comando a cada uno. El mensaje de error posterior le dice en qué frontera estaba realmente.
El nodo de dispositivo y la capacidad son dos puertas
El nodo de dispositivo es un objeto del sistema de archivos, así que un contenedor necesita verlo en su propio espacio de nombres de montaje. La capacidad es un permiso, así que el proceso necesita CAP_NET_ADMIN en el espacio de nombres donde se creará la interfaz. Pasar el dispositivo sin la capacidad le da un nodo que se abre y un ioctl que falla. Conceder la capacidad sin el dispositivo deja a la aplicación incapaz de abrir nada en absoluto, y por eso los dos suelen aparecer juntos en los ejemplos.
La configuración devices de Docker asigna el dispositivo del host dentro del contenedor, mientras que cap_add ajusta el conjunto de capacidades. Un bind mount de la misma ruta pone el archivo a la vista sin aplicar la semántica de acceso al dispositivo.
Reprodúzcalo fuera del archivo Compose
Antes de editar el servicio, compruebe que el host tiene el dispositivo y que un contenedor desnudo puede crear una interfaz. El comando de abajo es deliberadamente mínimo, y su único propósito es separar un problema del host de un problema de compose. Si falla, ningún cambio de compose ayudará.
ls -l /dev/net/tun
docker run --rm --cap-add NET_ADMIN --device /dev/net/tun:/dev/net/tun alpine sh -c 'apk add -q iproute2 && ip tuntap add dev tun9 mode tun && ip link show tun9'
Un nodo ausente en el host significa que el módulo tun no está disponible, lo que es una corrección del lado del host y no del contenedor. Un nodo que existe pero no puede abrirse dentro del contenedor apunta al acceso al dispositivo, y el mensaje dirá permission denied en lugar de no such file. El orden de esos dos fallos es todo el diagnóstico. Anote cuál vio antes de cambiar una opción.
Los errores posteriores a TUN son problemas distintos
En cuanto aparece la interfaz, el siguiente fallo tiene otro dueño. Los errores de autenticación significan que el túnel llegó al servidor y las credenciales fueron rechazadas, así que los cambios de capacidad no ayudarán. Un túnel que se establece mientras las aplicaciones siguen fallando apunta a rutas, reenvío, resolución DNS dentro del contenedor o la propia disposición de red del contenedor. Cada una de esas es una pregunta de red ordinaria que el permiso TUN no puede responder. Repetir la prueba original después de cada cambio evita que los fallos se fusionen en una sola impresión.
Copiar cada ajuste de un ejemplo que funciona es cómo una corrección mínima se convierte en una definición de servicio ilegible. Lleve solo los que este despliegue necesita y anote por qué está cada uno.
Verifique la interfaz dentro del contenedor
Compruebe la interfaz y el conjunto de capacidades desde dentro del contenedor en ejecución y no desde el host. Los comandos de abajo muestran el nodo de dispositivo, la lista de capacidades y si se puede crear una interfaz. Ejecútelos en el mismo contenedor que ejecuta el cliente, e instale las herramientas si la imagen es mínima.
ls -l /dev/net/tun
capsh --print | grep -i net_admin
ip link add dev tun9 type tun && ip link show tun9
Una capacidad presente en el bounding set pero ausente del effective set se comporta de forma distinta a una que nunca se concedió, y capsh muestra ambas. Si el nodo existe y la capacidad está ahí mientras la creación sigue fallando, el entorno de ejecución impone otra cosa, como un perfil seccomp o una política AppArmor que restringe la operación. Esa es una tercera frontera, documentada por el entorno de ejecución y no por la aplicación.
Anote los indicadores del contenedor, la imagen y el error exacto de cada intento. La próxima persona que lea esa nota podrá saber qué puerta estaba cerrada sin repetir toda la investigación.