Uncategorized

OpenVPN with dual layer authentication (keys and pam)

Currently, my original ‘how-to’ on getting OpenVPN running with OpenVPN-GUI used the standard key based authentication. You can configure your client to password protect your connection, but I wasn’t comfortable with that scheme. If a laptop is stolen, it would be possible (and not hard to bypass this password). Now, we can add a additional layer with pam and server side interaction.

We still need keys to create the tunnel and send our authentication, so the ‘base’ security layer is untouched, but now we’re going to add pam to authenticate our user. This can be handy if you’re creating multiple VPN users, simply removing their system account, will remove their ability to VPN, etc.

Currently, my original ‘how-to’ on getting OpenVPN running with OpenVPN-GUI used the standard key based authentication. You can configure your client to password protect your connection, but I wasn’t comfortable with that scheme. If a laptop is stolen, it would be possible (and not hard to bypass this password). Now, we can add a additional layer with pam and server side interaction.

We still need keys to create the tunnel and send our authentication, so the ‘base’ security layer is untouched, but now we’re going to add pam to authenticate our user. This can be handy if you’re creating multiple VPN users, simply removing their system account, will remove their ability to VPN, etc.

To do this (and assuming that we already have a working OpenVPN setup), we will need to make some change to our server config as well as client configs. This how-to is based on a Gentoo, install, so others may have to play with various pam settings to get this to work.

First item is to make sure that OpenVPN is built with pam support. Here are my current USE flags:


[ebuild R ] net-misc/openvpn-2.0.6 USE="examples pam ssl threads -iproute2 -minimal -passwordsave (-selinux) -static" 650 kB

With pam added a .so file is compiled and is available on our system. We will need to add this to the server configuration


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

Note: system-auth is needed for Gentoo, this could be login for other linux distros.

Remember to restart OpenVPN and verify the start up was fine by verifying the logs.


/etc/init.d/openvpn restart

Now, pam will look at system users for to authenticate against. But, while I was writing this, I felt that this could be a bit tighter, since any ‘valid’ user with a password will allow the VPN connection. I thought restricting this to the vpn group might be the best way.

I first created the vpn group


groupadd vpn

Then I added a user to test with


useradd -s /bin/false -g vpn vpntestuser
passwd vpntestuser

To restrict OpenVPN to only allow users in the vpn group, we need to make some changes to the plugin call, but first we need to make a quick adjustment in pam. I copied /etc/pam.d/system-auth to a new file called /etc/pam.d/ovpn. I did this because we’re going to be using pam_listfile.so and did not want to taint system-auth with my change, since this would break things like SSH.. not good. pam_listfile.so uses a list to determine access by either group or user, since I don’t want to continually add to this list, I felt that group was the way to go.

We need to create the list, and I created mine here:


/etc/security/vpn.group.allowed

This file has one line with a single value


vpn

We now have a group.allowed value, so we need to adjust our /etc/pam.d/ovpn to use this. Here is the copy of my ovpn file:


#%PAM-1.0
auth required pam_listfile.so onerr=fail item=group sense=allow file=/etc/security/vpn.group.allowed
auth required pam_env.so
auth sufficient pam_unix.so try_first_pass likeauth nullok
auth required pam_deny.so

account required pam_unix.so

# This can be used only if you enabled the cracklib USE flag
password required pam_cracklib.so difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3
# # This can be used only if you enabled the cracklib USE flag
password sufficient pam_unix.so try_first_pass use_authtok nullok md5 shadow
# # This can be used only if you enabled the !cracklib USE flag
# # password sufficient pam_unix.so try_first_pass nullok md5 shadow
password required pam_deny.so
#
session required pam_limits.so
session required pam_unix.so

As you can see, pam_listfile.so will fail on error, check group and use the file we created. Since we’re moving away from system-auth to ovpn, we need to adjust the openvpn.conf with this new value:


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

Again, remember to restart OpenVPN when done.

Ok. We’re lookin’ good on the server side of things. We need to make a simple change to our client side OpenVPN config. Simple add this single line to your config, and you’ll be using a combination of keys and user/pass authentication to connect to your vpn:


auth-user-pass