First, let’s install the RADIUS server, FreeRADIUS. On the server that is going to host it do:

sudo 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

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.


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. 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 disable it in the ‘/etc/freeradius/clients.conf’ file by commenting it out.

#client localhost {
        #  Allowed values are:
        #       dotted quad (
        #       hostname    (
#       ipaddr =

        #  OR, you can use an IPv6 address, but not both
        #  at the same time.
#       ipv6addr = ::   # any.  ::1 == localhost

And now we add an 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:

client mywap {
        ipaddr =
        secret = myRandomP@55w05D
        require_message_authenticator = yes

Please be sure you’ve changed the parts I put in bold. You will need a client entry for each WAP that is on your network. I recommend a different password for each one, in addition to needing the static IP address of the WAP.


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/eap.conf’ to look something like this:

# -*- text -*-
# Example /etc/freeradius/eap.conf 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 = ""
	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.


sudo rm /etc/freeradius/sites-enabled/*

Create a new server config file at /etc/freeradius/sites-available/mynetwork that contains something like the following:

authorize {
	eap {
		ok = return

authenticate {

preacct {

accounting {

session {

post-auth {
	Post-Auth-Type REJECT {

pre-proxy {


post-proxy {

Now, link that to the sites-enabled directory like so:

sudo su -
cd /etc/freeradius/sites-enabled/
ln -s ../sites-available/mynetwork ./mynetwork

And then stop FreeRADIUS and restart it in debug mode to make sure all is loading correctly:

service freeradius stop
freeradius -X

Hopefully it starts up just fine without any errors. You should see “Ready to process requests”. Any error messages you see now is the time to do some research and find out why. Once you’ve finished the test type CTRL-C to stop the server.


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 *.pem
rm *.key
mkdir /var/certs
mkdir /var/certs/freeradius
chgrp ssl-cert /var/certs/freeradius
chmod 710 /var/certs/freeradius
cp /usr/share/doc/freeradius/examples/certs/* /var/certs/freeradius/
cd /var/certs/freeradius/
rm bootstrap
chmod 600 *
make destroycerts
make index.txt
make serial

Next, edit the ‘ca.cnf’ file and change a few of the defaults. Change the following lines:

[ CA_default ]
default_days = 1825
default_md = sha1
[ req ]
default_bits = 4096
input_password = myserverkeypassword
output_password = myserverkeypassword

That sets certificates good for 5 years (you can change the days to whatever you like) and increases the certificate security considerably from the defaults. The “myserverkeypassword” above should match the one in the eap.conf file at the beginning and should be a randomly generated string. You’ll never have to enter this in a client so make it complicated.

Now, generate the ‘ca.pem’ file:

make ca.pem
make ca.der
make printca

Now, edit the “server.cnf” file and do similar changes:

[ CA_default ]
default_days = 1825
default_md = sha1
[ req ]
default_bits = 4096

Under the “[server]” tag put in your appropriate contact information. Now generate the ‘server.pem’ file:

make server.pem


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

Note that the above lines will wrap in your browser but if you copy and paste them they should be formatted correctly.

Make sure indented lines are tabs and not spaces or the file will not work. This change creates a special case for Android certificates and renames the files to be easier to identify.

Edit ‘client.cnf’ to set your defaults just like you did before but this time for any client certificates. You probably want to shorten the default_days to 365 (will need to regenerate keys for the device in a year) but again change the default_md to sha1 and 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. The “[client]” section uniquely identifies the user in log files, so be sure the emailAddress and commonName are set properly.

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 and create the links we need:

chmod 600 *
chmod 640 ca.pem
chmod 640 server.pem
chmod 640 server.key
chgrp ssl-cert ca.pem
chgrp ssl-cert server.pem
chgrp ssl-cert server.key
cd /etc/freeradius/certs/
ln -s /var/certs/freeradius/ca.pem ca.pem
ln -s /var/certs/freeradius/server.pem server.pem
ln -s /var/certs/freeradius/server.key server.key

After creating new client certificates, the first four lines of the above command should be run again to ensure the security is set properly.


Here’s the files needed:

  • Windows: ca.der and [user].p12
  • 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 regardless it doesn’t actually affect the operation of the device.


This entry was posted in Radius. Bookmark the permalink.