Engineering, Operations & Cloud Security


OpenVPN at Scale. Part 1: Okta SSO VPN!

Back in July we did an OpenVPN “reboot”.

This is Part 1 of OpenVPN at Scale. Be sure to also read Part 2: Monitoring!

Back in May, our original VPN setup meant we had many OpenVPN instances, all carefully and manually crafted and built and an inconsistent way of managing user logins and passwords and MFA methods, none of which was self-service. Most of the time, resetting passwords or MFA required a back-and-forth in Jira.

It was basically friction and the antithesis of building for lazy #BeachOps.

Our goals were simple:

  • Consolidated our OpenVPNs into one (we had many).
  • Codify VPN setup, including VPC peering and host configuration in Terraform & Ansible.
  • Consolidate authentication using our SAML provider, Okta.

That last bullet led us down a very windy and not well-documented world.

So this blog post hopes to help the next persons searching for a how-to.

  • How to setup OpenVPN SSL certificates with Let’s Encrypt
  • How to use Okta as an LDAP provider
  • How to configure OpenVPN to use Okta LDAP
    • Tweaking authentication timeouts for Okta MFA
  • (How to debug Okta & LDAP)
  • How to login to OpenVPN with Okta & Okta MFA

We’ll generally assume you know how to install OpenVPN – we opted for the AWS Marketplace version.

We’re using (almost) real hostnames and users in the examples below but adjust as necessary.

Let’s Encrypt & OpenVPN

First things first, we secure the OpenVPN WebUI.

The following two guides were helpful:

Install Certbot. We used Ansible to do this part:


- block:

  - name: add certbot repository
      repo: "ppa:certbot/certbot"
      state: present
      update_cache: yes

  - name: install certbot
    package: name=certbot state=latest

Run Certbot. There are a couple ways to do this but we found the steps in the second post the easiest:

sudo certbot certonly \
  --standalone \
  --non-interactive \
  --agree-tos \
  --email YOUR_EMAIL \
  --domains YOUR_DOMAIN \
  --pre-hook 'sudo service openvpnas stop' \
  --post-hook 'sudo service openvpnas start'

Install the certificates. Certbot puts its files in /etc/letsencrypt/live/ and the easiest way was to symlink them. There’s a more complicated way that involves using the OpenVPN command line, sacli, and a couple ConfigPut but since these certificates will need to renew every 90-days or so, we went with symlinks:

sudo ln -s -f /etc/letsencrypt/live/YOUR_DOMAIN/cert.pem /usr/local/openvpn_as/etc/web-ssl/server.crt
sudo ln -s -f /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem /usr/local/openvpn_as/etc/web-ssl/server.key


Using Okta as an LDAP provider

We wanted to consolidate all authentications into Okta which already is already part of our IT processes. We also like that, for the most part, Okta has enough self-service for most things and is a central place to ensure password policies.

Enable Okta LDAP

Okta provides an LDAP Interface that lets us perform cloud-based LDAP authentication off Okta’s existing directory. Okta has docs over here but you can just start with this one.

There are only two things you have to do:

  1. In the Okta Admin console, go to Directory | Directory Integrations
  2. Click Add Directory | Add LDAP Directory

That’s it! You will want to make note of Host, & Base DN.

Add Okta/LDAP group (optional)

Unless you want everyone in your Okta organization to have access to OpenVPN, you’ll want to create an Okta group and add users to it. For simplicity, we went with a single word, lowercase group openvpn. Make a note of the group name you use.

Configuring OpenVPN & Okta LDAP

Create a Bind User. We created a specific, authenticated service account for the initial LDAP bind.

  1. Create Service Account, perhaps
  2. Disable MFA requirement for Service Account

We have to disable MFA for this Service Account since it’s not possible (or really hard?) to inject an MFA response for each LDAP bind request. Do this with care and adjust for your own local password rotation policy.

Disable MFA for your Service Account Okta user:

  • In the Okta Admin console, Security | Authentication
  • Edit your existing MFA policy and include your Service Account user in “Exclude Users”.

Configuring OpenVPN. You’ll need to enable LDAP now. In the OpenVPN Admin UI ( This is under Authentication | LDAP:

  • LDAP Settings | Primary server
  • Use SSL to connect to LDAP servers
  • Credentials for Initial Bind | Use these credentials
    • Use Bind DN & password for your Service Account
    • Example:,dc=lacework,dc=okta,dc=com
  • Fill in Base DN for User Entries (this comes from Okta in Directory | Directoroy Integrations | LDAP Interface, in case you lost it)
    • dc=lacework,dc=okta,dc=com
  • Fill in Username Atttribue: uid
  • Additional LDAP Requirement (group membership)
    • memberOf=cn=openvpn,ou=users,dc=lacework,dc=okta,dc=com

Caveat – OpenVPN Users

Quick note – LDAP users in OpenVPN don’t show up in User Management. If you need to adjust user permissions, for example enabling admin permissions, you’ll need to manually add their username and grant permissions.

Tweaking authentication timeouts for Okta MFA

Since OpenVPN will make an LDAP auth request to Okta and Okta will either make an MFA request (Okta Verify push notification) or expect one (software MFA), we need to increase the timeout that OpenVPN uses to wait for a response from LDAP:

/usr/local/openvpn_as/scripts/sacli --key "auth.ldap.0.timeout" --value 60 ConfigPut
/usr/local/openvpn_as/scripts/sacli start

[This hint was taken from the Foxpass docs “OpenVPN AS via LDAP“.]

Debugging LDAP

It’s been something like 42 years since any of us actually worked with LDAP. Testing this setup was a bit of manual debugging so we’ll leave the steps we used here.

Install LDAP tools:

sudo apt-get -y install ldap-utils

Use ldapsearch to test:

ldapsearch -H ldaps:// -b "dc=lacework,dc=okta,dc=com" -s sub -D ",dc=lacework,ou=users,dc=okta,dc=com" -W -z none -Z "("

Test LDAP group/memberOf searches:

ldapsearch -H ldaps:// -b "dc=lacework,dc=okta,dc=com" -s sub -D ",dc=lacework,ou=users,dc=okta,dc=com" -W -z none -Z "(&(objectClass=inetOrgPerson)(memberOf=cn=openvpn,ou=users,dc=lacework,dc=okta,dc=com))"

Logging in with Okta credentials & MFA

Worth nothing that using Okta for LDAP works best Okta’s push client, Okta Verify. It’s super seemless and depending on your OpenVPN client, your username & password may be stored by your OS.

  • Login to OpenVPN with your Okta username & password
  • Wait for push notification
  • Acknowledge the login request
  • You are logged in

However, if you’re using a software MFA token, your MFA token is entered as part of your password. The format of your password is “password-comma-MFA“. For example:

  • myPasswd42%,669922

This method works, of course, but also means that you’ll have to type your password each time you login to OpenVPN. YMMV.

Wrapping it all up

What more is there to say?

Write a Comment