YubiKey OTP 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 OTP (One Time Password) with a YubiKey. This guide will expand on setting up an OpenVPN server on Ubuntu by adding YubiKey OTP support to that server using Viscosity's built in Challenge/Request support.
For this guide, we assume:
- You have already installed the latest LTS version of Ubuntu (22.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
- You have a YubiCo YubiKey that supports OTP
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 a YubiKey's OTP support.
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.
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.
Modifying the Server
To get started, we need to update/upgrade our Ubuntu installation to prevent any conflicts.
sudo apt update
sudo apt upgrade
Next install Python PIP, this will allow us to install extra packages, install it by running the following from your Ubuntu server's command line:
sudo apt install python3-pip
Next, install PAM and yubico-client using PIP:
sudo python3 -m pip install yubico-client python-pam
Next you will need to download our script for OpenVPN to use. Do this with:
sudo wget https://raw.githubusercontent.com/thesparklabs/openvpn-two-factor-extensions/master/yubikey-otp/openvpn_otp_auth.py
After the file is in place, we need to make it executable by running:
sudo chmod +x /etc/openvpn/openvpn_otp_auth.py
We now need to get a YubiCo apikey for their cloud services for checking YubiKeys. To do this, go to https://upgrade.yubico.com/getapikey/ and simply follow the instructions to get your ClientID and Secret Key.
Finally, now we have our YubiKey cloud service keys, we need to modify the OpenVPN server configuration. First, stop the server using:
sudo systemctl stop openvpn@server
Then edit the server configuration using:
sudo nano /etc/openvpn/server.conf
Scroll all the way to bottom then on a new line add the following:
#Use a script to authenticate username/password and yubikey OTP setenv yubicoClientId YOURCLIENTID setenv yubicoSecretKey YOURSECRETKEY auth-user-pass-verify openvpn_otp_auth.py via-env script-security 3 #Auth-gen-token for renegotiation without needing to use token auth-gen-token
Replace YOURCLIENTID with your Client ID, and YOURSECRETKEY with your Secret Key and save the script.
Now find the following two lines:
user nobody group nobody
And comment them out, changing them to:
#user nobody #group nobody
Save the configuration then restart the server:
sudo systemctl start openvpn@server
Setting up Viscosity
Now the server is setup, we need to make two small changes to our configuration in Viscosity.
- Open Viscosity's Preferences and edit your connection.
- Go to the Authentication tab and tick 'Use Username/Password authentication'
- Go to the Advanced tab, then on a new line add:
static-challenge "Activate your YubiKey" 0
- Save the connection
The comment in quotes for the static-challenge command you added, i.e. "Activate your YubiKey" is what is displayed to the user when the YubiKey OTP password needs to be entered. You can change this message to whatever you like.
Now that changes to your configuration in Viscosity have been made, connect to the server to test the changes! You will see an extra Password window appear during the connection process, tap your YubiKey when you see it.