OpenVPN Authentication Using PAM and Duo Security
You just need to think like a hacker… By using password concatenation with OpenVPN’s PAM plugin and Duo Security’s plugin, your password will be comma-delimited, supporting both a PAM integrated password and Duo Security’s phone authentication.
I wasn’t satisfied with OpenVPN’s options for two-factor authentication. I configured OpenVPN with client certificates and Active Directory password integration via pam_winbind, but I wanted better security.
Knowing that it’s possible for an attacker on a compromised workstation to grab both the certificate and the user’s password (by keylogging or, depending on the OpenVPN configuration, memory scraping), I felt I needed a second out-of-band factor.
But since the Duo Security’s OpenVPN plugin utilizes the password field to input your method of authentication, this poses a problem to your existing PAM integration. The problem is, OpenVPN sends the same password to both plugins. Therefore, simply using your existing PAM plugin with Duo’s plugin isn’t an option.
…unless we make some modifications.
Why you’d want to do this
- You don’t want the workstation to be the single point of compromise (for both factors when using certificates and passwords).
- You don’t want to password-protect your certificates because that would be a static password.
- You want to use your existing password policies and lockouts with AD or some form of LDAP.
- Duo Security has made phone authentication easy, powerful and slick.
No reason to rehash steps for which there are already good tutorials. Make sure you have the following steps completed and working before moving on:
- Get password authentication working with pam_winbind (we will force OpenVPN to use this PAM module later).
- Install OpenVPN and create user certificates (Note: the CN field in the user certificate MUST equal the username for the user). Your clients should be able to authenticate with certificates only at this point.
- Set up your Duo Security account with OpenVPN integration and users.
Patching the plugins
Both plugins need minor patching to split the concatenated password. The following patches will split based on the rightmost comma.
Patch OpenVPN’s auth-pam plugin
- Download OpenVPN source and extract
- Download the auth-pam patch
- Patch and compile auth-pam.c
tar -xzvf ./openvpn-2.2.2.tar.gz -C /usr/local/src/
patch < auth-pam.patch
cp ./openvpn-auth-pam.so /usr/lib/openvpn/
Patch Duo Security’s OpenVPN plugin
- Download the Duo OpenVPN plugin
- Download the duo_openvpn patch
- Patch and compile duo_openvpn
- Follow the remainder of duo_openvpn installation starting at ‘Configure the server config’ and stopping when you come to ‘Test your step’
wget -O duosecurity-duo_openvpn.tar.gz https
tar -xzvf duosecurity-duo_openvpn.tar.gz
patch < duo_openvpn.patch
make && make install
Setup a PAM configuration for OpenVPN
Place your PAM configuration in the following location: /etc/pam.d/openvpn
I use pam_winbind and my configuration is below. It allows only users that are in the ‘vpnusers’ group defined in Active Directory. You can really use any PAM module if it is configured correctly. I haven’t tested with pam_ldap, but it should work without any problems.
auth [success=1 default=ignore] pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass require_membership_of=DOMAIN\vpnusers
auth requisite pam_deny.so
auth required pam_permit.so
- Add the following lines in your OpenVPN server config/s (`IKEY`, `SKEY` and `HOST` are assigned by Duo Security in the admin interface when you setup an ‘integration’)
- Restart OpenVPN
- Test your configuration Connect with an OpenVPN client and, when prompted for a username and password, enter your password in the following fashion: ad_intergrated_password,phone
plugin /usr/lib/openvpn/openvpn-auth-pam.so openvpn
plugin /opt/duo/duo_openvpn.so IKEY SKEY HOST
sudo /etc/init.d/openvpn restart
OpenVPN will defer authentication while Duo calls the phone that is provisioned for that user to then accept the connection.
You can also test other methods. Scroll to the bottom of Duo Security’s OpenVPN documentation page to see the supported factor identifiers.
If you are having troubles authenticating and it’s not obvious in either server or client logs, start by disabling the Duo plugin and making sure your client can connect with just certificates and the PAM authentication.
It’s also best to increase the verbosity in the server-side logs by adding ‘verb 7’ in the server configuration. This will help with displaying the debug output of the plugins.
A successful PAM authentication in the OpenVPN server logs will return a
status=1 is a failure. This plugin call output will looks like this:
PLUGIN_CALL: POST /usr/lib/openvpn/openvpn-auth-pam.so/PLUGIN_AUTH_USER_PASS_VERIFY status=0
If you are successfully connected and your tunnel re-keys every hour, make sure your server config and client configs have matching reneg-sec statements. Otherwise, re-keying will happen with whichever one is the lowest. A non-defined reneg-sec statement defaults to one hour.