FIDO2 Two-Factor Authentication with OpenVPN and Viscosity
After setting up your own OpenVPN server, you may want to enhance it's security. One way to do that is to use 2FA (Two Factor Authentication). This adds another security measure to prevent unwanted users connecting to your server. One type of 2FA is FIDO2, otherwise known as CTAP2 or WebAuthn, with a YubiKey or Windows Hello, though other hardware and software tokens are supported. This guide will expand on setting up an OpenVPN server on Ubuntu by adding FIDO2 support to that server using Viscosity's built in FIDO2 support which was added in version 1.8.7.
For this guide, we assume:
- You have already installed the latest version of Ubuntu LTS (18.04 or 20.04 at time of writing)
- You have root access to this installation
- You have already an OpenVPN server running using one of our guides
- You already have a copy of Viscosity installed on your client device and already setup for this server
- Your copy of Viscosity is at least version 1.8.7
- Your copy of Viscosity is running on Windows 10 1809 or newer, or macOS 10.13 or newer
- You have a YubiCo YubiKey that supports FIDO2 or Windows Hello enabled
- Your OpenVPN server has a Fully Qualified Domain Name (FQDN), more information below.
This guide assumes you have followed one of our server setup guides and you are already able to connect to the server we will be modifying using certificate/key authentication. This guide will add two more authentication steps. A username and password using PAM, and a challenge request using FIDO2.
PAM authentication is the simplest form of username/password authentication we can use with OpenVPN. PAM uses the Ubuntu's user management to authenticate against so we don't need to manage an extra database of username and passwords. If you want to add a new user to be able to authenticate, you can simply add the new user with the useradd command in Ubuntu.
A final requirement to support FIDO2 is your server must have a FQDN. FIDO2 requires that you must connect to your OpenVPN server with a domain name, not an IP Address. A dynamic DNS service is fine if you are connecting back to your home for a server you are hosting on a VPS though for example, we recommend you register a domain address, something like myserver.mydomain.com.
The follow instructions for Ubuntu assume that you have already setup an OpenVPN server using our Setting up an OpenVPN server with Ubuntu and Viscosity guide.
As this is a newer type of 2FA, OpenVPN needs some modifications to support FIDO2. We've done the heavy lifting for you for Ubuntu 18.04 and 20.04, however if you would like to view the patch, or recompile OpenVPN yourself, you can download the patches here and here, or view them in our PPA.
First, remove your current OpenVPN install and any other apt repo's you have added for OpenVPN, we're assuming you've followed our Ubuntu guide:
sudo systemctl stop [email protected]
sudo systemctl disable [email protected]
sudo apt remove openvpn
sudo rm /etc/apt/sources.list.d/openvpn-aptrepo.list
sudo rm /etc/apt/sources.list.d/openvpn-aptrepo.list.save
sudo apt update
Next, add our PPA so you can install the modified version of OpenVPN:
sudo apt install software-properties-common
sudo add-apt-repository ppa:sparklabs/ppa
Press Enter to confirm
And the install the modified OpenVPN, the FIDO2 plugin for OpenVPN and other requirements.
sudo apt update
sudo apt install openvpn openvpn-fido2-plugin python3-pip
To confirm you've installed the right version of OpenVPN, during the last step you should see a version of OpenVPN installed containing 'u2f', for example:
Setting up openvpn (2.4.8-1ubuntu1u2f2)
Installing FIDO2 Requirements
Now OpenVPN will support FIDO2, we can configure the server for FIDO2. The plugin uses a python script which interfaces with the python-fido2 package. This can be installed via pip:
sudo python3 -m pip install fido2
Now we can configure our OpenVPN server.
Setting up OpenVPN
Now all the requirements we need are installed and setup, we can interface FIDO2 with OpenVPN. First, we need to modify our OpenVPN server configuration. Make a copy of the existing server and edit the configuration:
sudo cp /etc/openvpn/server.conf /etc/openvpn/fido2.conf
sudo nano /etc/openvpn/fido2.conf
Scroll to the bottom of the configuration and on a new line add the following, replacing 'myserver.mydomain.com' with your server address (your remote):
#FIDO2 and PAM plugin plugin /usr/share/openvpn/pam-fido2/auth-pam-fido2.so login setenv fido2_origin myserver.mydomain.com setenv fido2_name "My OpenVPN FIDO2 Server" #Uncomment the below if you wish to change the path for the script #setenv fido2_script_path /usr/share/openvpn/pam-fido2/auth-fido2.py #Auth-gen-token for renegotiation without needing to use token auth-gen-token
You can also change "My OpenVPN FIDO2 Server" to something more appropriate if you wish, this name may be displayed by some operating systems.
Save the configuration and then start up the new server.
That's it, our server is ready to go with FIDO2 support! We just need to make a quick change to our configuration, read on.
Changing Token Support
There are a couple of tweaks that can be made to narrow down the types of FIDO2 devices you support. To do this, edit the script at
/usr/share/openvpn/pam-fido2/auth-fido2.py, and scroll down to the buildFIDO2Registration function, about line 120. Here you will see two variables you can change. If you change either, simply save the script and the next login attempt will use the new settings, there is no need to restart the OpenVPN server.
If you decide to make changes, we recommend you copy the script somewhere else and set the script path in the OpenVPN configuration as any updates from APT-GET in the future will override your changes.
This effectively sets whether a users token needs to have a login. It can have three values:
- discouraged - No extra login/pin required for the token. This is best for Yubikeys which have a gold pad to tap - preferred - Prefer a token needs a pin. For example if this is set, Windows will require you set a PIN to use a Yubikey if it supports it, though will still allow a device that does not support a pin/password login to be used. - required - Only tokens which have support for a PIN are allowed to be used by a user.
This is commented out by default, which allows any type of authenticator to be used. It has the following values that can be set though:
- cross-platform - Only devices, like a YubiKey, which can be transported to different machines can be used. If you wish to use YubiKeys, we recommend setting this value. - platform - Only devices built into a PC, like a finger print reader or Windows Hello can be used
The credentials file is stored at /etc/openvpn/creds.pickle by default. Each line in this file presents a user. If you wish to remove a users registered authentication device so they can register again, simply remove the line beginning with their username.
This plugin is designed to be an example script to get you started. As such it does not support options like multiple devices per user or complex user IDs. The script should be simple to modify however to interface with your IDMS of choice which supports FIDO2.
Setting up Viscosity
Now the server is setup, we only need to make a single change to Viscosity:
- Open Viscosity's Preferences and edit your connection.
- Go to the Authentication tab and tick 'Use Username/Password authentication'
- Save the connection
If during this guide you registered a dynamic DNS or domain name for your OpenVPN server, also change your servers IP address to the new address.
Now that the changes to your configuration in Viscosity are finished, you can connect to the VPN server to test the connection. The first time you connect you'll be prompted to register your FIDO2 security device. Simply follow the on-screen instructions by connecting your key to your computer, and if required tapping the gold disk or button on the device to activate and register it.
By default, when first registering to connect to the server, all devices will be able to be used. If you have both Windows Hello and a Yubikey for example, you may need to click Cancel if you receive a Windows Hello prompt first, then a prompt for your Yubikey will be displayed instead. When Authenticating after this, only the device you registered with will be prompted for.
Once you have registered your device, or if it is already registered, you'll be prompted to authenticate using your security key. Again, simply make sure your key is connected to your computer, and if required tap the gold disk or button on the device to activate it and authenticate. Your VPN connection will then proceed to connect if authentication was successful.