Using LetsEncrypt certificates
When configuring FreeRADIUS to use EAP, the use of keys and certificates are essential. Unfortunately this is one of those areas that can be hard to get right and prone to problems. Notably, certificates can expiry at very inopportune moments. At which point no one can get online.
Our recommendation is always to use a private CA for both server and user certificates for utmost security. However, the problem of having to install the CA root certificate on all end user devices can put many people off of this route. In that case, using a public CA certificate for the server is often seen as the most convenient answer, even if it is not the most secure.
Never configure FreeRADIUS to use a public CA root in the
ca_file or ca_path EAP module settings. This would potentially
allow any secondary (intermediate) CA signed by that public CA to
issue client certificates, and be authenticated by your server!
|
Prerequisites
The instructions here depend on the following criteria:
-
You have chosen to use a public CA to issue the server certificate for your RADIUS server, and are aware of the security considerations in doing so.
-
You wish to use [LetsEncrypt[(https://letsencrypt.org/) for this purpose, and want certificate renewals (usually every 2-3 months) to be automatic.
-
The RADIUS server has a public IP address and can receive traffic on port 80 for certificate renewals, and you have considered the security implications of this.
-
There is a DNS entry pointing at the server that the certificate can be issued for.
RADIUS servers are usually best hidden away on an internal network, so the final few points above are worth considering carefully. It is possible to set this up using a front web-server which requests the certificate and then pushes it back to the RADIUS server internally, but that configuration is beyond the scope of this document.
Set up process
The instructions here use LetsEncrypt’s [certbot](https://certbot.eff.org/) tool to generate certificates and renew them when necessary. Other alternative tools can be used based on the following instructions.
We will be setting up the following components:
-
Creating up a group that has access to the certificate files.
-
Writing a post-renewal hook script for
certbot
so that FreeRADIUS is restarted after the new certificate has been installed. -
Running
certbot
to issue the certificate. -
Configuring FreeRADIUS to use the LetsEncrypt issued certificate and associated private key.
This document is based on a Debian system (version 12 at the time of writing), so it may need adjusting for other operating systems. The instructions here are for a generic system, so it may also need adjusting for each particular case. For example, a group may already exist that has ownership of the certificates, so that can likely be used instead of creating a new one.
Initial system configuration
FreeRADIUS should already be installed. We will assume here that
it is running as the freerad
user, but may be radiusd
on RPM
based systems, radius
if installed from source, or some other
user.
You must have a public IP address for the server, and there must be a DNS entry (of the name of the certificate you will be requesting) pointing to this IP. The server must be reachable on port 80 (HTTP) from the Internet. |
Install the certbot
utility from LetsEncrypt. On Debian it can
be installed from the default repositories:
apt-get update
apt-get install certbot
Add a group for the certificate and key files, and then add the FreeRADIUS user to this group so that FreeRADIUS can read the certificate files:
addgroup -s certs
adduser freerad certs
Configure certbot
We will use a script to restart FreeRADIUS whenever certbot
renews
the certificate. This script will also ensure that the permissions are
always set correctly on the certificate files, so that FreeRADIUS
is able to read them.
Create a file /usr/local/sbin/certbot-post-hook
with the following
contents:
#!/bin/sh
# Ensure certificates are in the correct group
chgrp -R certs /etc/letsencrypt/live /etc/letsencrypt/archive
chmod 750 /etc/letsencrypt/live /etc/letsencrypt/archive
# Restart FreeRADIUS
/usr/sbin/service freeradius restart
Generate the certificate
The system is now ready to request a certificate from LetsEncrypt. We
will be using the example FQDN of radius.example.com
here; replace
this name with whatever name you have in your DNS, and which points to
the public IP address of the RADIUS server.
First, generate a certificate from the test certificate issuer. There are severe rate limits on the production issuer server, which can mean you are quickly locked out if making multiple requests while testing. It is therefore useful to try with the test issuer first.
Run the following to generate a key and to request the certificate.
Note that certbot
will open up a temporary web server on port 80
while this is in progress, so ensure that any firewalls are already
opened up, and that external systems can connect to the machine in
port 80.
certbot certonly \
--test-cert \
--standalone \
--cert-name radius.example.com \
-d radius.example.com \
--post-hook /usr/local/sbin/certbot-post-hook
Any issues generating this certificate pair need to be investigated and fixed. Repeat the above command as necessary until the certificate is issued successfully.
There are still rate limits on LetsEncrypt’s test server, but they are higher and you are less likely to hit them than with the production issuer. |
Once you have successfully generated a test certificate, you can remove it and request the real certificate:
certbot revoke \
--test-cert \
--standalone \
--delete-after-revoke \
--cert-name radius.example.com
certbot certonly \
--standalone \
--cert-name radius.example.com \
-d radius.example.com \
--post-hook /usr/local/sbin/certbot-post-hook
FreeRADIUS configuration
The last step is to configure FreeRADIUS to use the new
LetsEncrypt certificates. In the default configuration this is in
the /etc/freeradius/mods-enabled/eap
file.
Find the tls-config tls-common
section. The default will have:
certificate_file = ${certdir}/rsa/server.pem private_key_file = ${certdir}/rsa/server.key
Change these entries to point to the new certificate and key:
certificate_file = /etc/letsencrypt/live/radius.example.com/fullchain.pem private_key_file = /etc/letsencrypt/live/radius.example.com/privkey.pem
Test the FreeRADIUS configuration with the following command:
radiusd -XC
If all is well then the server will print the following message:
Configuration appears to be OK
Finally restart FreeRADIUS to use the new LetsEncrypt certificate:
service freeradius restart
Check certificate renewal process
The certificates need to be renewed before three months is up.
There is a command, certbot renew
, to do this automatically. On
Debian based systems, the certbot
package will create a cron job
or systemd timer to run this at least daily, but you should still check that this
cron job is enabled.
Troubleshooting
There are a number of issues that may occur. We list some here that may help.
Certificate won’t issue
-
Can the RADIUS server be reached from the Internet to tcp port 80? Is there a firewall or similar blocking access?
-
Is there a DNS entry, for the same domain name being requested, resolvable in the public DNS?
-
Does that DNS entry point to the IP of the system running
certbot
? -
Have you hit the LetsEncrypt rate limits?
Certificate expires and does not renew
-
Is the server still reachable on port 80, and is the DNS entry still present and correct (as above)?
-
Is the
certbot
cron job orsystemd
timer to renew certificates enabled? The Debian packaging creates these, but other systems may not.