openvpn 2fa
Setup OpenVPN + 2fa
The way it works is that openvpn besides only allowing guest with a valid certificate it will prompt users for a username and password in where username is a system user and password is the OTP generated by the google authenticator.
First you need to install google-authenticator
:
pkg install pam_google_authenticator
Next create the file /etc/pam.d/openvpn
with this contents:
auth required /usr/local/lib/pam_google_authenticator.so
The openvpn configuration should look like this:
# ------------------------------------------------------------------------------
# routed VPN
# ------------------------------------------------------------------------------
port 1194
proto udp
dev tun
topology subnet
server 172.16.13.0 255.255.255.0
tun-mtu 1400
ca keys/ca.crt
cert keys/server.crt
key keys/server.key
dh keys/dh2048.pem
tls-auth keys/ta.key 0
key-direction 0
push "dhcp-option DNS 4.2.2.2"
push "dhcp-option DNS 8.8.8.8"
push "redirect-gateway def1"
client-config-dir ccd
plugin /usr/local/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
duplicate-cn
cipher AES-256-CBC
auth SHA512
comp-lzo
max-clients 100
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 4
keepalive 20 40
# certificate revoking list
# crl-verify keys/crl.pem
Notice the line:
plugin /usr/local/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn
The client side should be something like this:
client
dev tun
proto udp
remote X.X.X.X 1194
resolv-retry infinite
nobind
persist-key
persist-tun
comp-lzo
key-direction 1
cipher AES-256-CBC
auth SHA512
verb 3
auth-user-pass
auth-nocache
<ca>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
-----END OpenVPN Static key V1-----
</tls-auth>
Notice the:
auth-user-pass
auth-nocache
🔗Add users (create & sign certs)
First create user certificate by doing something like (this can be created by user and the admin could only sign the cert):
openssl req -new -newkey rsa:2048 -nodes -out guest.csr -keyout guest.key -subj "/C=DE/ST=Germany/L=Berlin/O=acme/OU=IT/CN=guest"
With the server key you need to sign the guest.csr
:
openssl x509 -req -in guest.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out users/guest.crt -days 7
In this case the guest.crt
will be only valid for 7 days.
🔗create the 2fA codes for the user
The easy way is to create / add user to the system adduser
, once the user has been created you could run this command:
su - guest -c google-authenticator
This will create a file in the guest
user $HOME: /home/test/.google_authenticator
:
$ cat .google_authenticator
35NIQ7S2T44WT5ZC
" RATE_LIMIT 3 30 1510594908 1510594922
" WINDOW_SIZE 17
" DISALLOW_REUSE 50353163
" TOTP_AUTH
53344656
94746893
13420893
11387169
23988009
The 35NIQ7S2T44WT5ZC
is the seed / code you need to use within your app that
generates the codes for example in authy it will be here:
This should be enough for a starting point.
To test that the pam
settings are working you could use pamtester
, for example:
# pamtester -v openvpn guest authenticate
pamtester: invoking pam_start(openvpn, test, ...)
pamtester: performing operation - authenticate
Verification code:
pamtester: successfully authenticated
The verification code should be the one generated by your application.