Paranoid Penguin - Securing Your WLAN with WPA and FreeRADIUS, Part III

by Mick Bauer

In the previous two Paranoid Penguin columns, I described how Wi-Fi protected access (WPA) can protect wireless LANs (WLANs) from unauthorized access and eavesdropping. I also began explaining how to use FreeRADIUS to implement WPA on your own WLAN. So far, we covered installing FreeRADIUS, creating a certificate authority (CA) and generating and signing digital certificates for WPA use. This month, I show you where to put those certificates, how to configure FreeRADIUS and how to configure your wireless access point and clients. With this information, you should be off to a good start in securing your WLAN.

A Brief Review

In case you're new to this series of articles or simply need some reminders about precisely what we're trying to achieve, let's briefly review our purpose and scope. WPA adds powerful authentication functionality to the older, cryptographically broken WEP protocol in the form of the 802.1x protocol and its subprotocols, such as EAP, PEAP and EAP-TLS. WPA also adds dynamic session key negotiation and automatic key regeneration, by way of the TKIP protocol. If your wireless client software supports WPA—that is, if it includes a WPA supplicant—and your wireless access point supports WPA, you're two-thirds of the way there already. But if you want to take full advantage of 802.1x, you need a back-end RADIUS server, which is where FreeRADIUS comes in.

In the example scenario I established last time, we're configuring a FreeRADIUS server to authenticate Windows XP wireless clients connecting to any WPA-compatible wireless access point. Our 802.1x method is EAP-TLS. EAP-TLS, you might recall, uses the TLS protocol to authenticate wireless supplicants (clients) and your access point to one another by using X.509 digital certificates.

The tasks at hand in this column are:

  • To install the server and CA certificates we created last time onto our FreeRADIUS server.

  • To configure FreeRADIUS to use these certificates with EAP-TLS to authenticate users for our access point.

  • To configure our access point to redirect authentication to our FreeRADIUS server.

  • To install the client and CA certificates we created last time onto a Windows XP client and configure it to use WPA when connecting to the WLAN.

Preparing the FreeRADIUS Server

In Part II of this WPA series, we created three X.509 digital certificates: a certificate authority certificate, called cacert.pem; one server certificate, called server_keycert.pem; and a client certificate, called client_cert.p12. The server and client files contain both a certificate and its private key, so each of these must be handled carefully. The CA certificate, however, is stored separately from its key, so you can distribute cacert.pem freely.

FreeRADIUS stores its configuration files in either /etc/raddb/ or /usr/local/etc/raddb/, depending on your distribution. This directory contains a subdirectory, certs/—this, naturally, is where you need to copy your CA certificate and your server certificate/key. Make sure that cacert.pem is owned by the user root and that its permissions are set to -r--r--r--. server_keycert.pem, on the other hand, should be owned by the user nobody and its permissions set to -r--------. Listing 1 shows the long directory listings for these two files.

Listing 1. Ownerships and Permissions for Certificates in raddb/certs

-r--r--r--  1 root   users 1294 2005-02-10 01:05 cacert.pem
-r--------  1 nobody users 1894 2005-02-10 01:00 server_keycert.pem

As long as you're attending to file ownerships, you also should make sure that the file /var/log/radius/radius.log and the directory /var/run/radiusd/ are writable by nobody. If you compiled FreeRADIUS from source, these paths instead may be /usr/local/var/log/radius/radius.log and /usr/local/var/run/radiusd/. Both radius.log and radiusd/ may be owned by nobody.

Before we dive into FreeRADIUS' configuration files, we need to create two files that FreeRADIUS must have in order to use TLS. The first is a Diffie-Hellman parameters file, or dh file, which is used for negotiating TLS session keys. To create a dh file, change your working directory to FreeRADIUS' raddb/certs/ directory and issue this command:

# openssl dhparam -check -text -5 512 -out dh

The second file you need is a data file that contains a random bitstream that also is used in TLS operations. Do not simply stick the current timestamp or any other similarly nonrandom string into a file called random, as is suggested in at least one WPA procedure I've seen on the Internet. Rather, use the kernel's high-quality random number generator. From within raddb/certs, run this command:

# dd if=/dev/urandom of=random count=2

Both of these files need to be readable by the user nobody, but they should not be writable by anybody.

Configuring FreeRADIUS

We're finally ready to configure FreeRADIUS. You may be intimidated when you see the long list of files in etc/raddb, but don't be. For WPA with EAP-TLS, we need to edit only three files: radiusd.conf, eap.conf and clients.conf.

In radiusd.conf, all we need to do is set the user and group accounts that the radiusd process runs as. By default these are inherited from whatever user starts the dæmon. If you run radiusd from a startup script, this is root; however, you definitely do not want to run radiusd as root. Therefore, you should set the user and group parameters in radiusd.conf, both set to nobody, as shown in Listing 2.

Listing 2. Two Parameters to Set in radiusd.conf

user = nobody
group = nobody

Naturally you can choose different nonprivileged user and group accounts instead of nobody and nobody, but if you do so, you need to adjust the ownerships and permissions on the certificate files we tweaked earlier. Regardless, make sure your nonprivileged user's entry in /etc/password sets the user's shell to a non-shell, such as /bin/false or /bin/true—this account should not be usable for SSH, telnet or similar programs. For that matter, make sure both the user and group accounts exist in the first place, and create them if they don't.

Other parameters may be set in radiusd.conf, but these really are the only two whose default settings need to be changed. See the radiusd.conf(5) man page or Jonathan Hassell's book RADIUS for more information.

The next file we need to edit is eap.conf; here's where the real heavy lifting occurs. Listing 3 shows the lines you need to edit in eap.conf.

Listing 3. Changes in eap.conf

eap {
  # There are several generic EAP parameters you can
  # set here, but the important one for our purposes
  # is default_eap_type:

  default_eap_type = tls

  # Next come parameters for specific EAP types. Since
  # we're going to use EAP-TLS, the tls{} section is
  # the one we care about:

  tls {
    # The following parameters tell radiusd where to
    # find its certs and keys, plus dh & random files:

    private_key_password = keYpasSphraSE_GOES_h3r3
    private_key_file = ${raddbdir}/certs/bt_keycert.pem
    certificate_file = ${raddbdir}/certs/bt_keycert.pem
    CA_file = ${raddbdir}/certs/cacert.pem
    dh_file = ${raddbdir}/certs/dh
    random_file = ${raddbdir}/certs/random

In Listing 3, I've specified a server-key passphrase with the private_key_password parameter. This actually should be empty if you created your server certificate and key with OpenSSL's -nodes option. Unfortunately, I told you to use this option in last month's column, and I'm retracting that advice now: it is poor practice to use passphrase-free X.509 keys, even when that key is stored in a clear-text configuration file such as eap.conf. Yes, if the FreeRADIUS server gets rooted—hacked into with root privileges—even a passphrase-protected certificate still can be compromised, thanks to eap.conf. But if the certificate/key file is eavesdropped in transit—when, for example, you transfer it from your CA host to your FreeRADIUS server—it is useless to the attacker if it's passphrase-protected.

Either way, make sure that eap.conf is owned and readable only by root and not by the unprivileged user account you configured in radiusd.conf. This may seem paradoxical—doesn't nobody need to be able to read configuration files? But, if you start radiusd as root, it reads its configuration files, including radiusd.conf, eap.conf and clients.conf, before demoting itself to nobody.

Finally, you need to create an entry for your access point in clients.conf. Listing 4 shows such an entry.

Listing 4. Access Point Entry in clients.conf

client {
      secret          = 1sUpErpASSw0rD
      shortname       = wiremonkeys_AP

In Listing 4, the client statement specifies the access point's IP address. Its secret parameter specifies a string that your access point uses as an encryption key for all queries it sends to your FreeRADIUS server. shortname simply is an alias for your access point to be used in log entries and so on.

You now can start radiusd by using the rc.radiusd script, for example, rc.radiusd start. You also could restart it with rc.radiusd restart. If radiusd starts without errors, you're ready to go.

Configuring the Access Point

The next step is the easiest part of this entire process: configure your wireless access point to use WPA and to point to your FreeRADIUS server. This requires only two pieces of information, the RADIUS secret you entered in your FreeRADIUS server's clients.conf file and the IP address of your FreeRADIUS server.

How you present those two pieces of information to your access point depends on your particular hardware and software. My own access point is an Actiontec DSL router with WLAN functionality. From its Web interface I clicked Setup→Advanced Setup→Wireless Settings and set Security to WPA. I then configured it to use 802.1x rather than a pre-shared key. I also provided it with a Server IP Address of, my FreeRADIUS server's IP and a Secret of 1sUpErpASSw0rD, as shown in Listing 4. I left the value for Port to its default of 1812.

Speaking of which, if your access point and RADIUS server are separated by a firewall, you need to allow the access point to reach the RADIUS server on UDP ports 1812 and 1813. Doing so also allows the RADIUS server to send packets back from those ports.

Configuring Windows XP Clients

And that brings us to configuring a Windows XP wireless client to use your newly WPA-enabled access point. This being a Linux magazine, I'm not going to describe this process in painstaking detail—for that you can see section 4.3 of Ken Roser's HOWTO, listed in the on-line Resources. In summary, you need to:

  1. Run the command mmc from Start→Run....

  2. In Microsoft Management Console, select File→Add/Remove Snap-in, add the Certificates snap-in and set it to manage certificates for My user account and, on the next screen, only for the Local computer.

  3. Copy your CA (cacert.pem) certificate to your Windows system's hard drive, for example, to C:\cacert.pem.

  4. From within MMC, expand Console Root and Certificates - Current User and right-click on Trusted Root Certification Authorities. In the pop-up menu, select All Tasks→Import. Tell the subsequent wizard to import the file C:\cacert.pem and to store it in Trusted Root Certification Authorities.

  5. Copy your client certificate/key file to your Windows system, for example, to C:\client_cert.p12.

  6. From within MMC→Console Root→Certificates, expand Personal and right-click on Certificates. In the pop-up menu, select All Tasks→Import. Tell the subsequent wizard to import the file C:\client_cert.p12.

  7. The certificate-import wizard then prompts you for the certificate's passphrase. In the same dialog, it offers the option to enable strong private key protection. Unfortunately, enabling this breaks WPA, so be sure to leave this option unchecked. Also, leave the option to mark this key as exportable unchecked—you're better off backing up the password-protected file you just imported rather than allowing the imported nonprotected version to be exportable.

  8. In the subsequent screen, let the wizard Automatically select the certificate store.

Now your Windows XP system is ready to go—all that remains is to create a wireless network profile. This, however, varies depending on your wireless card's drivers and which Windows XP Service Pack you're running. On my Windows XP SP1 system, using a Centrino chipset and XP's native WPA supplicant, I created a wireless network profile specifying my WLAN's SSID. I set Network Authentication to WPA, Data encryption to TKIP and EAP type to Smart Card or other Certificate. Windows automatically determined which client certificate I used—this is because we took pains to create a client certificate that references Windows XP's extended attributes (see my previous column).

After you configure your wireless network profile, your Windows system should connect automatically to your access point and negotiate a WPA connection. If this succeeds, Network Connections should show a status of Authentication succeeded for your Wireless Network Connection entry.


I hope you've gotten this far successfully and are off to a good start with WPA. WPA isn't perfect—the world needs WPA supplicants that can handle passphrase-protected client certificates without storing passphrases in clear text. But, wireless networking is, it seems, finally headed in a secure direction.

Resources for this article: /article/8200.

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.

Load Disqus comments