Paranoid Penguin - Securing Your WLAN with WPA and FreeRADIUS, Part II
Last month, I described the new wireless LAN security protocol, Wi-Fi Protected Access (WPA). I showed how it adds strong and flexible authentication, plus dynamic encryption-key negotiation, to the otherwise-insecure WEP protocol. I also showed how WPA's component protocols, including 802.1x, the various flavors of EAP and RADIUS, interrelate. In this month's column I start to show how to create your own authentication server for WPA and other 802.1x scenarios, using FreeRADIUS and OpenSSL.
WPA, you may recall, is more modular than WEP. Whereas authentication and encryption in WEP both are achieved through a shared secret used by all wireless clients, authentication in WPA normally is achieved by using the 802.1x protocol. The pre-shared key (PSK) mode, which works more like WEP, also is an option. With WPA, unique encryption keys for each client are generated dynamically and refreshed periodically by the access point.
802.1x is a flexible authentication protocol that depends on the Extensible Authentication Protocol (EAP). Many different flavors of EAP, including EAP-TLS and PEAP, are supported in WPA-enabled products. If you choose to skip 802.1x and deploy WPA in the much simpler PSK mode, which gives you dynamic encryption key generation but exposes authentication credentials by transmitting them in clear text, all you need to do is configure your access point and wireless clients with the same pre-shared key.
If, however, you want to use WPA to its full potential by employing the much-stronger authentication mechanisms in 802.1x, you need a RADIUS server. Commercial tools are available for this work, such as Funk Software's Steel Belted RADIUS. But if you prefer a free and open-source RADIUS application, FreeRADIUS supports all major flavors of EAP and is both stable and secure. Here's how you can put it to work.
Naturally, I don't have enough space to describe all possible uses of FreeRADIUS with 802.1x or even specifically with wireless scenarios. Therefore, let's start with a description of an example usage scenario that subsequent procedures can implement.
The most important choice to make when implementing WPA is which flavor of EAP to use. This is limited not only by what your RADIUS server software supports but also by your client platforms. Your wireless access point, interestingly, is EAP-agnostic—assuming it supports 802.1x and/or WPA in the first place. It simply passes EAP traffic from clients to servers, without requiring explicit support for any particular EAP subtype.
What your client platform supports is a function both of your client operating system and of its wireless hardware. For example, a Microsoft Windows XP system with an Intel Pro/2100 (Centrino) chipset supports EAP-TLS and PEAP, but EAP-TTLS isn't an option. But if you run Linux with wpa_supplicant (see the on-line Resources), you have a much wider range of choices available.
In our example scenario, I cover EAP-TLS. EAP-TLS requires client certificates, which in turn requires you to set up a certificate authority (CA). But there are several good reasons to use EAP-TLS. First, EAP-TLS is supported widely. Second, TLS (X.509 certificate) authentication provides strong security. Third, it really doesn't require that much work to use OpenSSL to create your own CA.
Our example scenario, therefore, involves Windows XP clients using EAP-TLS to connect to a WPA-enabled access point. The access point, in turn, is configured to authenticate off of a FreeRADIUS 1.0.1 server running Linux.
SuSE 9.2, Fedora Core 3 and Red Hat Enterprise Linux each has its own FreeRADIUS RPM package, called freeradius. Debian Sarge (Debian-testing) has a DEB package by the same name. With Red Hat, Fedora and Debian-testing, additional packages are available if you want to use a MySQL authentication database. In addition, Debian-testing has a few other features broken out into still more packages. With all four distributions, however, the only package you should need for 802.1x authentication is the base freeradius package. If your favorite Linux distribution doesn't have its own FreeRADIUS package, or if it does but not a recent enough version to meet your needs, you can download the latest FreeRADIUS source code from the Web site (see Resources).
Compiling FreeRADIUS is simple: it's the common ./configure && make && make install routine. If you're new to the compiling game, see the source distribution's INSTALL file for more detailed instructions. You should execute the configure and make commands as some nonroot user and execute only make install as root.
Notice that, by default, the configure script installs FreeRADIUS into subdirectories of /usr/local. Because the Makefile has no uninstall action, I recommend leaving this setting unchanged, as it simplifies removing FreeRADIUS later, should that become necessary.
Before we configure FreeRADIUS, we need to create some certificates. And before we create any certificates, we must create our CA. My book Linux Server Security contains a section in Chapter 5 titled “How to Become a Small-Time CA”, which goes into more depth than I can go into right now, but here's a crash course nonetheless.
First, what is a CA and where should it reside? A CA is a system that acts as the root of a public key infrastructure. It's the central authority that vouches, by way of digital signatures, for the authenticity of all certificates issued in your organization. It also periodically issues certificate revocation lists (CRLs), lists of certificates the CA no longer vouches for, for example, certificates issued to people who've left the organization, servers that are no longer on-line and so on.
None of this requires your CA to act as an actual server; in fact, it's better if it doesn't. For a CA to be trustworthy, it must be protected carefully from misuse. My own CAs, therefore, tend to reside on systems I only periodically connect to the network, such as VMware virtual machines.
You already may have a CA that you've used to create certificates for Web servers, stunnel or other applications that use TLS. If so, you can use it for WPA too. If not, here's how to create a CA. First, make sure your designated CA system has OpenSSL installed. OpenSSL is a standard package on all popular Linux distributions, not to mention FreeBSD, OpenBSD and the like. One quick way to make sure you have OpenSSL is to issue the command which openssl—this returns the path to your OpenSSL command, if it's installed.
Next, change your working directory to wherever your system keeps OpenSSL's configuration and certificate files. On SuSE, this is /etc/ssl, but this location varies by distribution. Doing a search for the file openssl.cnf should bring you to the correct place.
Now, open the file openssl.cnf with your text editor of choice. We need to tweak some default settings so as to make certificate creation speedier later on. Listing 1 shows the lines in openssl.cnf I like to change.
Listing 1. Changes to openssl.cnf for Optimal Certificate Creation
# First we change the CA root path in the CA_default # section to reflect the CA we're about to create [ CA_default ] dir = ./micksCA # Where everything is kept # The following lines are further down in openssl.cnf: countryName_default = US stateOrProvinceName_default = Minnesota 0.organizationName_default = Industrial Wiremonkeys of the World
Next, we should edit the CA creation script to change our CA's root directory to something other than demoCA, that is, to match the dir variable we just changed in openssl.cnf. I use the script CA.sh, which on SuSE systems is located in /usr/share/ssl/misc but may reside elsewhere on your system. The line you need to change is CATOP=./micksCA.
If you changed your working directory to edit this file, change back to your SSL configuration directory, for example, /etc/ssl. From there, run the CA.sh script with the -newca option, for example, /usr/share/ssl/misc/CA.sh -newca. You then are prompted to create a new root certificate and to type a passphrase for its private key. Choose a difficult-to-guess passphrase, and write it down in a safe place—if you forget it, you'll be unable to use your CA.
After the script is done, your SSL configuration directory should contain a new directory, micksCA in our example. At the root level of this directory is your new CA's public certificate; by default this file is named cacert.pem. As I demonstrate later, you need to copy this file to your FreeRADIUS server and to each wireless client.
There's one more thing you need to do before creating certificates if you've got Windows XP wireless clients. Windows XP expects certain attributes in server and client certificates, so you need to create a file called xpextensions that contains the lines shown in Listing 2.
Listing 2. Contents of xpextensions
[ xpclient_ext] extendedKeyUsage = 18.104.22.168.22.214.171.124.2 [ xpserver_ext ] extendedKeyUsage = 126.96.36.199.188.8.131.52.1
The xpextensions file is referenced in some of the OpenSSL commands I'm about to show you. It should reside in the same directory as openssl.cnf.
How EAP-TLS Works
In EAP-TLS, a wireless client and your RADIUS server mutually authenticate each other. They present each other with their respective certificates and cryptographically verify that those certificates were signed by your organization's certificate authority. In some ways, this is an elegant and simple way to handle authentication. After you install the CA's public certificate on the FreeRADIUS server, you don't need to configure any other client information explicitly, such as user names, passwords and so on.
That doesn't mean EAP-TLS is less work than user name-password schemes, however. You still need to use OpenSSL to create certificates for all your users and copy those certificates over to them. You also need to ensure that everyone has a copy of the root CA certificate installed in the proper place.
For EAP-TLS, you need at least two certificates besides your CA certificate, a server certificate for your FreeRADIUS server and one client certificate for each wireless client on your network. Creating certificates is a three-step process:
Generate a signing request, that is, an unsigned certificate.
Sign the signing request with your CA key.
Copy the signed certificate to the host on which it will be used.
Let's start by creating a server certificate signing request using OpenSSL's req command:
$ openssl req -new -nodes -keyout server_key.pem -out server_req.pem -days 730 -config ./openssl.cnf
This command creates the files server_req.pem, which contains the actual request—an unsigned certificate—and server_key.pem, its passphrase-less private key. First, though, you are prompted for your organization's Country Code, State and so on, much of which can use the default values you tweaked in openssl.conf. Pay special attention, however, to Common Name. When prompted for this, type the fully qualified domain name of your server, for example, server.wiremonkeys.org.
Next, let's use our CA key to sign the request by using OpenSSL's ca command:
$ openssl ca -config ./openssl.cnf \ -policy policy_anything -out server_cert.pem \ -extensions xpserver_ext -extfile ./xpextensions \ -infiles ./server_req.pem
This command reads the file server_req.pem and, after prompting for your CA key's passphrase, saves a signed version of it plus its corresponding private key to the file server_cert.pem. Notice the -extensions and -extfile options—this is why earlier we created the file xpextensions.
Open your signed certificate with the text editor of your choice and delete everything before the line -----BEGIN CERTIFICATE-----. Concatenate it and your key into a single file, like this:
$ cat server_key.pem server.cert.pem > \ server_keycert.pem
Now we've got a server certificate with a key that we can copy over to our FreeRADIUS server. Its private key isn't password-protected, however, so be sure to delete any extraneous copies after you've got it in place.
Now we need to create a client certificate signing request. The OpenSSL command to do this is similar to that used to create server certificates:
$ openssl req -new -keyout client_key.pem \ -out client_req.pem -days 730 -config ./openssl.cnf
As you can see, we're writing our signing request and key to the files client_req.pem and client_key, respectively. Unlike with the server signing requests, however, we're omitting the -nodes option. Therefore, when you run this command, you are prompted for a passphrase with which the certificate's private key can be encrypted.
Next we sign the client certificate's signing request:
$ openssl ca -config ./openssl.cnf \ -policy policy_anything -out client_cert.pem \ -extensions xpclient_ext -extfile ./xpextensions \ -infiles ./client_req.pem
Again, this is similar to the equivalent command for our server, except this time the -extensions command references a different entry in xpextensions. Also, if your clients run Linux, you should delete the extraneous stuff in the certificate, like you did with server_cert.pem. You then either can leave the certificate and key files separate or concatenate them. From there, copy your client certificate file(s) to your Linux client system.
If your certificate is to be used by a Windows XP client, you have one more step to take. You need to convert the certificate file(s) to a PKCS12-format file, with this command:
openssl pkcs12 -export -in client_cert.pem \ -inkey client_key.pem -out client_cert.p12 -clcerts
You are prompted for client_key.pem's passphrase and then for a new passphrase for the new file; you can use the same password as before if you like. You may be tempted simply to press Enter instead, especially given that the WPA supplicant in Windows XP works only when you store its certificates without passphrases. It's very, very bad practice, however, to move private keys around networks unprotected, so I strongly recommend that you not remove the passphrase until after this file is copied safely over to your Windows XP client.
Lest you be tempted to take this opportunity to bash Microsoft, I must note that both Xsupplicant and wpa_supplicant on Linux require you to either use a blank passphrase or store the passphrase in clear text in a configuration file. This is contrary to good certificate-handling wisdom. I hope we some day see WPA supplicants intelligent enough to prompt the user for its certificate passphrase on startup.
The resulting file, in this example client_cert.p12, contains both your signed certificate and its private key. Copy it to your Windows XP client system.
We've installed FreeRADIUS, created a certificate authority, generated server and client certificates and transferred them to their respective hosts. But we're not done yet. We still need to configure FreeRADIUS, our access point and our wireless clients. We'll do all that next time. Until then, be safe!
Resources for this article: /article/8134.
Mick Bauer, CISSP, is Linux Journal's security editor and an IS security consultant in Minneapolis, Minnesota. O'Reilly & Associates recently released the second edition of his book Linux Server Security (January 2005). Mick also composes industrial polka music but has the good taste seldom to perform it.