Openvpn – How to enable 2-factor auth using Google Authenticator for .ovpn file based openVPN access

google-authenticatoropenvpn

I have an openVPN setup where the users do not have shell accounts on the Debian VM running openVPN. The articles I found while Googling all have instructions of setting up Google Authenticator for a classical *nix user (needing to execute the Authenticator binary in the user's home directory, for example).

Is there a doc explaining how to integrate Google Authenticator for openvpn servers that authenticate based solely on .ovpn files used on the client side?

I looked at https://github.com/evgeny-gridasov/openvpn-otp , but it still requires configuring Google Authenticator.

Best Answer

No. Of course you can't do that. This would defeat the very purpose of 2FA. Your server must have a way to verify the user credentials, and this info shouldn't be sent over the network (ie. you can't use solely the client.ovpn file).

While you don't necessarily have to create unix users, but you must let your users install their verification codes to the server. You can use sftp with virtual users using their already issued certificate, https with client side (mutual) authorization, CIFS (samba), or good old ftp with TLS extension or any other way which let the server know the verification codes created by the users. The communication channel should be secure (encrypted || local).

Naturally if your users upload their own files, you cannot use the aggregated file based credentials used by openvpn-otp. Fortunately we have another (and much better) option by using linux excellent security module pam.

First of all, you have to collect the user files created by google-authenticator in a directory by one of the methods mentioned above. In our case it will be /etc/google-auth.

You must enforce single user-id for all files here, because you don't have real users. Let it be openvpn. The permissions must be 0400 (-r--------). Pam don't like world/group readable credentials (certainly). You can easily enforce this with either samba, apache, ftp or at the worst case using a cron tab (not recommended).

For test purpose, just do this:

mkdir /etc/google-auth
apt-get install libpam-google-authenticator
google-authenticator
# set up as you wish, save image and/or codes
mv ~/.google_authenticator /etc/google-auth/some_username
chown -R openvpn /etc/google-auth

After that you ask openvpn to authenticate against libpam, which has its own google auth module. Append this to your openvpn server file:

plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so openvpn

This says we will use the pam authentication method with the pam auth id openvpn.

Now, create the pam setup for openvpn. Edit /etc/pam.d/openvpn :

auth    requisite       /lib/security/pam_google_authenticator.so secret=/etc/google-auth/${USER}  user=openvpn
account    required     pam_permit.so

Here we say that without successful google authentication we fail immediately (requisite), we are using a special secret file instead of the default $HOME/.google_authenticator (secret=) and we access the files as user openvpn since there is no real userid associated with our users. In the next line we just say we allow everyone to connect after successful authentication. Of course you should implement your own permission policy here. You can control permitted users by file, mysql db or ldap with the respective pam modules.

Append this to your openvpn client file

   auth-user-pass
   auth-nocache
   reneg-sec 0

We use auth-user-pass to let the openvpn client to ask for username and password. We don't like caching ("password" is changing) and periodical re-negotion is bad for us for the same reason.

After that you should be able to connect without openvpn-otp. Please consider this is much more flexible method, since you can implement very complex rules in pam control files if you wish. You can enable/disable users based on your mysql or ldap directory without touching those certificates for example.