Using a RADIUS 3.X Server on Ubuntu 14.04 for WIFI Authentication
This is an update from an older article on Freeradius 2.x. This version covers Freeradius 3.x
Looking for how to add a CRL? See my new article on that.
Thanks to TechTalk for their help in debugging this article.
Let's be honest. Your wifi password is probably something pretty simple. When you have to be able to both verbally convey the password to new users and type it in on a mobile device, it's not like the password can be 25 random characters including special characters, can it?
To have real security, you should be using a pre-shared encryption certificate. This moves the security from "something you know", aka your password, to "something you have", an encryption certificate file. Most modern Wireless Access Points (WAP) support WPA2-Enterprise which expects that you are running a RADIUS server for authenticating clients.
Now there's many ways that a RADIUS server can be configured but I'm going to suggest one that generates signed certificates for users that then must be installed on their devices. Other RADIUS implementations allow you to store a unique user login in an LDAP database backend for instance, but rather than providing attackers a huge list of possible passwords to crack we want to eliminate the password as a possible login method entirely.
RADIUS is an acronym for "Remote Authentication Dial In User Service." You may be able to tell by the name that it's not a new technology - the last time I used a dial-in connection was probably 16 years ago. Fortunately for us this means that RADIUS is a well established and tested standard and because it's also flexible, we can now use it for authenticating users in many different scenarios, including WIFI.
A few pre-requisites I'm going to assume
I'm going to assume that you have a WAP that supports WPA2-Enterprise.
Your WAP must be configured with a static IP address.
You also need a server with a static IP address running Ubuntu 14.04 that you intend to run a RADIUS server on.
You have a basic knowledge of administering Linux and Ubuntu servers already.
Install FreeRADIUS 3.x From The PPA Repository
For this it will be much easier if you just run the following on the server that will host Freeradius...
sudo su -
...and become the root user.
First, let's add the PPA repository for the Freeradius 3.x stable branch:
apt-get install python-software-properties apt-add-repository ppa:freeradius/stable-3.0 apt-get update apt-get install freeradius make
There are many different ways that FreeRADIUS can be configured, and honestly I don't understand most of them. Here's what I found that worked for me.
Turn off the proxy feature on the server (unless you know you need it) by editing /etc/freeradius/radiusd.conf and changing the following line:
proxy_requests = no # $INCLUDE proxy.conf
You may also want to look over the logging features in that configuration file to set what gets logged and where. I use "auth=yes" in the log{} block so that I log every time someone connects to the wifi. It also tells me which access point they connected to.
What is a Radius client?
FreeRADIUS may throw you for a loop talking about servers and clients. The client is NOT what you think - it's not the user's laptop or phone. The client is the WAP, because it performs the authentication request against the server. This confusion is exacerbated by the fact that to configure a user certificate, you edit a file called "client.cnf".
By default, FreeRADIUS will set up the localhost of the server as a client as well, and we won't be needing that so let's just start a new clients.cnf file and put our entry for our WAP in that. Create a new random password that you'll enter into the WAP itself that it uses to authenticate against the RADIUS server. Again in the '/etc/freeradius/clients.conf' file:
# -*- text -*- ## ## clients.conf -- client configuration directives ## ## $Id$ ####################################################################### # # Define RADIUS clients (usually a NAS, Access Point, etc.). client mywap { ipaddr = 192.168.1.100 secret = myRandomP@55w05D require_message_authenticator = yes }
Please be sure you've changed the ipaddr and secret lines. You will need a client entry for each WAP that is on your network. The client name is arbitrary, but will show in the logs when a user authenticates, so it's always good to be able to easily identify which WAP a user connected to. I recommend a different password for each one, in addition to needing the static IP address of the WAP.
When you configure the "WPA2-Enterprise" options on your WAP, you'll enter the IP address of your Radius server, and this password.
EAP Configuration
Next we want to edit the configuration for the Extensible Authentication Protocol (EAP). Rather than telling you what to comment, I'm going to just show you what you need. Edit '/etc/freeradius/mods-available/eap' to look something like this:
# -*- text -*- # Example /etc/freeradius/mods-available/eap file eap { default_eap_type = tls timer_expire = 60 ignore_unknown_eap_types = no cisco_accounting_username_bug = no max_sessions = 4096 tls { certdir = ${confdir}/certs cadir = ${confdir}/certs private_key_password = myserverkeypassword private_key_file = ${certdir}/server.key certificate_file = ${certdir}/server.pem ca_path = ${cadir} ca_file = ${cadir}/ca.pem dh_file = ${certdir}/dh random_file = /dev/urandom cipher_list = "HIGH" make_cert_command = "${certdir}/bootstrap" ecdh_curve = "prime256v1" cache { enable = no # Optionally enable lifetime = 24 # hours max_entries = 255 } verify { tmpdir = /tmp/radiusd client = "/usr/bin/openssl verify -CAfile ${..ca_file} %{TLS-Client-Cert-Filename}" } ocsp { enable = no # optionally enable override_cert_url = yes url = "http://127.0.0.1/ocsp/" } } ttls { default_eap_type = md5 copy_request_to_tunnel = no use_tunneled_reply = no virtual_server = "inner-tunnel" } }
The "myserverkeypassword" above will need to match the password you use when generating the server's keys later.
What we've done mostly is disable other protocols like LEAP and PEAP and MSCHAPv2 among others, none of which are good ideas to use. Only EAP-TLS will be used.
Disable all the default servers
rm /etc/freeradius/sites-enabled/*
Create a new server config file at /etc/freeradius/sites-available/mynetwork that contains something like the following:
###################################################################### server { listen { type = auth port = 1812 ipaddr = * } authorize { preprocess eap { ok = return } expiration logintime } authenticate { eap } preacct { preprocess acct_unique suffix files } accounting { detail # unix radutmp # exec attr_filter.accounting_response } session { radutmp } post-auth { # exec Post-Auth-Type REJECT { attr_filter.access_reject } } pre-proxy { } post-proxy { eap } }
Now, link that to the sites-enabled directory like so:
cd /etc/freeradius/sites-enabled/ ln -s ../sites-available/mynetwork ./mynetwork
Configure SSL Certificates
Assuming all went well, now we start generating SSL certificates. First we want to remove the default certificates and set up a basic framework:
cd /etc/freeradius/certs rm * cp /usr/share/doc/freeradius/examples/certs/* /etc/freeradius/certs/
Now we want to edit the /etc/freeradius/certs/ca.cnf file and change the following options:
[CA_default] .. default_days = 1825 .. [req] default_bits = 4096 input_password = mycapassword output_password = mycapassword .. [certificate_authority]
Edit the lines under the certificate_authority section to match what your certificate should say about you, and change the CA password that's in bold above.
Now we make the CA keys and the DH file:
make ca.pem make ca.der make printca make dh
And now we edit the server.cnf file making some similar changes:
[ CA_default ] .. default_days = 1825 .. [ req ] .. default_bits = 4096 input_password = myserverkeypassword output_password = myserverkeypassword [server]
Change the server section to match what your certificate should say about your server. Note that the passwords in this file should match the password in the eap file we configured previously. Now make the server certificate:
make server.pem
Last bit of server configuration
Freeradius 3.x doesn't appear capable of creating it's temp directory, so I had to do this by hand:
mkdir /tmp/radiusd chown freerad:freerad /tmp/radiusd chmod 700 /tmp/radiusd
Let's test the server
We should be ready to launch the server now, so let's run it in the foreground first to make sure everything launches correctly:
service freeradius stop freeradius -X
The last line should say: "Ready to process requests"
If the test all goes well you can stop the server with: ctrl-c
Create user certificates
Now we generate client certificates, but there's something we need to change in the Makefile first. "nano Makefile".
Locate the lines that say:
client.p12: client.crt openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) client.pem: client.p12 openssl pkcs12 -in client.p12 -out client.pem -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) cp client.pem $(USER_NAME).pem
Change it to read:
client.p12: client.crt openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) cp client.p12 $(USER_NAME).p12 client.pem: client.p12 openssl pkcs12 -in client.p12 -out client.pem -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) cp client.pem $(USER_NAME).pem client_android.p12: client.crt openssl pkcs12 -export -in client.crt -inkey client.key -certfile ca.pem -name "$(USER_NAME)" -out client_android.p12 -passin pass:$(PASSWORD_CLIENT) -passout pass:$(PASSWORD_CLIENT) cp client_android.p12 $(USER_NAME)_android.p12
Make sure indented lines are tabs and not spaces or the file will not work. If you just copy-paste this, it will probably paste as spaces, and you'll need to delete the indents and replace with tabs. It's a Makefile thing. These edits create a special case for Android certificates and renames the files to be easier to identify.
nano client.cnf
Edit 'client.cnf' to set your defaults just like you did before but this time for any client certificates. You probably want to change the default_days to 365 (will need to regenerate keys for the device in a year) but again change the default_bits to 4096.
In the "[ req ]" section of client.cnf is the "input_password" and "output_password". Set these both to the same, and keep in mind that this password will be needed when the certificate is installed on the client so keep in mind using mobile keyboards to type it as you choose the password.
[ CA_default ] .. default_days = 365 .. [ req ] prompt = now distinguished_name = client default_bits = 4096 input_password = clientpassword output_password = clientpassword ..
Note that the "distinguished_name" should remain as "client" and not the name of the client.
The "[client]" section uniquely identifies the user in log files, so be sure the emailAddress and commonName are set properly to the user's email address. It causes less confusion if the emailAddress and commonName bothd match.
Now create the client certificate with:
make client.pem make client_android.p12
Simply edit the client.cnf file for the next certificate and run those commands again to generate certificates for each device that will have WIFI access.
Finally, lets set the proper permissions for certificates:
chmod 600 * chown root:freerad * chmod 640 ca.pem chmod 644 dh chmod 640 server.key chmod 640 server.pem
The Right Certificates in the Right Places
Here's the files needed:
- Windows: ca.der and [user].p12 - See this page for installation details.
- Linux: ca.pem and [user].p12
- Android: [user]_android.p12
Note that recent versions of Android will constantly display a warning that your connection is monitored while using wifi with a RADIUS server. There are ways on a rooted device to install the certificate in the root store, but it doesn't actually affect the operation of the device.
Should be ready to go
You should have everything configured at this point and be able to launch your Freeradius server with:
service freeradius restart
If you run into any trouble, launch it in the foreground by running:
freeradius -X
This will give you more debug output and show what's happening when a client authentication request arrives.