This article explains how to set up OpenVPN with Google Authenticator on pfSense. I’m using pfSense 2.4.2 but the method shouldn’t change much. If you follow along you’ll end up with a VPN server that asks for the user’s username, a pre-set PIN (4-8 numbers) and a one-time generated code from Google Authenticator on your phone. The PIN + the OTP will be the user’s password.

I will not explain the inner workings of Google Authenticator or OpenVPN on pfSense. Other articles on my site can help you set up OpenVPN on pfSense. (Follow this one but skip the Active Directory part.) This will not work if you use Active Directory to authenticate VPN connections; you would need OTP on AD or some other method to achieve that.

Using this method an adversary would need to:
– have your laptop (because of the certificate);
– know your username and your PIN;
– have your phone with Google Authenticator.

If this article has helped you feel free to click some of the ads on this site. It will not make me rich but it would let me know someone appreciates my work and it helps a little to pay for hosting this site. If you’re really ecstatic about it there’s a PayPal donation button on the right :)

Every step is followed by a screenshot, so text first, picture next.

Install the FreeRADIUS package from System > Package Manager > Available Packages.

Set up the FreeRADIUS interfaces:

Services > FreeRADIUS > Interfaces | Add

Interface IP Address
Port 1812
Interface Type Authentication
IP Version IPv4
Description Authentication

Services > FreeRADIUS > Interfaces | Add

Interface IP Address
Port 1813
Interface Type Accounting
IP Version IPv4
Description Accounting

Add a NAS client (pfSense’s User Manager is the client).

Services > FreeRADIUS > NAS/Clients | Add

Client IP Address
Client IP Version IPv4
Client Shortname pfsenseclient
Client Shared Secret think up a passphrase.
Client Protocol UDP
Client Type other
Require Message Authenticator No
Max Connections 16
NAS Login empty
NAS Password empty
Description pfSense

Add an authentication server so pfSense can authenticate using FreeRADIUS:

System > User Manager > Authentication Servers | Add

Descriptive Name localfreeradius
Protocol PAP
Hostname or IP address
Shared Secret enter your passphrase here.
Services offered Authentication and Accounting
Authentiocation port 1812
Accounting port 1813
Authentication Timeout 5

Add your users. For each user:

Services > FreeRADIUS > Users | Add

Username vorkbaard
Password empty
Password Encryption Cleartext-Password
One-Time Password [x] Enable One-Time Password (OTP) for this user
OTP Auth Method Google-Authenticator
Init-Secret click Generator OTP Secret
PIN enter 4-8 numbers and remember them.
QR Code click Generate QR Code.

At this point open Google Authenticator on your phone and click the + sign to add a service and select ‘Scan a bar code’. Then scan the QR code. You may need to install a bar/QR code scanner first. Afterwards you may rename the entry.

Miscellaneous, Network and Time Configuration, Traffic and Bandwidth and Advanced Configuration can all be empty and except for Time Configuration I don’t think they would have any influence on the VPN.

Verify you can log in with Diagnostics > Authentication.

Authentication Server localfreeradius
Username vorkbaard
password your PIN + your current Google Authenticator code

Check with a wrong PIN/code:

Check with the correct PIN/code:

It should say ‘User vorkbaard authenticated successfully.’ If it doesn’t, check under Status > System Logs > System > General.

In the OpenVPN Server configuration choose localfreeradius as the Backend for authentication.

If you connect your OpenVPN client you must enter your username and the PIN + the Google Authenticator one-time code as your password.

One more thing: OpenVPN renegotiates the authentication every 3600 seconds. But a Google Authenticator code is only valid for 30 seconds. So then renegotiation will fail and you will be disconnected and asked to re-enter your password (your PIN + your current Google Authenticator code). That’s ok and it works but you may want to change that behaviour.

The relevant setting is reneg-sec and you must set it to the number of seconds after which you want the negotionation to occur. 3600 is the default but you could set it to a higher value like a day. Use 0 to disable it altogether. Here I’m using 0; use however many you like.

Keep in mind that this value is used at the client and the server and the shortest value counts so you must change both.
– In the OpenVPN Server configuration, under Advanced Configuration > Custom options, add: reneg-sec 0

– Under Client Export > Advanced > Additional configuration options also add: reneg-sec 0 (click Save as default if you don’t want to add it manually every time you export a config).