LXC/OpenVZ OpenVPN TUN/TAP error

Al intentar levantar OpenVPN dentro de un contenedor LXC o OpenVZ en Proxmox, el servicio da error. Los logs como journalctl -u openvpn@server.conf o /var/log/openvpn.log no son de ayuda pues no indican el motivo del error. La única forma de ver el error es invocar directamente en la consola openvpn.

El error para un contenedor LXC es similar a:

1
2
3
4
5
6
7
8
[root@OpenVPN openvpn]# openvpn /etc/openvpn/server.conf
Sat Jun 25 09:07:07 2016 OpenVPN 2.3.11 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on May 10 2016
Sat Jun 25 09:07:07 2016 library versions: OpenSSL 1.0.1e-fips 11 Feb 2013, LZO 2.06
Sat Jun 25 09:07:07 2016 Diffie-Hellman initialized with 4096 bit key
Sat Jun 25 09:07:07 2016 Socket Buffers: R=[212992->212992] S=[212992->212992]
Sat Jun 25 09:07:07 2016 ROUTE_GATEWAY 192.168.100.1/255.255.255.0 IFACE=eth0 HWADDR=36:30:32:39:35:65
Sat Jun 25 09:07:07 2016 ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such file or directory (errno=2)
Sat Jun 25 09:07:07 2016 Exiting due to fatal error

El error para un contenedor OpenVZ es similar a:

1
2
3
4
5
6
7
8
9
[root@OpenVPN openvpn]# openvpn /etc/openvpn/client.conf
Sun Jun 26 06:23:46 2016 OpenVPN 2.3.11 x86_64-redhat-linux-gnu [SSL (OpenSSL)] [LZO] [EPOLL] [PKCS11] [MH] [IPv6] built on May 10 2016
Sun Jun 26 06:23:46 2016 library versions: OpenSSL 1.0.1e-fips 11 Feb 2013, LZO 2.06
Sun Jun 26 06:23:46 2016 Socket Buffers: R=[133120->133120] S=[133120->133120]
...
...
Sun Jun 26 06:23:49 2016 ROUTE_GATEWAY ON_LINK IFACE=venet0 HWADDR=00:00:00:00:00:00
Sun Jun 26 06:23:49 2016 ERROR: Cannot open TUN/TAP dev /dev/net/tun: Operation not permitted (errno=1)
Sun Jun 26 06:23:49 2016 Exiting due to fatal error

El problema reside en que el contenedor no puede acceder al dispositivo de caracteres (sin buffer) /dev/net/tun.

Solución para LXC

Configurar Proxmox

Es necesario permitir al contenedor el acceso al dispositivo de caracteres /dev/net/tun. Esto se hace añadiendo al archivo de configuración del contenedor el parámetro lxc.cgroup.devices.allow indicando:

  • Tipo de dispositivo: b para un archivo especial de bloques (con búfer), c para un archivo especial de caracteres (sin búfer), p para un FIFO. Más información en man mknod.
  • ID de dispositivo: Los ID de dispositivos están formados por dos partes, el major ID y el minor ID. Tradicionalmente el major ID identifica el driver asociado al dispositivo aunque en los kernels modernos varios drivers pueden compartir major ID por lo que actualmente se podría decir que los major ID identifican la clase del dispositivo; mientras que el minor ID identifica el dispositivo exacto. Más información en man makedev y en el capítulo Char Drivers, página 43, de Linux Device Drivers.
  • Permisos cgroup para el dispositivo: pudiendo ser una composición de r para lectura, w para escritura y m para mknod.

Para obtener el major ID y el minor ID tan solo es necesario listar los dispositivos de caracteres o de red, y buscar el dispositivo tun:

1
2
3
4
root@promox:~# ls -lah /dev/char/ | grep tun
lrwxrwxrwx 1 root root 10 May 18 11:17 10:200 -> ../net/tun
root@promox:~# ls -l /dev/net/ | grep tun
crw-rw-rw- 1 root root 10, 200 May 18 11:17 tun

En el ejemplo anterior, el major ID es 10 y el minor ID 200.

Una vez recopilada esta información, tan es necesario añadir lxc.cgroup.devices.allow = c 10:200 rwm al archivo de configuración del contenedor /etc/pve/lxc/ID.conf.

En el ejemplo de a continuación se hace para el contenedor con ID 100103:

1
2
3
cat >> /etc/pve/lxc/100103.conf << EOF
lxc.cgroup.devices.allow = c 10:200 rwm
EOF

Configurar el contenedor

Llegados a este punto el contedor tiene permisos para acceder al dispositivo especial de caracteres /dev/net/tun, sin embargo este dispositivo no existe en el contenedor LXC por ello es necesario crear un servicio systemd para automatizar la creación del archivo /dev/net/tun

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat >> /etc/systemd/system/create-net-tun.service << EOF
[Unit]
Description=Create /dev/net/tun device
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/bin/mkdir /dev/net
ExecStart=/usr/bin/mknod /dev/net/tun c 10 200
ExecStart=/usr/bin/chmod 666 /dev/net/tun
[Install]
WantedBy=openvpn@.service
EOF
systemctl enable create-net-tun

Por último solo queda apagar y encender el contenedor.

Solución para OpenVZ

Configurar Proxmox

Añadir CAPABILITY="NET_ADMIN:on" y DEVNODES="net/tun:rw" al archivo de configuración del contenedor OpenVZ. A continuación un ejemplo para el contenedor con ID 1103

1
2
3
4
5
6
7
8
9
vzctl stop 1103
cat >> /etc/pve/openvz/1103.conf << EOF
CAPABILITY="NET_ADMIN:on"
DEVNODES="net/tun:rw"
EOF
vzctl start 1103
vzctl exec 1103 mkdir -p /dev/net
vzctl exec 1103 mknod /dev/net/tun c 10 200
vzctl exec 1103 chmod 600 /dev/net/tun

Entradas de interés

Contenidos
  1. 1. Solución para LXC
    1. 1.1. Configurar Proxmox
    2. 1.2. Configurar el contenedor
  2. 2. Solución para OpenVZ
    1. 2.1. Configurar Proxmox