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 | 127.0.0.1 |
Port | 1812 |
Interface Type | Authentication |
IP Version | IPv4 |
Description | Authentication |
Services > FreeRADIUS > Interfaces | Add
Interface IP Address | 127.0.0.1 |
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 | 127.0.0.1 |
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 |
Type | RADIUS |
Protocol | PAP |
Hostname or IP address | 127.0.0.1 |
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).
Thanks a lot for this great article!
Great tutorial. Thanks.
Thank you for the detailed write up. Was somewhat stuck w/ the 2FA bit but then I found your article. Very much appreciate it!
I would LOVE if you added to your instructions explaining what/why some things are done/needed. It would really enrich the experience. For instance: The very first thing you say is to add Interface address. Why that specific address, etc. Thanks and I’ll try to set it up and see what happens.
Hi Lorne, there’s a link in the second paragraph of this article to one that does just that. This is just an addendum.
Okay, so far all seems pretty straight forward until I get to the last set of instructions. VPN/OpenVPN/Server/Edit: You talk about General settings and the reneg-sec 0, but you left out all of the other settings. Cryptograpic settings, Tunnel settings, Client settings, Advanced client settings. Assuming that is all default, produce and error of The selected certificate is not valid, and The field IPv4 Tunnel network is required.
There are so many settings that describing all of them would be to reproduce the PfSense Manual. Most of those are preferences. This article is meant to explain how to add Google Authenticator to an already working vpn implementation on PfSense. It says so right in the beginning.
Follow-up. I’ve used this page many times so thank you. However, I’ve just run into some followup info. 2.4.4 is out now and there are some changes.
1. In System/User Manager/Authentication Servers: there is an additional box that is not intuitive. The last line has added: “RADIUS NAS IP Attribute”. Your choices are what ever ports you have. The assumption is there is WAN and LAN.
2. All of a sudden my dyndns is not updating, so i suspect a problem with the update and I’m still researching that.
Keep up the good work.
Hello Kapitein Vorkbaard, very nice your articles from pfsense, very easy and very effective, congratulations for the work, I would like to know if you have already done some project related to the captive portal with freeradius3 + ldap, if we share it would help me, my lack of knowledge me force to seek more …
Hi Felipe, this sounds for a fun holiday project. Unfortunately for me there is no holiday in sight. Perhaps later this year!
vacation, what do you mean? kkkk, Congratulations again for your work
Thanks for the contributions. I would like to know how to make a project using PfSense’s FreeRADIUS3 LDAP, in which it connects to the Active Directory server and uses it as authentication for the captive portal.
Hi,
if someone is facing this probem: Warning: [/usr/local/etc/raddb/mods-config/attr_filter/access_reject]:11 Check item “FreeRADIUS-Response-Delay-USec” found in filter list for realm “DEFAULT” after going through the manual I have a solution that worked for me.
Cert Manager -> Certificates -> Create a server type cert for Free Radius and link it to the default FreeRADIUS CA.
Go to Services -> Free Radius -> EAP -> SSL CA should be the defaut one (FreeRADIUS CA). Then for Server SSL Certificate set the newly created server type cert.
Test in again in Diagnostics -> Authentication.
Pingback: Απομακρυσμένη σύνδεση και ασφάλεια στο γραφείο με χρήση Firewall, PfSense, DuckDNS, OpenVPN και VNC - taxonomy.gr | Λογιστικό Γραφείο Καβάλα
Pingback: Απομακρυσμένη σύνδεση και ασφάλεια στο γραφείο, με χρήση Firewall, PfSense, DuckDNS, OpenVPN και VNC - taxonomy.gr | Λογιστικό Γραφείο Καβάλα
If you want use radius not only for VPN, but for pfsense administrative users too, simple add in services / FreeRADIUS / Users in advanced section RADIUS user reply attribute:
Class := “admins”
Thanks for the tutorial. very useful!
It worked.. thanks.
Once you have 2fa working using google authenticator you will be able to use programmable hardware tokens (e.g. Deepnet Security”s Diamond Token) as a direct replacement for google authenticator – this might be handy if you don’t want 2fa authentication to be dependant upon having your mobile phone with you.
Great article. Looks like Sophos is using this solution on their firewalls with the user/pwd taken from LDAP indtead. How about the opposite? Connect pfsense to do a site to site VPN using a 2FA interactive password with user credentials. I have it working but pfsense asks for password only once on the console during boot so if the connection drops it forces a reboot. I don’t have control of the remote server.
Great tutorial! Thanks a lot! Everything still works with pfSense 2.5.2 Community edition. Also I prefer the “Microsoft Authenticator” to the Google’s one – cleaner interface and ability to backup (if you’d like so) – wanted to confirm that it’ll work with the same QR code generated for “Google Authenticator” and you don’t need to create or login with Microsoft account in order to use it. You only need to login with Microsoft account if you’d like to backup the config.
How did you export VPN client configuration? I didnt see any user in that section.
Why do you choose PHP as Radius Protocol? PAP is not secure and submits the password in a not secure way!
Thanks for this highly informative article!
One thing you may want to emphasize is that for authentication to require *both* user certificate *and* Google Authenticator (TOTP), the user will have to exist both in the local user database *and* in FreeRADIUS.
At least that’s my experience after running through your example. Please correct me if I’m wrong.