User > Tor > VPN > Internet doesn't work in Whonix 16 / 17

In Whonix 15, with OpenVPN 2.4, it was easy to Tor > VPN > Internet, but since Whonix 16 (based on Debian Bullseye) has OpenVPN 2.5, iproute isn’t available and lots of other changes, and as such Tor > VPN > Internet is not working as per documentation.

I am making the changes in Whonix Workstation as per the docs.

The issues:

1) In the openvpn config file iproute ( iproute /usr/bin/ip_unpriv ) no longer works in openvpn 2.5 and as such it throws off

Options error: Unrecognized option or missing or extra parameter(s) in /etc/openvpn/openvpn.conf:26: iproute (2.5.1)
Use --help for more information.

when trying to connect. If iproute is commented out then

ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)

even if dev tun0 is present in the config file.

2) If OpenVPN is compiled with --enable-iproute2, then error

RTNETLINK answers: File exists
ERROR: Linux route add command failed: external program exited with error status: 2

3) If Whonix workstation Firewall is modified as per the docs i.e.

WORKSTATION_FIREWALL=1
TUNNEL_FIREWALL_ENABLE=true

then there is no internet connectivity in the workstation, even after reboot.

I have verified the signatures and both the Gateway and Workstation VM are ok (uncorrupted).

System Specs:
Windows 7 (Host)
Virtualbox VM ( Virtualbox Version 6.1.34)

Debian dropped --enable-iproute2 as suggested by upstream. Source:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=976070

For potential approach to research / fix this, see:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=976070#10

Maybe helpful search term:

openvpn unprivileged Netlink

The abstract thing to be found out is:

How to run OpenVPN unprivileged using netlink?

related user documentation wiki page:

Hi @Patrick

The discussions on the iproute issue in these two threads:

https://phabricator.vyos.net/T3805

The workaround suggested was

Remove user & group directives from /etc/openvpn/openvpn.conf and to add Ambient Capabilities and User=tunnel and Group=tunnel to a separate .service file (which, in our case, would be /lib/systemd/system/openvpn@openvpn.service.d/50_unpriv.conf).

So, I modified the 50_unpriv.conf file as follows

[Unit]
ConditionPathExists=!/run/qubes/this-is-templatevm

[Service]

User=tunnel
Group=tunnel
SecureBits=keep-caps
ExecStartPre=/usr/bin/sudo --non-interactive /usr/sbin/openvpn --rmtun --dev tun0
ExecStartPre=/usr/bin/sudo --non-interactive /usr/sbin/openvpn --mktun --dev tun0 --dev-type tun --user tunnel --group tunnel
AmbientCapabilities=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

ExecStopPost=/usr/bin/sudo --non-interactive /usr/sbin/openvpn --rmtun --dev tun0

I did a **sudo systemctl daemon-reload** and ran the debug process steps including sudo -u tunnel openvpn /etc/openvpn/openvpn.conf. But this didn’t work and gave the following error:

	2022-06-20 07:38:04 us=410798 net_iface_mtu_set: mtu 1500 for tun0
	2022-06-20 07:38:04 us=410867 sitnl_send: rtnl: generic error (-1): Operation not permitted
	2022-06-20 07:38:04 us=410936 Linux can't set mtu (1500) on tun0
	2022-06-20 07:38:04 us=410985 Exiting due to fatal error

The solution that worked for me:

I gave the Ambient Capability directly to the Openvpn executable with user=tunnel privileges, and nothing in the systemd service:

sudo /sbin/capsh --keep=1 --user='tunnel' --inh='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' --addamb='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' -- -c 'openvpn /etc/openvpn/openvpn.conf'

Refer: How do I use capsh: I am trying to run an unprivileged ping, with minimal capabilities - Unix & Linux Stack Exchange

I also checked out Openvpn process for capabilities related to user=tunnel

user@host:~$ sudo grep Cap /proc/23712/status
	CapInh:	00000000200474c2
	CapPrm:	00000000200474c2
	CapEff:	00000000200474c2
	CapBnd:	000001ffffffffff
	CapAmb:	00000000200474c2
user@host:~$ sudo capsh --decode=00000000200474c2
0x00000000200474c2=cap_dac_override,cap_setgid,cap_setuid,cap_net_bind_service,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_sys_chroot,cap_audit_write

This works! But I don’t want to use this route as this might not be the best way to go about it.I now have a binary that can be executed by any user, which I don’t really like.

Why wasn’t systemd able to set the Ambient Capabilities in case of user=tunnel whereas capsh was able to? How to make this work with systemd? Is this an issue of SELinux?

My working config file for OpenVPN: (without iproute and User directive)

client
dev tun0
proto tcp

remote X.X.X.X 443

server-poll-timeout 20

remote-random
resolv-retry infinite
nobind

# The following setting is only needed for old OpenVPN clients compatibility. New clients
# automatically negotiate the optimal cipher.
cipher AES-256-CBC

auth SHA512
verb 4

setenv CLIENT_CERT 0
persist-key
persist-tun

reneg-sec 0

remote-cert-tls server
auth-user-pass /etc/openvpn/auth.txt
pull

script-security 2
up "/etc/openvpn/update-resolv-conf script_type=up dev=tun0"
down "/etc/openvpn/update-resolv-conf script_type=down dev=tun0"

<ca>
-----BEGIN CERTIFICATE-----

---------------------------
-----END CERTIFICATE-----
</ca>

key-direction 1
<tls-auth>
# 2048 bit OpenVPN static key
-----BEGIN OpenVPN Static key V1-----
-----------------------------------
-----END OpenVPN Static key V1-----
</tls-auth>
1 Like

That’s excellent progress!

Using systemd and its capabilities seems the right approach.

Could you please consider to Improve the Documentation / Edit the Whonix ™ Wiki?

Which binary? The sudo /sbin/capsh command? Well, it still requires sudo. So not worsening the security model.

I appreciate the --non-interactive as this makes potential issues in the future easier to debug.

I don’t think systemd units should ever use sudo. ExecStartPre / ExecStartPost can if desired run as root while ExecStart does not and runs as a limited user.

  • That is systemd config under [Service]:
    • PermissionsStartOnly=true

  • An alternative to this is:
    • ExecStartPre=+

    • ExecStartPost=+

Can anyone provide and how to guide how to do this on latest Whonix? OpenVPN/WireGuard
Thank you.

Highly unlikely. Somebody needs to pay someone (not me) to figure this out. But even that is not likely.

These bugs have been fixed according to above bug reports. But I didn’t test it.