The toughest WiFi on the block

A WPA2 Enterprise WiFi network consists of a number of components. You’ll need at least one access point that supports the WPA2 standard, a RADIUS server and your own set of TLS certificates to enable encryption. This is a whole lot more than you need for WPA2 Personal, which can be made just as secure in practice by simply using a hugely complex password. The Enterprise bit won’t give you any kind of additional functionality, unicorn magic or pixie dust if you’re only deploying a small network.

Yes, you need a dedicated server

Let’s get the sticky bit out of the way first: you’ll need a dedicated system to host the RADIUS server. In a small network this can be something like a tiny netbook, a Raspberry Pi, a Soekris box, or a virtual machine hosted on an existing physical box. Whatever you choose, you’ll need the RADIUS server to be active whener you want to use your wireless network and you’ll need a wired connection from your access point to the RADIUS host.

RADIUS is the component that provides all of the authenticating intelligence behind your new WiFi. The access point is just a dumb go-between that passes your users’ authentication requests to RADIUS and then essentialy just gets handed back a ‘yes’ or ‘no’ to base its decision on.

In my case this means a consumer router connected by wire to my existing XBMC media center where I’m hosting a dedicated FreeBSD 9.0 based RADIUS server using Freeradius 2 (/usr/ports/net/freeradius2). Specs on this can be extremely low by today’s standards.

My VM, when just running day to day, has only 64MB of RAM assigned to it and a positively roomy 8GB of disk and it’s still half empty and doing nothing most of the time. Just beef up the RAM when you intend to install new ports. Compiling packages takes up quite a bit more than 64MB of RAM but you can easily scale back after it’s done.

Since the RADIUS machine is the key to your network, you should probably host it on a dedicated (virtual) machine that you firewall off as tightly as possible even from your own computers. Only your access point(s) will ever directly access your RADIUS machine over UDP port 1812. No other access will ever be required other than DNS, maybe a small hole for administration over SSH, and optional clock sync over NTP.

Here’s how you install the port:

#cd /usr/ports/net/freeradius2
#make install
#make clean

Installing Freeradius from ports pulls in a small boatload of build dependencies, especially if you enable stuff like LDAP and SQL support (which you won’t need for EAP-TLS), so make sure you have the necessary time to wait for the compilation to finish.

You may already have your own SSL/TLS certificate authority in place, but Freeradius comes with a fairly neat set-up of its own for this purpose. The added bonus of that being that even Windows’ crippled network stack can use them. According to my info that’d be valid for at least Windows XP and Vista but I haven’t owned Windows computers for years now so I can’t really help you with that. For now, FreeBSD will generate a bunch of dummy certificates for you to work with while testing.

Disable the insecure parts

Freeradius comes with an example configuration that works with just about anything RADIUS-enabled under the sun. Much of that has nothing to do with wireless networks and a lot is also legacy, working with potentially insecure algorithms that used to be acceptable back when most of the world was still in sepia and “bandwidth” meant dial-up modems paired with clunky phones that sported big rubber cups on the horn. Honestly, you don’t want to know.

I’m aiming for EAP-TLS authentication here, which is the hairiest, nastiest version of EAP around. It uses TLS certificates in both directions for the utmost security so it eats wardrivers and the neighbours’ snarky kid for breakfast. Chuck Norris would probably be proud, even though he’d never show it. Undermining all that by using potentially insecure ciphers and hash functions would be sub-optimal at best.

You’ll find a bunch of config files in /usr/local/etc/raddb. One of them is eap.conf, which configures specifically the EAP authentication mechanisms. Since I’m exclusively going for EAP-TLS I don’t need any of the others. I stripped out all of the comments and reached the following contents for eap.conf.

eap {
default_eap_type = tls
timer_expire = 60
ignore_unknown_eap_types = no
cisco_accounting_username_bug = no
max_sessions = 4096
# Supported EAP-types
tls { 
  certdir = ${confdir}/certs
  cadir = ${confdir}/certs
  private_key_password = enter_your_pass_here
  private_key_file = ${certdir}/server.key
  certificate_file = ${certdir}/server.pem
  CA_file = ${cadir}/ca.pem
  dh_file = ${certdir}/dh 
  random_file = ${certdir}/random
  CA_path = ${cadir}
  cipher_list = "HIGH"
  make_cert_command = "${certdir}/bootstrap" 
  ecdh_curve = "prime256v1" 
  verify { 
    tmpdir = /tmp/radiusd 
    client = "/usr/bin/openssl verify -CApath ${..CA_path} %{TLS-Client-Cert-Filename}" 
  mschapv2 { 
    send_error = no

Note that in the above config you have to set a value for private_key_password. While you’re still testing, set this value to the literal word ‘whatever’ or it won’t work. We’ll get to setting up a proper password later. By clipping the file down to the above contents you’ll exclude legacy crud like EAP-MD5 and Cisco’s not-invented-here-but-still-crummy LEAP. Note that I’ve also set the cipher_list to “HIGH” instead of “DEFAULT”. This limits the support ciphers to only the highest class encryption available.

When you have the above in place, try starting the RADIUS daemon in debug mode:

#radiusd -X

Your console should flood with a bunch of text and hog your terminal with “Ready to process requests” on the last line. Any errors at this point usually have to do with your certificates not being in the right place, the private_key_password mismatching or something to do with file permissions in the raddb directory. Everything in this directory should be owned by the freeradius user and group.

Building your own certificates

Upon installation FreeBSD generated a bunch of fake TLS certificates in /usr/local/etc/raddb/certs. In the same directory you’ll find tools to generate a proper set, with your own name on them. I could regurgitate the entire README file which you’ll also find in this directory, but I’ll just assume for now that you can actually read it yourself. Follow all the steps in there to delete the existing fake certificates and generate new ones. There’s just one very annoying omission in this file: OpenSSL won’t regenerate the serial and index.txt files automatically once they’re gone. So after you delete all the existing stuff according to the instructions provided, run the following commands to put things back in order before generating server.pem.

#touch index.txt
#echo 1000 > serial
#chown freeradius:freeradius index.txt serial

After this step, you can properly generate the server certificate and any number of client certificates you need. Take note of the fact that the passwords you set in the ca.cnf, server.cnf and client.cnf files will be the private key passwords for the respective certificates. Especially for client certs, this’ll be a password which you’ll hand out to your end users. This may or may not be a problem, just don’t use any duplicates and don’t forget to update eap.conf according to what your set in server.cnf.

Tip: If you prefer not to go through the whole exercise of setting up a CA, a server certificate and all your client certificate every year, you should take a look at the ‘days’ setting in the .cnf files. These are set to 365 by default, which may be a bit short for a CA and your RADIUS server.
Security: While you’re at it, fix the default_md setting in the .cnf files as well. It’s set to md5 for compatibility, but the civilized world can deal with the much better sha1 so set it to that. It’ll close a tiny but present hole in your armor.

Check to see if your RADIUS daemon is still willing to start and whether it gives you any weird errors. If it does, just google them verbatim. There are tons of forums out there where any issue you could encounter at this stage has already been solved. Once your daemon starts properly again, you’re ready to finish the RADIUS component.

Finishing RADIUS config

Now that you have the core of your security in place, you need to edit /usr/local/etc/raddb/clients.conf in the same directory. It’s needed to allow your access point to consult RADIUS to authenticate your WiFi users. Add the following to clients.conf for each of your access points:

client {
  secret = your_radius_secret
  shortname = router
  nastype = other

Change the IP address to that of your local access point. The secret is a pre-shared secret between your router and the RADIUS server. You can enter whatever you like in there. The secret should of course be kept safe, but it won’t travel across the air so you don’t need to be concerned about people sniffing it.

Setting your router

In order to have your router work in WPA2 Enterprise mode, you’ll need to point it to your RADIUS server. Set it like the screenshot below. Make sure you only do this with an alternative (wired) connection in place, or you may find yourself uncomfortably debugging by constantly switching your router’s settings.

Install your clients

Installing certificates onto client systems is hardly generic across systems. What you’ll need is the client certificate, the client’s private key and the CA certificate from your RADIUS configuration. You may be able to work with the generated .pem files directly. Renaming these files on the client to .crt may help a lot. Android 4 works properly with these for example.

Another widely supported option is the PKCS12 format, which Microsoft -in a spasm of not-invented-here-syndrome of their own- calls PFX. Filenames end in .p12 or .pfx respectively. Generating them takes an extra step, which you’ll be able to do from your FreeBSD box because that has OpenSSL and the certificates already on them.

#openssl pkcs12 -export -out client.p12 -in clientcert.pem -inkey clientkey.pem -certfile cacert.pem

You’ll be asked for the private key’s password and a so-called “Export password”. The last is a password set on the PKCS12 file itself and the client will need it in order to read the file’s contents. Do set the password, because even though you can get away with creating passwordless PKCS12 files, not many applications will accept an empty password upon importing the file.

Once you have a file in PKCS12 format, you can freely rename them to .pfx or .p12 depending on what your client system expects. Apple’s MacOS X likes .p12 while Windows is likely to prefer .pfx.

Refer to your client system’s documentation for detailed instructions on how to install client certificates for use with WPA EAP-TLS.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.