home > security > 2fa > openvpn-with-2fa

OpenVPN with 2fa

| 01 Jun 2015

OpenVpn with 2fa Setup

How to setup OpenVPN with two factor authentication, tls-auth for packet filtering, and high grade ciphers to keep your data well encrypted.

This solution is totaly free and open source and as secure as vpn's get.

Install via Ansible Galaxy

If you don't want to setup the vpn yourself, or you want it in a hurry, you can use my ansible code.

Software Used

Overview of solution

Once setup, when authenticating to your VPN service the following authentication process will occur;

  1. A TLS handshake will be established.
  2. You will be asked for your username and 2fa token (OATH-TOTP)
  3. Your Certificates / Keys will be used to verify and encrypt your data.

Install and configure OpenVPN

First checkout easyrsa3, it's the easiest way to manage a number of certs for different users.

git clone https://github.com/OpenVPN/easy-rsa

Once checked out you'll first want to edit the default vars this will save you time whilst creating certs as well as strengthen the security by upping the certs from sha1rsa 1024 bit to sha256rsa 4096 bit.

cd easy-rsa/easyrsa3
cp vars.example vars
vi vars

Full example setup:

set_var EASYRSA_REQ_PROVINCE    "London"
set_var EASYRSA_REQ_CITY    "London"
set_var EASYRSA_REQ_ORG    "Organisation"
set_var EASYRSA_REQ_EMAIL    "user@domain.uk"
set_var EASYRSA_REQ_OU        "Org Unit"
set_var EASYRSA_KEY_SIZE    4096
set_var EASYRSA_ALGO        rsa
set_var EASYRSA_CA_EXPIRE    3650
set_var EASYRSA_CERT_EXPIRE    3650
set_var EASYRSA_CRL_DAYS    180
set_var EASYRSA_DIGEST        "sha256"

Then setup your certs:

./easyrsa init-pki
./easyrsa build-ca
nohup ./easyrsa gen-dh &
./easyrsa build-server-full

finally create a new cert for each user using;

./easyrsa build-client-full

Use your package manager to install OpenVPN and generate a tls authenticatio key

yum install openvpn
apt-get install openvpn
openvpn --genkey --secret ta.key

edit the config file; /etc/openvpn/server.conf. A template copy of this config file can be found by using mlocate.

yum/apt-get install mlocate; updatedb; locate openvpn | grep sample-config-files

A complete config file example:

plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-pam.so openvpn
local [PUBLIC IP]
port 1194
proto udp
dev tun
ca /etc/openvpn/easyrsa3/pki/ca.crt
cert /etc/openvpn/easyrsa3/pki/issued/main.crt
key /etc/openvpn/easyrsa3/pki/private/main.key
dh /etc/openvpn/easyrsa3/pki/dh.pem
ifconfig-pool-persist ipp.txt
client-config-dir ccd
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS"
push "dhcp-option DNS"
push "dhcp-option DNS"
push "dhcp-option DNS"
keepalive 10 900
tls-auth /etc/openvpn/easyrsa3/pki/ta.key 0
cipher AES-256-CFB8
auth SHA512
max-clients 100
user vpndata
group vpndata
status openvpn-status.log
log openvpn.log
verb 1
reneg-sec 10800

The key config settings are;

1. plugin /usr/lib64/openvpn/plugin/lib/openvpn-auth-pam.so openvpn
This is the pam plugin that we will be using to setup 2fa.

2. tls-auth /etc/openvpn/easyrsa3/pki/ta.key 0
The tls auth key generated with "openvpn --genkey --secret ta.key", acts as a packet filter and can protect from DoS attacks. This is in addition to the tls-cipher (double TLS).

3. tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA
The tls cipher list provided by openvpn actually just prints all tls ciphers supported by openssl, as any not supported by openvpn will be supported by openssl. Should you choose to you can specify a list of acceptable tls ciphers.

4. cipher AES-256-CFB8
To get a list of ciphers supported by your version of openvpn you can use "openvpn --show-ciphers", if you are using NetworkManager in linux you can roll back to "AES-256-CBC". This is one of the most important values as this is the cipher used to encrypt your data.

5. auth SHA512
This setting will authenticate packets signed with a HMAC-SHA512, you could leave it at HMAC-SHA1 (the default), yubico have an article on why HMAC-SHA1 is not vulnerable as SHA1 is. However I chose to up this regardless.

6. reneg-sec 10800
The vpn will by default request users to re-authenticate every hour, dependant on your client tool this can cause issues, so consider increasing this value to 3 hours.

Google Authenticator Pam Module

checkout the google authenticator pam module using git, build it and add a line to the pam configuration for openvpn.

git clone https://github.com/google/google-authenticator/
cd google-authenticator/libpam/
autoreconf --install
make install
locate pam_google_authenticator.so
vi /etc/pam.d/openvpn

# google auth
auth        required    /usr/local/lib/security/pam_google_authenticator.so

account        required    pam_nologin.so
account        include        system-auth
password    include        system-auth
session        include        system-auth

Once the pam module is inplace all you'll need to do is execute google-authenticator as a vpn user, and save the stored OATH-HOTP or OATH-TOTP into either google-authenticator or a 2fa security device like the Yubico Yubikey.

Example output from the google-authentication setup tool:

[bob@test1001 ~]$ /usr/local/bin/google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Your new secret key is: VPVDLLGGJHYLWR6A
Your verification code is 640702
Your emergency scratch codes are:

Do you want me to update your "/home/bob/.google_authenticator" file (y/n) y

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y

By default, tokens are good for 30 seconds and in order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with poor
time synchronization, you can increase the window from its default
size of 1:30min to about 4min. Do you want to do so (y/n) y

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y

Setting Up The Client to Connect

Download the following files from your vpn server;

  1. ta.key
  2. ca.crt
  3. "client".crt
  4. "client".key

Then edit a file for the OpenVPN config; vi my-vpn.ovpn

dev tun
proto udp
remote [PUBLIC IP]
ca ca.crt
cert "client".crt
key "client".key
comp-lzo yes
script-security 2
reneg-sec 10800
tls-auth ta.key 1
cipher AES-256-CFB8
remote-cert-tls server
auth SHA512

and finnaly you can connect with:

openvpn --config my-vpn.ovpn

Post a Comment