Use OpenLDAP TOTP as authentication for VPN
For this setup, we will be using FreeRADIUS and compiled OpenLDAP from source along with the TOTP (Time-based One Time Password ) module on CentOS 7. We will be using TOTP as authentication for OpenLDAP and use it as authentication for VPN if your router supports L2TP/IP Protocol. L2TP tunneling protocol can be deployed without any additional software on PCs, Macs, iOS devices, and Android devices, since all of these operating systems natively support L2TP VPN connections.
yum update
yum install make gcc openssl-devel libtool-ltdl-devel libdb-devel cyrus-sasl-devel git tcpdump vim libtool-ltdl-devel
yum group install "Development Tools"
Download OpenLDAP and compile it along with TOTP. Check for any error during compilation. use ./configure –help for other available options.
cd /opt/
git clone https://github.com/openldap/openldap.git
cd openldap
./configure --enable-modules --enable-dynamic --enable-syslog --enable-spasswd --enable-debug --enable-crypt --enable-spasswd
make depend
make -j$(nproc)
make install
Go to the slapd module directory to enable OpenLDAP to manage TOTP and install it.
cd contrib/slapd-modules/passwd/totp/
make
make install
slapd-totp.c provides support for RFC 6238 TOTP Time-based One Time Passwords in OpenLDAP using SHA-1, SHA-256, and SHA-512.
TOTP Libraries will be installed in:
/usr/local/libexec/openldap
Run the slappasswd command to set an LDAP root password and save the output because we are going to need it to configure OpenLDAP:
slappasswd
Edit slapd.conf file and load the TOTP module. Define rootpw here which was generated earlier.
vim /usr/local/etc/openldap/slapd.conf
include /usr/local/etc/openldap/schema/core.schema
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/nis.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema
pidfile /usr/local/var/run/slapd.pid
argsfile /usr/local/var/run/slapd.args
modulepath /usr/local/libexec/openldap
moduleload pw-totp.so
password-hash {TOTP1}
database mdb
maxsize 1073741824
suffix "dc=bidhankhatri,dc=com,dc=np"
rootdn "cn=ldapadmin,dc=bidhankhatri,dc=com,dc=np"
rootpw {SSHA}xxxxxxxxxxxxxxxxxx
directory /usr/local/var/openldap-data
index objectClass eq
overlay totp
Create a directory for LDAP Database.
mkdir /usr/local/var/openldap-data
Create systemd file for slapd service.
vim /etc/systemd/system/slapd.service
[Unit]
Description=OpenLDAP Server Daemon
After=syslog.target network-online.target
[Service]
Type=forking
PIDFile=/usr/local/var/run/slapd.pid
ExecStart=/usr/local/libexec/slapd
[Install]
WantedBy=multi-user.target
Test the configuration using the following command:
slaptest -u
config file testing succeeded
Now start LDAP Daemon and enable it on boot.
systemctl start slapd
systemctl enable slapd
And now create a base.ldif file for your domain:
vim base.ldif
# bidhankhatri.com.np
dn: dc=bidhankhatri,dc=com,dc=np
dc: bidhankhatri
objectClass: domain
objectClass: top
# users, bidhankhatri.com.np
dn: ou=users,dc=bidhankhatri,dc=com,dc=np
ou: users
objectClass: organizationalUnit
objectClass: top
ldapadd -x -D "cn=ldapadmin,dc=bidhankhatri,dc=com,dc=np" -W -f base.ldif
Enter the root password when prompted.
Create another ldif file for users and add those users to LDAP Database.
vim users.ldif
# bidhan.khatri, users, bidhankhatri.com.np
dn: uid=bidhan.khatri,ou=users,dc=bidhankhatri,dc=com,dc=np
objectClass: inetOrgPerson
objectClass: top
uid: bidhan.khatri
ou: users
cn: Bidhan Khatri
sn: bidhan.khatri
mail: bidhan.khatri@bidhankhatri.com.np
userPassword:
ldapadd -x -D "cn=ldapadmin,dc=bidhankhatri,dc=com,dc=np" -W -f user.ldif
Managing Password
There is a requirement for the secret key, the minimum size has to be 128 bit, it is recommended to extend this to 160 bit (20bytes).
Here, I am using 21 bytes strings as a password for user bidhan.khatri.
echo "helloworldnepal12345" | wc -c
21
As there is a password hashing scheme defined in slapd.conf {TOTP1}, the attribute userPassword may now be modified by means of LDAP Password Modify Extended Operation.
Now define a password for user bidhan.khatri. and also need to define ldapadmin password.
ldappasswd -x -D "cn=ldapadmin,dc=bidhankhatri,dc=com,dc=np" -W -S "uid=bidhan.khatri,ou=users,dc=bidhankhatri,dc=com,dc=np"
This string will be internally converted into a base32 string, while the output of ldapsearch or slapcat will be additionally base64 encoded.
Search LDAP Directory to verify. Your new users should be listed.
ldapsearch -x -b 'dc=bidhankhatri,dc=com,dc=np'
# bidhan.khatri, users, bidhankhatri.com.np
dn: uid=bidhan.khatri,ou=users,dc=bidhankhatri,dc=com,dc=np
objectClass: inetOrgPerson
objectClass: top
uid: bidhan.khatri
ou: users
cn: Bidhan Khatri
sn: bidhan.khatri
mail: bidhan.khatri@bidhankhatri.com.np
userPassword:: e1RPVFAxfU5CU1dZM0RQTzVYWEUzREVOWlNYQVlMTUdFWkRHTkJW
echo "e1RPVFAxfU5CU1dZM0RQTzVYWEUzREVOWlNYQVlMTUdFWkRHTkJW" | base64 -d
{TOTP1}NBSWY3DPO5XXE3DENZSXAYLMGEZDGNBV
Just to verify the bytes used by the shared key.
echo "NBSWY3DPO5XXE3DENZSXAYLMGEZDGNBV" | wc -c
33
Share that secret key to people either by generating a QR code or through sending by email.
User now adds this shared key to their authenticator. In the Google Authenticator app, they would select ‘Enter a setup key’ option and then any account name and below that name there is key section where secret key need to be set. and after that click on add.
NOTE:
Trailing ‘=’ signs in base32 encoding for TOTP will fail with Google Authenticator in iOS but it’s fine in android OS. so it’s better to use fixed-size password length which doesn’t involve padding in the secret key.
If you want to encode secret keys in QR codes as a URI then follow below format. otpauth://TYPE/LABEL?PARAMETERS
otpauth://totp/BDN:bidhan.khatri?secret=NBSWY3DPO5XXE3DENZSXAYLMGEZDGNBV&issuer=BDN&period=30&digits=6&algorithm=SHA1
Default period is of 30sec. Though you compile TOTP with a time step of 60 seconds, authenticator apps like Google Authenticator will not work with a defined period of seconds. 30sec is the default time in Google Authenticator. You can not change this period in google authenticator. The period parameter is ignored by Google Authenticator.
Ref: https://github.com/google/google-authenticator/wiki/Key-Uri-Format
Now check LDAP authentication for the user.
ldapwhoami -x -D "uid=bidhan.khatri,ou=users,dc=bidhankhatri,dc=com,dc=np" -W
Enter LDAP Password: (Enter token from Google Authenticator)
dn:uid=bidhan.khatri,ou=users,dc=bidhankhatri,dc=com,dc=np
Supported authenticator
- Google Authenticator
- Sophos Authenticator
- FreeOTP
Installing and Configuring FreeRADIUS
Install freeradius package.
yum install freeradius freeradius-utils freeradius-ldap
Edit radius default file and enable LDAP auth type.
cat /etc/raddb/sites-enabled/default | grep -v "#" | sed '/^$/d'
change these fields only.
authorize {
filter_username
preprocess
files
-sql
# The ldap module reads passwords from the LDAP database.
ldap
expiration
logintime
pap
}
authenticate {
Auth-Type PAP {
ldap
}
Auth-Type LDAP {
ldap
}
}
cd /etc/raddb/mods-enabled/
ln -s ../mods-available/ldap ldap
Define LDAP details.
cat /etc/raddb/mods-enabled/ldap | grep -v "#" | sed '/^$/d'
server = 'localhost'
port = 389
identity = 'cn=ldapadmin,dc=bidhankhatri,dc=com,dc=np'
password = secret(your ldap password)
base_dn = 'dc=bidhankhatri,dc=com,dc=np'
Define Your Router client along with secret key in /etc/raddb/client.conf file like below.
cat /etc/raddb/clients.conf | grep -v "#" | sed '/^$/d'
client router_name {
ipaddr = xxx.xxx.xxx.xxx
secret = yoursecret
}
Start and enable radius service.
systemctl start radiusd
systemctl enable radiusd
Now test radius server by querying directly with requests through radtest command. Here, “537769” is TOTP for user bidhan.khatri. your reply should be Access-Accept
radtest bidhan.khatri 537769 127.0.0.1 1812 testing123
Sent Access-Request Id 59 from 0.0.0.0:38107 to 127.0.0.1:1812 length 83
User-Name = "bidhan.khatri"
User-Password = "537769"
NAS-IP-Address = x.x.x.x
NAS-Port = 1812
Message-Authenticator = 0x00
Cleartext-Password = "537769"
Received Access-Accept Id 59 from 127.0.0.1:1812 to 0.0.0.0:0 length 20
That’s it. Now you can point radius server IP from your router end to authenticate users through OpenLDAP TOTP for VPN access.
Comments