Running as non-root user

In the simplest case, OpenConnect needs to be run as the root user in order to make changes to the system networking configuration. If it cannot create the local tun network interface, you will see an error such as:

  Failed to bind (TUNSETIFF) tun device: Operation not permitted
or in older versions, "TUNSETIFF failed: Operation not permitted". The path of least resistance is to run OpenConnect as root.

However, in some cases authentication needs to run as the unprivileged user — to access crypto tokens, password managers, for SAML authentication to spawn the user's browser, etc.

Even with plain password authentication it is better for security reasons if network-facing code can run without root privileges — so there are a few options which allow OpenConnect to run without root privileges.

Pre-configured tun device

On Linux, it's possible to create its tun device in advance. For example:

# ip tuntap add vpn0 mode tun user dwmw2

This creates a device vpn0 which can be opened by user dwmw2 who can pass traffic to/from it without needing any elevated privileges. You can now tell OpenConnect to use that device by adding "-i vpn0" to its command-line arguments. Note that the /dev/net/tun device node should be readable and writeable by everyone, since only privileged users can create or attach to tunnel devices anyway. (Some distributions misconfigure that, so if it isn't world-writeable then please file a bug against your distribution.)

Of course, something does also need to configure the IP addresses and routing. You could either add "-s /bin/true" to OpenConnect's command line to stop it trying to run vpnc-script for itself, and manually configure the network as root too. Or you could use "-s 'sudo -E /etc/vpnc/vpnc-script'" so that OpenConnect itself runs without elevated privileges but can still invoke vpnc-script as root. Note the -E part which ensures the environment variables with the configuration are actually passed through to vpnc-script.

NetworkManager usually has a dedicated unprivileged user nm-openconnect and runs OpenConnect as that user, having pre-created the tun device for it. OpenConnect then invokes a "vpnc-script" provided by NetworkManager which just passes all the configuration back to NetworkManager over DBus.

Authenticate separately as yourself

A simpler option which works on non-Linux systems is just to run the authentication stage as your own user, passing the resulting authentication cookie to an openconnect process which runs as root. You can use the --authenticate option to OpenConnect, with a script such as the following:

#!/bin/bash

COOKIE=
eval `openconnect --authenticate "$@"`
if [ -z "$COOKIE" ]; then
    exit 1
fi

sudo openconnect --servercert "$FINGERPRINT" "$CONNECT_URL" --cookie-on-stdin ${RESOLVE:+--resolve "$RESOLVE"} <<< "$COOKIE"

Care must be taken to ensure that the second stage openconnect connects directly to the same server that the authentication ended at, after any any redirections, etc.

The same trick can be used to allow for more flexible authentication from the command line, while NetworkManager controls the actual connection:

  nmcli con up 'My VPN Configuration' passwd-file /proc/self/fd/5 5<<EOF
vpn.secrets.cookie:$COOKIE
vpn.secrets.gwcert:$FINGERPRINT
vpn.secrets.gateway:$CONNECT_URL
vpn.secrets.resolve:$RESOLVE
EOF

SOCKS / port-forwarding proxy

An alternative option which doesn't require any root access at all, is simply not to create the tun device and modify the system's network configuration. Instead, OpenConnect can spawn a user-supplied program, passing all data traffic through a UNIX socket to that program.

This option can be used in conjunction with a userspace TCP stack such as lwip to provide SOCKS access to the VPN, without requiring root privileges at all.

SOCKS proxy implementions suitable for being used from OpenConnect include: