# Update repository lists sudo apt update # Install OpenLDAP and standard utility tools sudo apt install -y slapd ldap-utils # Install the FreeRADIUS LDAP module (rlm_ldap) sudo apt install -y freeradius-ldap
# Configure or reconfigure slapd defaults interactively sudo dpkg-reconfigure slapd
sudo slapcat dn: dc=radiusdesk,dc=com objectClass: top objectClass: dcObject objectClass: organization o: radiusdesk dc: radiusdesk structuralObjectClass: organization entryUUID: 8c68dc16-1a3f-1041-9add-250d07e316fc creatorsName: cn=admin,dc=radiusdesk,dc=com createTimestamp: 20260722173600Z entryCSN: 20260722173600.213629Z#000000#000#000000 modifiersName: cn=admin,dc=radiusdesk,dc=com modifyTimestamp: 20260722173600Z
dn: ou=people,dc=radiusdesk,dc=com objectClass: organizationalUnit ou: people
ldapadd -x -D "cn=admin,dc=radiusdesk,dc=com" -W -f ou.ldif
dn: uid=testuser,ou=people,dc=radiusdesk,dc=com objectClass: top objectClass: account objectClass: simpleSecurityObject uid: testuser userPassword: mysecretpassword description: RADIUS Test User
ldapadd -x -D "cn=admin,dc=radiusdesk,dc=com" -W -f user.ldif
sudo slapcat dn: dc=radiusdesk,dc=com objectClass: top objectClass: dcObject objectClass: organization o: radiusdesk dc: radiusdesk structuralObjectClass: organization entryUUID: 8c68dc16-1a3f-1041-9add-250d07e316fc creatorsName: cn=admin,dc=radiusdesk,dc=com createTimestamp: 20260722173600Z entryCSN: 20260722173600.213629Z#000000#000#000000 modifiersName: cn=admin,dc=radiusdesk,dc=com modifyTimestamp: 20260722173600Z dn: ou=people,dc=radiusdesk,dc=com objectClass: organizationalUnit ou: people structuralObjectClass: organizationalUnit entryUUID: a6c420c6-1a48-1041-895a-41f787ad35f7 creatorsName: cn=admin,dc=radiusdesk,dc=com createTimestamp: 20260722184109Z entryCSN: 20260722184109.903088Z#000000#000#000000 modifiersName: cn=admin,dc=radiusdesk,dc=com modifyTimestamp: 20260722184109Z dn: uid=testuser,ou=people,dc=radiusdesk,dc=com objectClass: top objectClass: account objectClass: simpleSecurityObject uid: testuser userPassword:: bXlzZWNyZXRwYXNzd29yZA== description: RADIUS Test User structuralObjectClass: account entryUUID: f0928490-1a48-1041-895b-41f787ad35f7 creatorsName: cn=admin,dc=radiusdesk,dc=com createTimestamp: 20260722184313Z entryCSN: 20260722184313.729405Z#000000#000#000000 modifiersName: cn=admin,dc=radiusdesk,dc=com modifyTimestamp: 20260722184313Z
sudo su service freeradius stop cd /etc mv /etc/freeradius /etc/freeradius.rd cp -r /etc/freeradius.orig /etc/freeradius chown -R freerad:freerad /etc/freeradius
sudo su # Navigate to the enabled modules directory cd /etc/freeradius/3.0/mods-enabled/ # Link the LDAP configuration module sudo ln -s ../mods-available/ldap .
ldap { # LDAP server connection parameters server = "localhost" port = 389 # Identity used to search the directory identity = "cn=admin,dc=radiusdesk,dc=com" password = testing123 # Base DN where user lookups will begin base_dn = "dc=radiusdesk,dc=com" # User lookup mapping filter update { control:Password-With-Header += 'userPassword' } user { base_dn = "ou=people,dc=radiusdesk,dc=com" filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})" } }
# # The ldap module reads passwords from the LDAP database. -ldap
sudo systemctl stop freeradius sudo freeradius -X
radtest testuser mysecretpassword localhost 1812 testing123 #This is the return on my setup Sent Access-Request Id 249 from 0.0.0.0:56819 to 127.0.0.1:1812 length 78 User-Name = "testuser" User-Password = "mysecretpassword" NAS-IP-Address = 127.0.1.1 NAS-Port = 1812 Message-Authenticator = 0x00 Cleartext-Password = "mysecretpassword" Received Access-Accept Id 249 from 127.0.0.1:1812 to 127.0.0.1:56819 length 38 Message-Authenticator = 0x216fe46614354e897d645ce27ec9e0d8
rlm_ldap (ldap): Reserved connection (1) (2) ldap: EXPAND (uid=%{%{Stripped-User-Name}:-%{User-Name}}) (2) ldap: --> (uid=testuser) (2) ldap: Performing search in "ou=people,dc=radiusdesk,dc=com" with filter "(uid=testuser)", scope "sub" (2) ldap: Waiting for search result... (2) ldap: User object found at DN "uid=testuser,ou=people,dc=radiusdesk,dc=com" (2) ldap: Processing user attributes (2) ldap: control:Password-With-Header += 'mysecretpassword' rlm_ldap (ldap): Released connection (1) Need 1 more connections to reach min connections (3) Need more connections to reach 10 spares rlm_ldap (ldap): Opening additional connection (7), 1 of 30 pending slots used rlm_ldap (ldap): Connecting to ldap://localhost:389 rlm_ldap (ldap): Waiting for bind result... rlm_ldap (ldap): Bind successful (2) [ldap] = updated (2) [expiration] = noop (2) [logintime] = noop (2) pap: No {...} in Password-With-Header, re-writing to Cleartext-Password (2) pap: Removing &control:Password-With-Header (2) [pap] = updated (2) } # authorize = updated (2) Found Auth-Type = PAP
mkdir -p ~/pki cd ~/pki
openssl genpkey -algorithm RSA -out ca.key -pkeyopt rsa_keygen_bits:4096
openssl req -new -x509 -days 3650 -key ca.key -sha256 -out ca.crt #### This is what we filled in #### You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:ZA State or Province Name (full name) [Some-State]:Gauteng Locality Name (eg, city) []:Johannesburg Organization Name (eg, company) [Internet Widgits Pty Ltd]:RADIUSdesk.com Organizational Unit Name (eg, section) []:PKI Common Name (e.g. server FQDN or YOUR name) []:RADIUSdesk Internal Root CA Email Address []:dirk@gmail.com
openssl genpkey -algorithm RSA -out ldap.key -pkeyopt rsa_keygen_bits:4096
[req] default_bits = 4096 prompt = no distinguished_name = dn req_extensions = req_ext [dn] CN = ldap.radiusdesk.com [req_ext] subjectAltName = @alt_names [alt_names] DNS.1 = ldap.radiusdesk.com DNS.2 = ldap IP.1 = 127.0.0.1
openssl req -new -key ldap.key -out ldap.csr -config ldap.cnf
openssl x509 -req -in ldap.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ldap.crt -days 825 -sha256 -copy_extensions copy
sudo mkdir /etc/ldap/tls #Copy the following files over sudo cp ca.crt ldap.key ldap.crt /etc/ldap/tls #Change their permissions sudo chown openldap:openldap /etc/ldap/tls/* sudo chmod 600 /etc/ldap/tls/ldap.key sudo chmod 644 /etc/ldap/tls/*.crt
dn: cn=config changetype: modify replace: olcTLSCertificateFile olcTLSCertificateFile: /etc/ldap/tls/ldap.crt - replace: olcTLSCertificateKeyFile olcTLSCertificateKeyFile: /etc/ldap/tls/ldap.key - replace: olcTLSCACertificateFile olcTLSCACertificateFile: /etc/ldap/tls/ca.crt
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f tls.ldif
# slapd normally serves ldap only on all TCP-ports 389. slapd can also # service requests on TCP-port 636 (ldaps) and requests via unix # sockets. # Example usage: # SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///" #SLAPD_SERVICES="ldap:/// ldapi:///" SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///" </code bash> * Restart **slapd**. <code> sudo systemctl restart slapd
sudo ss -lnpt | grep 636 LISTEN 0 2048 0.0.0.0:636 0.0.0.0:* users:(("slapd",pid=698775,fd=11)) LISTEN 0 2048 [::]:636 [::]:* users:(("slapd",pid=698775,fd=12))
127.0.0.1 localhost 127.0.1.1 xubuntu-24-4 127.0.0.1 ldap.radiusdesk.com # The following lines are desirable for IPv6 capable hosts ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
openssl s_client -connect ldap.radiusdesk.com:636 -CAfile ca.crt #IT should end with something like this: --- SSL handshake has read 3905 bytes and written 401 bytes Verification: OK --- New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Server public key is 4096 bit Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 0 (ok)
Important is to specify the CA cert (LDAPTLS_CACERT) that ldapsearch needs to use else if will fail.
LDAPTLS_CACERT=/etc/ldap/tls/ca.crt ldapsearch -H ldaps://ldap.radiusdesk.com -x -D "cn=admin,dc=radiusdesk,dc=com" -w testing123 -b dc=radiusdesk,dc=com
sudo cp /etc/ldap/tls/ca.crt /usr/local/share/ca-certificates/radiusdesk-ca.crt sudo update-ca-certificates #This is the output on our system Updating certificates in /etc/ssl/certs... rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL 1 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... Processing triggers for ca-certificates-java (20240118) ... Adding debian:radiusdesk-ca.pem done. done. #Now we can just use plain ldapsearch ldapsearch -H ldaps://ldap.radiusdesk.com -x -D "cn=admin,dc=radiusdesk,dc=com" -w testing123 -b dc=radiusdesk,dc=com
I like to know how things work. If you also like to know how things work the following insert is for you
sudo su #Copy the OpenLDAP's CA to FreeRADIUS cp /etc/ldap/tls/ca /etc/freeradius/3.0/certs/ca.crt
#Look for these items... #server = 'localhost' #---This has to match the cert's ubjectAltName (SAN)--- server = 'ldap.radiusdesk.com' # server = 'ldap.rrdns.example.org' # server = 'ldap.rrdns.example.org' # Port to connect on, defaults to 389, will be ignored for LDAP URIs. ##port = 389 #--We specify the ldaps port-- port = 636 #--- Then loop for the tls section tls { # Set this to 'yes' to use TLS encrypted connections # to the LDAP database by using the StartTLS extended # operation. # # The StartTLS operation is supposed to be # used with normal ldap connections instead of # using ldaps (port 636) connections #--- Disable start_tls since we are forcing ssl/tls --- #start_tls = yes # ca_file = ${certdir}/cacert.pem #--- The CA file from OpenLDAP-- ca_file = /etc/freeradius/3.0/certs/ca.crt # ca_path = ${certdir} # certificate_file = /path/to/radius.crt # private_key_file = /path/to/radius.key # random_file = /dev/urandom # Certificate Verification requirements. Can be: # 'never' (do not even bother trying) # 'allow' (try, but don't fail if the certificate # cannot be verified) # 'demand' (fail if the certificate does not verify) # 'hard' (similar to 'demand' but fails if TLS # cannot negotiate) # # The default is libldap's default, which varies based # on the contents of ldap.conf. #---Enforce FreeRADIUS to check the validity of the certificate --- require_cert = 'demand' # # Check the CRL, as with the EAP module. #
rlm_ldap (ldap): Reserved connection (3) (3) ldap: EXPAND (uid=%{%{Stripped-User-Name}:-%{User-Name}}) (3) ldap: --> (uid=testuser) (3) ldap: Performing search in "ou=people,dc=radiusdesk,dc=com" with filter "(uid=testuser)", scope "sub" (3) ldap: Waiting for search result... (3) ldap: User object found at DN "uid=testuser,ou=people,dc=radiusdesk,dc=com" (3) ldap: Processing user attributes (3) ldap: control:Password-With-Header += 'mysecretpassword' rlm_ldap (ldap): Released connection (3) Need more connections to reach 10 spares rlm_ldap (ldap): Opening additional connection (7), 1 of 25 pending slots used rlm_ldap (ldap): Connecting to ldap://ldap.radiusdesk.com:636 rlm_ldap (ldap): Waiting for bind result... rlm_ldap (ldap): Bind successful