Estou tentando executar o servidor openvpn dentro do contêiner podman sem privilégios.
O Openvpn precisa ser capaz de gerenciar interfaces de rede (ou seja, criar uma interface tun, atribuir um endereço IP a ela, criá-la). No meu sistema (arch linux) dentro openvpn-server.service
eu notei CapabilityBoundingSet
e isso me fez experimentar e criar meu próprio serviço que ao invés de rodar o openvpn vai rodar podman run
.
Primeiro criei meu container openvpn, abaixo está o Dockerfile (usei archlinux como base por conveniência):
FROM archlinux
RUN pacman -Sy --noconfirm openvpn
Eu então construo este contêiner (sendo logado como my_unprivileged_user
)
podman build \
--force-rm \
--no-cache \
--rm \
--device=/dev/net/tun \
-t openvpn .
Então eu criei my_custom_openvpn.service
:
Description=OpenVPN in Podman container
After=syslog.target network-online.target
Wants=network-online.target
[Service]
User=my_unprivileged_user
Group=my_unprivileged_group
WorkingDirectory=/etc/openvpn
ExecStart=/usr/bin/podman run --rm --name openvpn -v ./server:/server --device /dev/net/tun --network "host" --cap-add CAP_IPC_LOCK,CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_SETGID,CAP_SETUID,CAP_SYS_CHROOT,CAP_DAC_OVERRIDE,CAP_AUDIT_WRITE localhost/openvpn:latest /usr/bin/openvpn --config /server/my_config.conf
ExecStop=/usr/bin/podman stop -t 0 openvpn
Capabilities=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
#ProtectSystem=true
#ProtectHome=true
RestartSec=5s
Restart=on-failure
TimeoutSec=5s
[Install]
WantedBy=multi-user.target
Então, pensei que o systemd passaria os recursos para o podman, que por sua vez os passaria para o openvpn.
Mas o openvpn falha ao começar a reclamar que não pode criar a interface tun0. Mesmo se eu mesmo criar o tun0 assim openvpn --mktun --dev tun0
, recebo outro erro de que o openvpn não pode configurar esta interface tun0.
Achei que talvez precisasse fazer setcap
dentro do container, então entrei podman exec
nele e executei abaixo:
setcap CAP_IPC_LOCK,CAP_NET_ADMIN,CAP_NET_BIND_SERVICE,CAP_NET_RAW,CAP_SETGID,CAP_SETUID,CAP_SYS_CHROOT,CAP_DAC_OVERRIDE,CAP_AUDIT_WRITE=+ep /usr/bin/openvpn
Mas isso não ajudou. Eu continuo recebendo esse erro:
Tue Jan 28 13:34:31 2020 /usr/bin/ip link set dev tun0 up mtu 1500
RTNETLINK answers: Operation not permitted
Talvez tentar usar recursos como esse não faça sentido?
Consegui fazer o openvpn funcionar substituindo
ip
dentro do contêiner pelo script bash que sempre retorna 0. Achei que a única coisa que o openvpn tenta fazer é configurartun0
e, em seguida, atribuir o endereço IP e ativá-lo. Decidi fazer isso manualmente de fora do contêiner (como root) e, portanto, o openvpn não precisa fazer isso. Eu descrevi o procedimento no wiki openvpn aqui