$ cat 'Configuring Google Authenticator on Ubiquity EdgeOS OpenVPN'

The following guide will help you to set up Google Authenticator based 2FA for OpenVPN on EdgeOS 2.0+ devices. It’s recommended to ensure you have another method to access your device in case you accidentally lose VPN access during the process. All steps should be run as root unless specified.

Install Dependencies

Run the following to install the required dependencies.

apt-get update
apt-get -y install libqrencode3 easy-rsa libpam-google-authenticator

Configure PAM

If you’d like to use a 2FA code and a certificate to log in without the user’s password, you can use (as root):

cd /etc/pam.d
cp common-account openvpn
echo "auth required /lib/mips-linux-gnu/security/pam_google_authenticator.so" >> openvpn

Otherwise, to require the user’s password as well as 2FA and certificate, use:

cd /etc/pam.d
cp common-account openvpn
echo "auth requisite pam_google_authenticator.so forward_pass" >> openvpn
echo "auth required pam_unix.so use_first_pass" >> openvpn

Configure OpenVPN

Configure OpenVPN to use the PAM configuration we set up previously.

configure
set interfaces openvpn vtun0 openvpn-option '--plugin /usr/lib/openvpn/openvpn-auth-pam.so openvpn'
commit
save
exit

Add New User

If you already have a user that you’d like to configure 2FA for, you can skip this step. I recommend you set up a new user to test this with though, to prevent accidentally locking your existing user out if the configuration doesn’t work.

You can run the following to generate a new user. Remember to switch out the USERNAME parameter to whatever you choose. The password parameter will be set to a random 64 character password.

export USERNAME=my-user
export PASSWORD=`cat /dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c64;`
configure
set system login user "${USERNAME}" authentication plaintext-password "${PASSWORD}" 
commit
save
exit
echo "Created user ${USERNAME} with password ${PASSWORD}."

Create User Certificate

Again, you can skip this step if you already have a certificate set up for the chosen user.

First we need to generate a certificate request for the user. Again, replace my-user in the below:

cd /usr/lib/ssl/misc
./CA.pl -newreq my-user

You’ll need to set the common name to the username of the user being added.

Next up we can sign the user’s certificate. You’ll need to enter the CA passphrase here.

./CA.pl -sign

And finally spit out the keys for the user, removing after they have been securely stored.

cat newcert.pem
cat newkey.pem
rm newcert.pem
rm newkey.pem

Configure 2FA

Configure 2FA for the user. Replace my-user with the user of your choice, and the label with whatever you like. When you run this you’ll see a QR code which you can scan to setup your 2FA app. Alternatively just copy the key from underneath the QR code.

sudo su -c "google-authenticator --label=\"My OpenVPN 2FA\"" my-user

You’ll be prompted to answer a few questions about the particular setup you want, which I encourage you to read and choose for yourself. Here are my typical selections:

Do you want me to update your "/home/my-user/.google_authenticator" file (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) n

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y

Next, ensure permissions for the Google authenticator setup are set to only allow access to the owner.

sudo chmod 400 /home/openvpn-user/.google_authenticator

Generate the Client Config

Finally, on the client machine, you’ll want an .ovpn config file to pass on to the user along with their certificate details.

I suggest creating a new directory to store this and the associated files.

You’ll want to replace the following placeholders:

Placeholder Value
{IP} The public IP of your Edge router in place of the placeholder on line 4.
{USERNAME} The username you created in the previous steps.
client
dev tun
proto udp
remote {IP} 1194
float
resolv-retry infinite
nobind
persist-key
persist-tun
verb 3
ca cacert.pem
cert {USERNAME}.pem
key {USERNAME}.key
auth-user-pass

Call this file config.ovpn.

The files which you stored earlier (the outputs of newcert.pem and newkey.pem should be written to {USERNAME}.pem and {USERNAME}.key respectively.

You should write the contents of /usr/lib/ssl/misc/demoCA/cacert.pem on the Edge router to cacert.pem.

At this point you should be able to connect to the VPN. Run:

sudo openvpn config.ovpn

The first password that is requested is your 2FA code. The subsequent passphrase will be your key passphrase that you entered when generating a certificate for the user.