Encrypt
Clients expect to see a certificate when connecting. The default Debian Snakeoil certificate causes some clients to show a red warning message (as it should).
Back in the bad old days, you had to purchase a ‘Unified Communication’ cert at a premium. But now you can use the free Let’s Encrypt project. It includes the EKU (Extended Key Usage) attribute “Server Authentication” which is required.
It can secure the inter-server communication channel as well.
Get the Certificate
There are a couple ways to prove yourself to Let’s Encrypt, but the simplest is let them connect to you at the DNS name you are requesting.
Configure a Reverse Proxy
Create the public DNS CNAME “wifi.example.org” for your hopefully-already-existing reverse proxy server. Forward port 80 to your RADIUS server for later use.
# HAProxy Example
frontend http
bind *:80
mode http
acl wifi hdr(host) wifi.example.org
use_backend wifi if wifi
backend wifi
mode http
server wifi radius.private.lan:80
# Caddy Example
http://wifi.example.org {
import logging
reverse_proxy * radius.private.lan
}
Install Certbot
The EFF makes a handy utility called certbot that will do the hard work for us. Though one hesitates to allow the internet in, certbot only listens for a few seconds every two months.
apt install certbot
certbot certonly --standalone -d wifi.example.org
ls /etc/letsencrypt/live/wifi.example.org/
Set Permissions
The cert files start as root-only but any changes are preserved.
# Create a certs group (if it doesn't already exist) and add the processes to it.
sudo addgroup certs
sudo chgrp -R certs /etc/letsencrypt/live /etc/letsencrypt/archive
sudo chmod 750 /etc/letsencrypt/live /etc/letsencrypt/archive
Configure FreeRADIUS
Add Group to FreeRADIUS
Grant the freerad process access to the certs
sudo adduser freerad certs
Change the EAP config
vi /etc/freeradius/3.0/mods-available/eap
...
...
tls-config tls-common {
private_key_file = /etc/letsencrypt/live/wifi.example.org/privkey.pem
#private_key_file = /etc/ssl/private/ssl-cert-snakeoil.key
...
...
certificate_file = /etc/letsencrypt/live/wifi.example.org/fullchain.pem
#certificate_file = /etc/ssl/certs/ssl-cert-snakeoil.pem
systemctl restart freeradius
Test with a client
The best way to test is to grab an IOS device or Apple Laptop. These will display the Cert when you connect.
Add a RADIUS Trigger
FreeRADIUS won’t know when a cert gets updated, so you’ll need to trigger a restart (a reload isn’t enough) with a certbot hook.
sudo touch /etc/letsencrypt/renewal-hooks/post/radius
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/radius
sudo vi /etc/letsencrypt/renewal-hooks/post/radius
#!/bin/sh
logger certbot renewel triggered restart of freerad
systemctl restart freeradius.service
Configure LDAP
In this example everything is running on one host. But if the data was traversing the network you’d encrypt it. The modern way is to enable and enforce TLS using the certificate we just got. In fact, RFC4513 says servers should disallow the use of passwords when TLS is not in use, so let’s get on this.
Configure SLAPD
First, let’s grant OpenLDAP access to the key.
sudo adduser openldap certs
Then, tell slapd about the cert by creating a configuration file in LDIF format and loading it.
vi cert.ldif
dn: cn=config
changetype: modify
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/letsencrypt/live/wifi.example.org/privkey.pem
-
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/letsencrypt/live/wifi.example.org/cert.pem
ldapmodify -Y EXTERNAL -H ldapi:/// -f cert.ldif
Test TLS is working with the ZZ option. (A single Z says means continue if negotiation fails, ZZ means stop if failed). Also use LDAPTLS_REQCERT=never. This allows us to verify that a cert is in place (ZZ) but don’t bother testing the validity (never).
# Use 'LDAPTLS_REQCERT=never' to trust any cert we get, but don't check the chain root yet
LDAPTLS_REQCERT=never ldapsearch -x -LLL -W -ZZ -D cn=admin,dc=example,dc=org -b dc=example,dc=org
There’s also the gold standard, openssl.
openssl s_client -starttls ldap -connect localhost:389
# Or a one-liner to decode as well
echo | openssl s_client -starttls ldap -connect localhost:389 | openssl x509 -text
Add a Hook
Just like before, we need to tel slapd about the new cert.
sudo touch /etc/letsencrypt/renewal-hooks/post/ldap
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/ldap
sudo vi /etc/letsencrypt/renewal-hooks/post/ldap
#!/bin/bash
logger certbot renewel triggered restart of openldap
systemctl restart slapd.service
Join Them Together
RADIUS TLS
We can now tell RADIUS to use TLS with LDAP. Use the ‘require_cert’ attribute to ignore the trust chain until later.
vi /etc/freeradius/3.0/mods-available/ldap
tls {
...
...
start_tls = yes
...
...
require_cert = 'never'
systemctl restart freeradius
# You can start in dubug mode like before to troubleshoot if needed
Next Steps
You may have noticed that are using certs now, but the processes themselves don’t care if they are valid. Just that we have one. We also haven’t done much with LDAP security. Let’s do that next.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.