So I decided to give Ubuntu 16.04 a chance despite a slightly unfavorable view about systemd.
After the upgrade my previously persistent OpenVPN connection doesn't work anymore. Fortunately the system log is rather helpful in pointing to the root cause.
openvpn-up: + /sbin/iptables -t nat -D POSTROUTING -o tun0 -s 192.168.x.x -j SNAT --to-source 10.x.x.x openvpn-up: modprobe: ERROR: could not insert 'ip_tables': Operation not permitted openvpn-up: iptables v1.6.0: can't initialize iptables table `nat': Table does not exist (do you need to insmod?) openvpn-up: Perhaps iptables or your kernel needs to be upgraded. openvpn-up: + /sbin/iptables -t nat -A POSTROUTING -o tun0 -s 192.168.x.x -j SNAT --to-source 10.x.x.x openvpn-up: modprobe: ERROR: could not insert 'ip_tables': Operation not permitted openvpn-up: iptables v1.6.0: can't initialize iptables table `nat': Table does not exist (do you need to insmod?) ovpn-conn: WARNING: Failed running command (--up/--down): external program exited with error status: 3 openvpn-up: Perhaps iptables or your kernel needs to be upgraded. ovpn-conn: Exiting due to fatal error
openvpn-up were produced by uncommenting the second line of the
/etc/openvpn/openvpn-up.sh script (line reads:
exec &> >(logger -s -t openvpn-up) && set -x).
Hmm, so for some reason the
ip_tables module could not be loaded. After making sure to have the kernel modules all there with
apt-get install --reinstall linux-image-$(uname -r), I tried to use
modprobe ip_tables and sure enough saw it now loaded with
lsmod but also in the system log:
kernel: [ 446.293882] ip_tables: (C) 2000-2006 Netfilter Core Team
And sure enough when running
systemctl restart openvpn after this point, it seemed to bring up the connection and
iptables-save output proves that the appropriate SNAT rule was added.
My guess is now that the OpenVPN unit gets executed with some user context that doesn't have enough privileges to use
However, I've been unable to confirm this suspicion. And in fact the output of
systemctl cat openvpn confuses the hell out of me:
# systemctl cat email@example.com # /lib/systemd/system/openvpn@.service [Unit] Description=OpenVPN connection to %i PartOf=openvpn.service ReloadPropagatedFrom=openvpn.service Before=systemd-user-sessions.service Documentation=man:openvpn(8) Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO [Service] PrivateTmp=true KillMode=mixed Type=forking ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/%i.conf --writepid /run/openvpn/%i.pid PIDFile=/run/openvpn/%i.pid ExecReload=/bin/kill -HUP $MAINPID WorkingDirectory=/etc/openvpn ProtectSystem=yes CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_AUDIT_WRITE LimitNPROC=10 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw [Install] WantedBy=multi-user.target
Is there a capability which I need to enable the scripts to succeed invoking
modprobe? I'd like to avoid adding
CAP_SYS_ADMIN as this seems rather crude. Or is the only way to load the
ip_tables module by dropping a
Essentially what I am asking is this: how does a stock Ubuntu 16.04 (which has not been upgraded from 14.04) accomplish this task? I.e. What's the canonical (and Canonical) way of doing it? And last but not least how can I determine in which user context a particular unit runs (or to be more precise: with which capabilities)?