How to create /dev/tun device inside unprivileged LXC container?
This question is similar to No tun device in lxc guest for openvpn . The LXC has evolved and the unprivileged LXC containers were introduced recently that offer another layer of security against breaking the jail.
I need to create an OpenVPN server inside one of the unprivileged container. I don't know how to let the container create a private tun network device.
I did append lxc.cgroup.devices.allow = c 10:200 rwm
to the ~/.local/share/lxc/mylxc/config
.
After starting the container, mknod /dev/net/tun c 10 200
returns mknod: '/dev/net/tun': Operation not permitted
inside the container.
I use a vanilla Ubuntu 14.04 64bit as host and a container created with
lxc-create -t download -n mylxc -- -d ubuntu -r trusty -a amd64
Did anyone managed to get /dev/tun
device running under unprivileged LXC?
Solution 1:
You need to explicitly add the CAP_MKNOD capability to your container.
lxc.cap.keep Specify the capability to be kept in the container. All other capabilities will be dropped. When a special value of "none" is encountered, lxc will clear any keep capabilities specified up to this point. A value of "none" alone can be used to drop all capabilities.
You could also try to automate this (if you happen to use systemd
inside the container) using:
lxc.hook.autodev A hook to be run in the container's namespace after mounting has been done and after any mount hooks have run, but before the pivot_root, if lxc.autodev == 1. The purpose of this hook is to assist in populating the /dev directory of the container when using the autodev option for systemd based containers. The container's /dev directory is relative to the ${LXC_ROOTFS_MOUNT} environment variable available when the hook is run.
which can point to a script running mknod
.
Using docker
this is very easy to accomplish. By default, containers are unprivileged.
In this example, I'm pulling a trusty
container from the registry:
sudo -r sysadm_r docker pull corbinu/docker-trusty
Pulling repository corbinu/docker-trusty
...
Status: Downloaded newer image for corbinu/docker-trusty:latest
And I'm starting it in interactive mode informing about the capability I need inside:
sudo -r sysadm_r docker run --cap-drop ALL --cap-add MKNOD \
-i -t corbinu/docker-trusty bash
root@46bbb43095ec:/# ls /dev/
console fd/ full fuse kcore mqueue/ null ptmx pts/ random shm/ stderr stdin stdout tty urandom zero
root@46bbb43095ec:/# mkdir /dev/net
root@46bbb43095ec:/# mknod /dev/net/tun c 10 200
root@46bbb43095ec:/# ls -lrt /dev/net/tun
crw-r--r--. 1 root root 10, 200 Apr 6 16:52 /dev/net/tun
As opposed to:
sudo -r sysadm_r docker run --cap-drop ALL \
-i -t corbinu/docker-trusty bash
root@9a4cdc75a5ec:/# mkdir /dev/net
root@9a4cdc75a5ec:/# mknod /dev/net/tun c 10 200
mknod: ‘/dev/net/tun’: Operation not permitted