This article attempts to gather all relevant information about OpenVPN privilege separation into one place. This includes use-cases, requirements, design and implementation details, etc. Currently this is very much work in progress. Please fill in the blanks and fix any errors.

OpenVPN consists of several different, interacting components:

Network utilitiesifconfig, route, etc.Yes
OpenVPNTunneling daemonYes
OpenVPN serviceSystem service wrapperYes
OpenVPN GUIGUI for interactive usersYes
OpenVPN configurationConfig files, keys, certificates, etc.No
TUN/TAP interfaceVirtual Ethernet interfaceNo

Each executable component runs as an operating system user with varying levels of privileges. Here we use the following terms:

  • Interactive user. This is the user account the end user uses to log in to the operating system. Most end-user applications run as this user, so it should be granted as few privileges as possible.
  • Unprivileged user. Any unprivileged user account. Not the same as the interactive user. For example, on many Linuxes OpenVPN runs as such, usually nobody:nogroup, after initialization.
  • Privileged user. Any user account that can do privileged operations. In OpenVPN context these operations are things such as adding routes or bringing up the TUN/TAP interface.

Depending on the use-case, different levels of privileges are needed to satisfy all the requirements.

OpenVPN use-cases

Standalone workstations

Standalone workstations and their VPN clients are controlled by the end-user. As such, attempts to control the VPN client by the VPN server administrator are guaranteed to fail. The goals of privilege separation in this use-case are:

  • Minimize damage a VPN client can do to the workstation if it's compromised
  • Minimize the actions VPN client can do due to valid server instructions.
  • User is at full control of its VPN configuration.

Enterprise workstations

Enterprise workstations and their VPN clients are controlled by the enterprise system administrator(s). The system administrator's goal is to lock down client workstations as much as possible. The goals of privilege separation in this use-case are:

  • Prevent a compromised VPN client being used by malware or remote attackers to access the enterprise network.
  • Prevent user to modify VPN client behavior.
  • [In future] Allow server to execute privileged commands to harden workstation during VPN connection.

For the VPN client this translates to the following requirements:

  • Non-privileged users can't read, copy or modify the VPN configuration
  • Workstations can't have simultaneous access to an untrusted network (e.g. the public Internet) and the VPN network. If they did, malware could spread from the untrusted network to the enterprise network [alonbl: this is not true as a standalone requirements, there might be a similar configuration]

Practical privilege separation models (enterprise use-case)


This solution was suggested by James Yonan. According to him it's fairly common in enterprise VPN clients:

ComponentRuns asTasks/capabilities
OpenVPN GUIInteractive userInitiate connections and disconnections
OpenVPN servicePrivileged userAccept connect/disconnect requests from the GUI. Control OpenVPN
OpenVPNPrivileged userSetting up TUN/TAP interfaces, routes, making connections, etc.

Using this approach, OpenVPN service provides a simple API that the OpenVPN GUI uses to connect and disconnect. The privilege separation is handled by Windows Services. To clarify, this is what happens when the interactive user wants to connect:

  1. OpenVPN GUI makes an API call to the OpenVPN service
  2. OpenVPN service asks OpenVPN to connect
  3. OpenVPN connects
  4. OpenVPN notifies OpenVPN service that connection has been established(?)
  5. OpenVPN service notifies OpenVPN GUI that connection has been established(?)

This separation model should not require any changes to current OpenVPN code, provided that local user does not have administrator privileges.

Details for successful implementation:

  • Fill me

alonbl notes

  1. API = what? This is exactly where COM comes handy... It creates the "service" for you while providing means of accessing it. Of course we can re-invent the wheel... Implementing the service by hand, and API via named pipe or socket... but why?
  2. I don't like the openvpn running under privileged account, if we want to take this seriously then we should separate the daemon out to unprivileged account, so that if it can be manipulated remotely the scope of damage will be known.
  3. What exactly privileged account is that? System? Network service? Administrator? I ask because we may need to modify the tap-windows configuration to use a specific ACL.
  4. The "notification" is exactly the current management interface, maybe I miss something...
  5. I still think the keys/certificates/peer validation should be delegated to the UI via the management interface, no matter what the privilege separation solution is.
  6. Doing PKCS#11 or CryptoAPI(CAPI) on service context will likely fail... as Windows progresses, the interactive devices are allocated only to the interactive user, also there is an issue with remote desktop, as only the interactive user can access the remote devices.

Interactive service

This approach was suggested by Heiko. At the moment the implementation is Windows-specific.

ComponentRuns asTasks/capabilities
OpenVPN GUIInteractive user
Interactive servicePrivileged userAct as a proxy between OpenVPN GUI and OpenVPN. Handles privileged operations on behalf of OpenVPN.
OpenVPNInteractive userConnect to the interactive service for privileged operations.

The interactive service is a new component that allows running privileged operations such changing routes by the unprivileged OpenVPN process. It's essentially a proxy the unprivileged OpenVPN/OpenVPN GUI application uses to do privileged operations.

Details for successful implementation:

  • Private key needs to be properly protected
    • From James Yonan: "To be complete, the wrapper [=interactive service] must also own the OpenVPN private key -- otherwise the configuration would be copyable by a non-privileged user, something that the enterprise model is determined to prevent. Protecting the private key can be accomplished by storing the key in the system cert/key store, and accessing the key through a Cryptographic Provider API such as Crypto API on Windows, PKCS#11 on Linux, or Keychain on Mac."
  • The interactive service must not allow access from non-OpenVPN processes running as the same user as OpenVPN/OpenVPN GUI
    • From James Yonan: "...the pipe/socket to the privileged process [=interactive service] needs to be access-controlled so that only openvpn can use it. You don't want to introduce a privilege escalation vulnerability where operations that would normally be privileged (like changing the default route) can now be done by any process in user space just by leveraging on the openvpn pipe/socket."
    • From James Yonan: "...other non-privileged software might be able to access the APIs for these wrappers [=interactive service], for example by pushing routes into the API. Malware that would normally be confined to user space can now perform privileged operations such as modifying the default route. The end user can now connect to any VPN server of their choice (a major violation of enterprise model). What you've essentially done with this model is introduce a privilege escalation vulnerability because operations that would normally require privilege, such as adding routes, can now be done by a non-privileged user."


This approach was suggested by Alon Bar-Lev. See the original email for more detailed information. In a nutshell, privilege separation would be achieved using COM+ objects:

ComponentCOM+ objectRuns asTasks/capabilities
OpenVPN GUI-Interactive userInitiate connections and disconnections. Run OpenVPN connect/disconnect scripts
Network configurationOpenVPNUI.NetworkPrivileged user (network operator group)Create and remove routes
OpenVPN serviceOpenVPNUI.TunnelAn unprivileged user accountAccess OpenVPNUI.Network object

The identity and access to the COM+ objects would be controlled by the COM+ infrastructure. This means COM+ would do all the work and no communication or security check within code are required. Each component of OpenVPN could be started in a different security context, e.g. OpenVPN service would run within a context that allows Network configuration.

Details for successful implementation:

  • Running OpenVPN daemon using completely unprivileged account.
  • Allowing OpenVPN to perform network operations by delegating these into OpenVPNUI.Network, this is optional if we would like to run OpenVPN daemon using completely unprivileged account.
  • The OpenVPNUI.Network may validate operations and allow [for example] only route into tap and/or tap configuration.
  • UI to run beforeconnect/connect/disconnect scripts.

Alonbl notes

  1. The OpenVPNUI.Network is only needed if we want to run the daemon under complete unprivileged account, if not, the OpenVPNUI.Tunnel is sufficient, and no need to change anything in openvpn.
  2. So at bottom line this solution is better than what James offered but with less code.
  3. The next mile is something that worth discussion, I think it is required for a proper solution for the entire problem, running the daemon as completely unprivileged account for enterprise configuration.
  4. Network configuration program has also [good] side effects... we could provide several "network configuration" executables, per platform, per security model, per utilities (ifconfig, iproute2), and split the platform dependent code from the openvpn executable, making it much simple as it uses a single interface. So we have advantage for this in all platforms.
  5. I provided the skeleton for this, so technology wise it is doable.
  6. I still think the keys/certificates/peer validation should be delegated to the UI via the management interface, no matter what the privilege separation solution is.

External links

Last modified 5 years ago Last modified on 03/14/12 12:12:34