Streamlining User Access To OpenVPN A Step-by-Step Guide To Setting Up SSO For Your OpenVPN Server with Keycloak

Vivek Matthew's avatar

Vivek Matthew

OpenVPN is widely used as a VPN solution across different cloud and in house datacenter solutions. While OpenVPN has an Open Source edition, with the basic default setup used in many cases, the administrator provisions the certificate in a .ovpn configuration file for each user in the organization. User can then connect to the VPN by importing the .ovpn configuration file in an OpenVPN client application.

While this is a quick way to get started with an OpenVPN setup, scaling this setup as more and more users connect to the VPN can become tedious. Additionally, revoking and rotating the certificate would need to be redone separately for each user.

Depending on the use case, an alternate method to consider is using a common certificate for all users and then leverage an OIDC compatible Identity Provider, like Keycloak, for authenticating individual users. This can be setup using pam-keycloak-oidc along with the PAM authentication support built-in to OpenVPN.

Keycloak

Keycloak is an open-source Identity and Access Management tool. For using OpenVPN with Keycloak, certain preliminary configurations need to be setup on Keycloak as mentioned in the pam-keycloak-oidc documentation:

  1. Create a Role, like openvpn

  2. Create a Client Scope, like pam_roles:

    • Protocol: openid-connect
    • Display On Consent Screen: OFF
    • Include in Token Scope: ON
    • Mapper:
      • Name: e.g. pam_roles
      • Mapper Type: User Realm Role
      • Multivalued: ON
      • Token Claim Name: pam_roles (the name of the Client Scope)
      • Claim JSON Type: String
      • Add to ID token: OFF
      • Add to access token: ON
      • Add to userinfo: OFF
    • Scope:
      • Effective Roles: openvpn (the name of the Role)
  3. Create a Client, like openvpn:

    • Client ID: openvpn (or whatever valid client name)
    • Enabled: ON
    • Consent Required: OFF
    • Client Protocol: openid-connect
    • Access Type: confidential
    • Standard Flow Enabled: ON
    • Implicit Flow Enabled: OFF
    • Direct Access Grants Enabled: ON
    • Service Accounts Enabled: OFF
    • Authorization Enabled: OFF
    • Valid Redirect URIs: urn:ietf:wg:oauth:2.0:oob
    • Fine Grain OpenID Connect Configuration:
      • Access Token Signature Algorithm: e.g. RS256 (we need to put this in the config file later)
    • Client Scopes:
      • Assigned Default Client Scopes: pam_roles
    • Scope:
      • Full Scope Allowed: OFF
      • Effective Roles: openvpn
  4. Assign the role openvpn to the relevant Group or User as required.

pam-keycloak-oidc

pam-keycloak-oidc will be used with OpenVPN's built-in PAM authentication in order to connect to Keycloak for authentication. To configure pam-keycloak-oidc on the OpenVPN server:

  1. Download the pre-compiled binary from the GitHub releases. If the pre-compiled binary is not available for the required architecture, compile the golang application as needed.

  2. Create a configuration file with the .tml extension such as pam-keycloak-oidc.tml:

# name of the dedicated OIDC client at Keycloak
client-id="openvpn"
# the secret of the dedicated client
client-secret="<client-secret>"
# special callback address for no callback scenario
redirect-url="urn:ietf:wg:oauth:2.0:oob"
# OAuth2 scope to be requested, which contains the role information of a user
scope="openvpn"
# name of the role to be matched, only Keycloak users who is assigned with this role could be accepted
vpn-user-role="openvpn"
# retrieve from the meta-data at https://<keycloak-domain>/auth/realms/<openvpn-realm>/.well-known/openid-configuration
endpoint-auth-url="https://<keycloak-domain>/auth/realms/<openvpn-realm>/protocol/openid-connect/auth"
endpoint-token-url="https://<keycloak-domain>/auth/realms/<openvpn-realm>/protocol/openid-connect/token"
# 1:1 copy, to `fmt` substituion is required
username-format="%s"
# to be the same as the particular Keycloak client
access-token-signing-method="RS256"
# a key for XOR masking. treat it as a top secret
xor-key="scmi"

Fill in the required configuration for <client-secret>, <keycloak-domain> and <openvpn-realm>.

  1. Test the PAM authentication with pam-keycloak-oidc and the configuration that was setup in the previous step:
export PAM_USER=<user-with-openvpn-role>
echo <password-for-user> | /opt/pam-keycloak-oidc/pam-keycloak-oidc

If the above outputs an Authentication succeeded message, then the pam-keycloak-oidc setup is complete!

OpenVPN

In order to use the pam-keycloak-oidc module with the PAM authentication in OpenVPN, the configuration is needed both in the OpenVPN Server and in the .ovpn configuration file used by the client. On the OpenVPN Server side:

  1. Add the following lines as required to the openvpn.conf:
# Enable PAM for user authentication
plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so "openvpn login USERNAME password PASSWORD"
auth-gen-token 43200 # To set an expiry for the token (in seconds)
setenv deferred_auth_pam 1 # To perform the PAM based authentication in the background when the connection is initiated
duplicate-cn # To allow multiple connections from a single certificate
  1. Configure the openvpn PAM authentication method by adding the following to /etc/pam.d/openvpn:
account	required			pam_permit.so
auth	[success=1 default=ignore]	pam_exec.so	expose_authtok	log=/var/log/pam-keycloak-oidc.log	/opt/pam-keycloak-oidc/pam-keycloak-oidc
auth	requisite			pam_deny.so
auth	required			pam_permit.so

Configure the path for /var/log/pam-keycloak-oidc.log and /opt/pam-keycloak-oidc/pam-keycloak-oidc as per the locations of these files on the system.

  1. Configure the PAM session handler by adding the following to /etc/pam.d/common-sesion:
session required      pam_mkhomedir.so   skel=/etc/skel umask=0002

Next, in the OpenVPN Client configuration .ovpn file, add the auth-user-pass configuration. This option configures the OpenVPN client to prompt the user for a username and password in order to authenticate and connect to the VPN.

With this setup complete, OpenVPN is now integrated with Keycloak for authentication!

Next Steps

Using pam-keycloak-oidc, it is possible to enforce the requirement of MFA with TOTPs for connecting to OpenVPN. Depending on the OpenVPN client used and the Authentication policy on the Keycloak server, the setup can be configured as described in the pam-keycloak-oidc documentation.