Multi-Factor Authentication In OpenVPN

This project was done as a part of Mozilla Winter of Security 2014 programme. The objective of this project is to implement native Multifactor Authentication Support for OpenVPN. The existing support for Multifactor Authentication in OpenVPN is through deferred C plugins and pythons scripts which has lots of limitations due to the nature they are implemented.

Need to Native MFA support

The plugins are present on the server side where they are called at appropriate places in the authentication process of OpenVPN with credentials. But on the client side, openVPN provides the users options for authenticating through static keys, username/Password or certificates. There is no support for entering OTP or any other credential here. This user ahs to resort to using hacky ways to circumvent this limitation like entering the OTP cancatenated with password which can lead to even more limitations on the length of password and so on. An example plugin, used by mozilla, can be found at https://github.com/mozilla-it/duo_openvpn .

This method can also limits the type of credentials that can be taken from the user. Typical Multifactor Authentication solutions also provide Push notifications on smartphones as a way for authentication along with the regular OTP method. Native Support for Multifactor Authentication in OpenVPN will help in supporting these modes of authentication.

Another use of native MFA support can be maintaining user sessions so that the user does not have to enter the second factor of authentication every time he/she logs in but say only once in a month. These reasons demand for native MFA suport in OpenVPN.

MFA Implementation

Our scheme of implementation provides support for three different types of authentication: OTP, Push and User-pass (as of yet) in addition to the certificate check that happens as a part of the normal TLS handshake.

We have modified the key-method 2 packet structure used for authentication to include MFA credentials. MFA username and password are sent to the script/plugin in a manner similar to the existing auth-user-pass soution . In case of OTP when there is no username, CN of the user is sent as username. In case of PUSH, CN is sent as username and an empty string as password. Three types of plugins are supported for MFA, one for each of push, otp and user-pass.

The type for push is - OPENVPN_PLUGIN_AUTH_MFA_PUSH_VERIFY

for otp - OPENVPN_PLUGIN_AUTH_MFA_OTP_VERIFY

for user-pass - OPENVPN_PLUGIN_AUTH_MFA_USER_PASS_VERIFY

MFA Usage and Config

In the server config, put the supported authentication methods as follows

mfa-method method-type [script_file via-env|via-file]
Here method type can be ‘otp’, ‘push’, ‘user-pass’. For example

mfa-method otp auth.pl via-file

The three methods differ in what credentials are asked from the user for authentication. In otp, only password is asked. In push, nothing is asked. This is meant for authentication by Push notification on mobile phones which can be handled by a deferred auth plugin on the server side. In user-pass, both username and password are asked from the user. If you want to use a plugin for authentication on the server, include the following lines in the config

mfa-method method-type
plugin plugin_shared_object_file

In the client config, put the following line

mfa-method mfa-type

User can authenticate using one method only. Multiple mfa-method lines will give an error.

Session Support Implementation

On startup the OpenVPN server generates a random key (48 bytes). When a client successfully authenticates with MFA enabled, the server generates a session token using the tls1_PRF function with the key as the secret and (Client CN + Expiry timestamp) as the data. The expiry timestamp and the token are sent to the client. When the client wants to connect later, it must send the token and the expiry timestamp. If verification succeeds, MFA auth is bypassed. If not, auth fails and the client is prompted for MFA authentication if the auth-retry directive is set to “interact”.

Session Support Usage and Config

The server needs to provide the following configuration option:

mfa-session-expiration session-validity

session-validity is the duration (in hours) for which the session cookie is valid.

The client needs to provide the following configuration option:

mfa-session-file filename

filename is the path to the file in which session tokens will be stored. If the filename is not provided, then we warn the user and disable session-support.

Code, Demo and Presentations

The code for this project can be found at https://github.com/mozilla/openvpn. The project wiki can be found here.

A video where we have explained the project and given a demo is present here.