OpenVPN + LDAP + OTP MFA
In the following post I will describe how to configure your existing OpenVPN server to support OTP MFA along with LDAP authentication.
I already had a working OpenVPN + Radius authentication with Active Directory on a Debian Server, but in order to add OTP as MFA, I had to switch to LDAP authentication.
Packages installed:
sudo apt install libpam-ldapd oathtool libpam-oath qrencode pamtester
After installing libpam-ldapd, you are asked to Configure nslcd and nssswitch.
You may enter some default config and edit this later.
The most importand config file is /etc/nslcd.conf, and after each edit remember to restart nslcd service!
sudo service nslcd restart
/etc/nslcd.conf
uri ldap://ldap.local
# The search base that will be used for all queries.
base dc=domain,dc=com
binddn cn=user,ou=hosted,dc=domain,dc=com
bindpw pass
tls_reqcert never
tls_cacertfile /etc/ssl/certs/ca-certificates.crt
# Mappings for Active Directory
pagesize 1000
referrals off
idle_timelimit 800
filter passwd (&(objectClass=user)(!(objectClass=computer))(uidNumber=*)(unixHomeDirectory=*))
map passwd uid sAMAccountName
map passwd homeDirectory unixHomeDirectory
map passwd gecos displayName
filter shadow (&(objectClass=user)(!(objectClass=computer))(uidNumber=*)(unixHomeDirectory=*))
map shadow uid sAMAccountName
map shadow shadowLastChange pwdLastSet
filter group (objectClass=group)
# The search scope.
scope sub
filter group (objectclass=group)
filter passwd (&(objectClass=user)(memberOf=cn=vpngroup,ou=MyUsers)
sudo service nslcd restart
Create /etc/pam.d/openvpn, this will be the pam config that your OpenVPN instance will use.
Note: At first, we won't add any OTP config, we will only setup and test our LDAP configuration:
/etc/pam.d/openvpn
auth required pam_ldap.so
account required pam_ldap.so
In order to test:
sudo pamtester openvpn testuser authenticate
Password: *******
pamtester: successfully authenticated
It is also a good idea to disable PAM authentication yes in sshd in case you dont want it:
/etc/ssh/sshd_config
UsePAM no
sudo service ssh restart
So you now have to add OTP to our configuration
First, edit /etc/pam.d/openvpn in order to add MFA Authentication with the pam_oath module:
/etc/pam.d/openvpn
auth required pam_ldap.so
auth requisite pam_oath.so debug usersfile=/etc/users.oath window=30 digits=6
account required pam_ldap.so
Creating users.oath file
# First, Generate a hex secret:
openssl rand -hex 64 | sha1sum | cut -d' ' -f1
ae6f7ccc9ac97f42529765f5b44105668d88993c
Copy the hash and then edit the /etc/users.oath file, so it includes your user’s id and the hash we copied, eg.
#type username pin secret-hash
HOTP/T30/6 user.name - ae6f7ccc9ac97f42529765f5b44105668d88993c
Generate the TOTP details, 6 digits long.
oathtool --totp -v ae6f7ccc9ac97f42529765f5b44105668d88993c
Hex secret: ae6f7ccc9ac97f42529765f5b44105668d88993c
Base32 secret: VZXXZTE2ZF7UEUUXMX23IQIFM2GYRGJ4
Digits: 6
Window size: 0
TOTP mode: SHA1
Step size (seconds): 30
Start time: 1970-01-01 00:00:00 UTC (0)
Current time: 2024-10-04 17:43:04 UTC (1728063784)
Counter: 0x36EF04E (57602126)
319549
Creating QR for your Authenticator App
qrencode -t UTF8 'otpauth://totp/openvpn-MFA:testuser?secret=VZXXZTE2ZF7UEUUXMX23IQIFM2GYRGJ4'
CLI tool to test your OTP:
watch oathtool --totp -b VZXXZTE2ZF7UEUUXMX23IQIFM2GYRGJ4
Getting things to work
At this time, I ran pamtester again but output was:
User not known to the underlying authentication module
I also tested the ldap query but got no luck:
getent passwd | grep testuser
and got no result
so after digging the logs, I found out that I had to modify /etc/nsswitch.conf and add ldap
/etc/nsswitch.conf
- passwd: files systemd
+ passwd: files systemd ldap
sudo service nscd restart
but still I got the message pamtester: User not known to the underlying authentication module
So I checked again the logs and realised that I had to set uid and gid to my users :(
2024-08-30T15:23:51.083026+03:00 debian-server nslcd[1799]: [7b23c6] <passwd(all)> cn=testuser,dc=domain,dc=com: uidNumber: missing
2024-08-30T15:24:04.357387+03:00 debian-server nslcd[1855]: [8b4567] <passwd(all)> cn=testuser,dc=domain,dc=com: gidNumber: missing
So I had to go to my Active directory and:
PS C:\Windows\system32> set-aduser -identity testuser -add @{gidnumber="266737"}
PS C:\Windows\system32> set-aduser -identity testuser -add @{uidnumber="266736"}
and after that I managed to get pam_oath.so to work and prompt me for an OTP.
Now I queried the user!
getent passwd | grep testuser
testuser:*:266737:266736:testuser::
Test again PAM with OTP:
sudo pamtester openvpn testuser authenticate
Password:
One-time password (OATH) for `testuser':
pamtester: successfully authenticated
server.conf (snippet)
plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so "openvpn login USERNAME password PASSWORD One-time OTP"
# setenv verb 9 ;debug
client.conf (snippet)
auth-user-pass
static-challenge "Enter your OTP" 1
reneg-sec 7200
Notes
- Remeber to restart services after doing changes!
- After enabling a very verbose debug, i found:
authenticate rc -26 (OATH_FILE_CHOWN_ERROR: System error when changing file ownership, so I fixed this:
-rw------- 1 root root 130 Sep 1 23:18 /etc/users.oath - After getting auth-pam OTP failures in OpenVPN, I had to enable some quite verbose output in order to find that I had to change "pin" to "One-time" in the module config as pam-oath queries for "query='One-time password (OATH) for `testuser': ' style=1", so "pin" did not match the query of the module.
- Regarding gidnumber/uidnumber which I had to add manually to the test account, I am working on a bulk workaround for all users.
Σχόλια
Δημοσίευση σχολίου