The following section provides details on setting up and configuring a wireless network with strong 802.1X-based authentication. The RADIUS server used will be the popular FreeRADIUS (running on Linux), and the EAP authentication type will be PEAP using MSCHAPv2 challenge response within the PEAP-protected channel. This configuration is a popular one because it provides strong authentication while minimizing the amount of certificates that need to be in place. It's also supported by default on later versions of Windows. Instructions on configuring Windows, OS X, and Linux-based clients are provided.
This section provides a quick tutorial on creating your own certificate authority (CA) using openssl. If you already have a CA in your organization, you should be able to use it to generate a certificate for your RADIUS server. If this is the case, you can skip this section and move on to configuring FreeRADIUS.
While many people think it takes a lot of resources to be a certificate authority, really all it takes is a self-signed certificate. As the name implies, anyone can sign their own certificate, so this isn't a large technical hurdle. The real burden with becoming a CA is to convince people to trust you to validate identities before signing their certificate request.
First, make sure openssl is installed, and then edit the config file (/etc/ssl/ openssl.conf usually). This configuration file contains default values for the certificates you will generate later. Filling them in here saves some time. The most important setting is the dir value, which is the name of the CA you are going to create.
[ CA_default ] dir = ./jcs_CA # Where everything is kept countryName_default = US stateOrProvinceName_default = California 0.organizationName_default = JCs kickin private network
Once the configuration file is done, you can create the CA. To do this, you need to modify a line in the etc/ssl/misc/CA.sh script and then run it. The CA.sh script will create a self-signed certificate and create a directory structure that openssl expects elsewhere:
[root@diz /etc/ssl]# vim ./misc/CA.sh CATOP=./jcs_CA #change this to the dir value placed in openssl.cnf
Once the script has been edited, go ahead and run it with the -newca parameter. It will ask you to enter a passphrase for the private key. You will be asked to enter this passphrase whenever you create a new certificate. When CA.sh asks for a filename, just press ENTER:
[root@diz /etc/ssl]# ./misc/CA.sh -newca CA certificate filename (or enter to create) Making CA certificate ... Common Name (eg, YOUR name) []:JC's ROOT Certificate for CA [root@diz /etc/ssl]#
Caution |
The CA.sh script isn't terribly careful with file permissions on your CA's private key. Depending on your umask, it may create a private key that is world-readable. Be sure to check the permissions on CA_TOP/private/cakey.pem, and remove the world-readable bit if necessary. |
At this point, you have a self-signed certificate in ./jcs_CA/cacert.pem and a DES-protected private key in ./jcs_CA/private/cakey.pem. Needless to say, you need to keep the private key well protected. Don't leave these things lying around servers with a lot of users or really run any networked services (for example, a web server or RADIUS server). Good suggestions for storage locations include a CD that you physically remove when not in use, or some other non-networked device.
Now that you have a CA, you should start generating some certificates. The nice thing about PEAP is that you don't need certificates for all the clients, just the servers. In this section, you will use openssl to generate a certificate for use by FreeRADIUS. There is one more thing you need to do before creating certificates, however-you need to create a text file containing some extended certificate attributes. Windows XP expects to see these in certificates; otherwise, it will hang during authentication.
You need a file commonly referred to as xpextensions to make Windows clients happy when they validate your server certificate. You can find this file included in FreeRADIUS or many other places on the Internet. Alternately, you could just create it yourself by issuing these commands:
[root@diz /etc/ssl]# vim ./xpextensions [ xpclient_ext] extendedKeyUsage = 1.3.6.1.5.5.7.3.2 [ xpserver_ext ] extendedKeyUsage = 1.3.6.1.5.5.7.3.1
This file contains the object identifiers (OIDs) that Windows wants to see in a certificate in order to use it for certain tasks. One of these OIDs is needed in the server-side certificate issued to the RADIUS server. When using PEAP, you don't need to issue client certificates, and in this tutorial, you won't make use of the xpclient_ext entry. Nonetheless, it doesn't hurt to keep the required attributes in the file, in case you need it for something else later.
With the CA created and the xpextensions file out of the way, you can finally create a certificate for the RADIUS server. This process actually involves creating quite a few temporary files, so creating them in a temporary directory makes it easy to clean up later:
[root@diz /etc/ssl]# mkdir tmp; cd tmp [root@diz /etc/ssl/tmp]# openssl req -nodes -new -keyout radius_server_key.pem -out radius_server_req.pem -days 365 Generating a 1024 bit RSA private key Common Name (eg, YOUR name) []:radiusserver1.802.11mercenary.net
This will create two files: the RADIUS server's private key (radius_server_key. pem) and a certificate signing request or CSR (radius_server_req.pem). The RADIUS server's private key is not protected by a passphrase because you passed the -nodes (no DES) option. This means the private key itself is not encrypted. When moving this key, be sure to do it over a secure channel, such as ssh.
The certificate signing request needs to be signed by the CA. Let's do that now. Notice in the following command how the xpextensions file is referenced:
[root@diz /etc/ssl]# openssl ca -config ./openssl.cnf -policy policy_anything -out ./tmp/radius_server_cert.pem -extensions xpserver_ext -extfile ./xpextensions -infiles ./tmp/radius_server_req.pem Using configuration from ./openssl.cnf Enter pass phrase for ./jcs_CA/private/cakey.pem: MySecureCARootPassPhrase Certificate is to be certified until Apr 10 15:22:22 2007 GMT (365 days) Sign the certificate? [y/n]:y [root@diz /etc/ssl]# ls ./tmp radius_server_cert.pem radius_server_key.pem radius_server_req.pem
You now have three files: the RADIUS server's private key, its recently signed certificate, and the old CSR. You no longer need the CSR, so you can safely delete it. For ease of maintenance, you are going to combine the private key and the certificate into one file (less things to lose). To do that, you have to clean up the certificate file you just created. radius_server_cert.pem contains some extraneous text output on the top; open it in your favorite editor and trim it down so it just contains the body of the certificate (it starts with -----BEGIN CERTIFICATE):
[root@diz /etc/ssl/tmp]# rm radius_server_req.pem [root@diz /etc/ssl/tmp]# vim radius_server_cert.pem <cut out extra stuff on top>
The last thing you need to do is to combine the two files. You can simply concatenate them together now:
[root@diz /etc/ssl/tmp]# cat radius_server_cert.pem radius_server_key.pem > radius_server_cert_plus_key.pem
If everything has gone well, radius_server_cert_plus_key.pem should look like the following:
[root@diz /etc/ssl/tmp]# cat radius_server_cert_plus_key.pem -----BEGIN CERTIFICATE----- MIIDVjCCAr... -----END CERTIFICATE----- -----BEGIN RSA PRIVATE KEY----- MIICXQ.. -----END RSA PRIVATE KEY-----
Finally, you have a certificate file to use with the RADIUS server. Copy the combined file securely to the RADIUS server (ssh, USB keychain, and so on). Once you have copied radius_server_cert_plus_key.pem to the RADIUS server, it is a good idea to clean up inside the CA. You definitely don't want to leave the private key lying around. If you have a secure file removing tool installed (such as srm), use it to delete everything created in the temporary directory:
[root@diz /etc/ssl/tmp]# scp radius_server_cert_plus_key.pem root@radiusserver1:/root/ [root@diz /etc/ssl/tmp]# ls radius_server_cert.pem radius_server_cert_plus_key.pem radius_server_key.pem [root@diz /etc/ssl/tmp]# srm radius_server_*
At this point, you have copied over the RADIUS server's certificate and securely deleted any files lying around that contained the RADIUS server's private key. The last thing you need to do is to copy the certificate authority's root certificate to the RADIUS server. It's a good idea to place this certificate someplace convenient, as it contains no secret keys, and it does no harm to distribute it. Any clients that want to be able to validate the RADIUS server's certificate will need a copy of this file.
[root@diz /etc/ssl/tmp]# scp ../jcs_CA/cacert.pem root@radiusserver1:/root/
Now that you have generated a certificate for the RADIUS server to use, you can start to configure it. FreeRADIUS compiles and installs like most open-source code (with a ./configure and make install). By default, it installs code into /usr/local/sbin and its configuration files into /usr/local/etc/raddb. The following examples assume a typical directory layout. FreeRADIUS comes with a certs directory complete with an example setup. You will move that out of the way in case it comes in handy later:
[root@radiusserver1 ~]# cd /usr/local/etc/raddb [root@radiusserver1 /usr/local/etc/raddb]# mv certs/ certs.stock [root@radiusserver1 /usr/local/etc/raddb]# mkdir certs [root@radiusserver1 /usr/local/etc/raddb]# mv /root/radius_server_cert_plus_ key.pem ./certs [root@radiusserver1 /usr/local/etc/raddb]# mv /root/cacert.pem ./certs
Once the certificates are in place, you need to create few other files inside the certs directory. This includes a random seed for the RADIUS server and a Diffie-Hellman parameter file created by openssl.
[root@radiusserver1 /usr/local/etc/raddb]# dd if=/dev/random of=./certs/random count=2 [root@radiusserver1 /usr/local/etc/raddb]# openssl dhparam -check -text -5 512 -out ./certs/dh
If everything worked correctly, you should see the following four files inside the certs directory:
[root@radiusserver1 /usr/local/etc/raddb]# ls ./certs cacert.pem dh radius_server_cert_plus_key.pem random
You have now created all the files you will need. It's time to wade into FreeRADIUS's configuration files.
The clients.conf file contains a list of APs (or Network Access Servers in RADIUS speak) that should be talking to the RADIUS server. This file authenticates devices that should be talking to the RADIUS server via two (relatively weak) techniques.
The first thing the RADIUS server checks for is to make sure the source IP address is one that it recognizes on a trusted list. Assuming that is true, it then authenticates the packet using a shared secret and MD5. You can have unique shared secrets for every AP on your network, or you can use the same one across them all. Clearly, using different secrets is better for security, but it can also be a big management headache. In the following example, the RADIUS server allows a single AP to connect to the server using a shared secret of SuperSecretRadiusSecret.
Many people overlook the importance of this RADIUS secret as the last line of defense against a large-scale network intrusion. Refer to Chapter 7 to see how important this secret can be if an attacker can sniff your wired traffic.
[root@radiusserver1 /usr/local/etc/raddb]# vim clients.conf client 192.168.2.1/32 { secret = SuperSecretRadiusSecret shortname = LinksysWRT_AP }
If you look carefully in the clients.conf file, you will notice that it has a default entry for localhost. This allows for debugging of the configuration. It's a good idea to keep it for now, but once everything is working, you should comment it out for security reasons.
The radiusd.conf file contains general RADIUS server settings. It can be a bit overwhelming at first, but the comments above each section provide good insight into exactly what each section controls. Since you are setting up a typical configuration, you do not have to change much.
The first thing you are going to do is tell FreeRADIUS who to run as. In this case, you can run as nobody because you won't need access to a database or the shadow file. In more complicated environments, you may need to choose a different user ID.
[root@radiusserver1 /usr/local/etc/raddb]# vim radiusd.conf user = nobody group = nobody
Once the user and group are set, you need to make some changes to the way MS- CHAP is configured. The MS-CHAP section is inside the modules section. You have to tell MS-CHAP to use Microsoft Point-to-Point Encryption (MPPE) to transport the PMK to the AP. You also have to tell the MS-CHAP module to require encryption. Once you are done editing, this section should look like the following:
mschap { authtype = MS-CHAP use_mppe = yes require_encryption = yes require_strong = yes }
The rest of the radiusd.conf file can probably be left alone, but it's good to double-check that the default settings are still correct. To that end, make sure the authorize section looks like
authorize { preprocess chap mschap suffix eap files }
Finally, in the authenticate section, make sure the following entry is uncommented:
Auth-Type MS-CHAP { mschap }
Once you have verified the authenticate and authorize sections, you have finished editing the radiusd.conf file.
In this example, you simply read the usernames and passwords out of a plaintext file. FreeRADIUS has support for integrating with LDAP MySQL and other databases as well, but configuring them is outside the scope of this book. Even if you plan on using a database for authentication purposes, debugging your configuration is much easier when you just use a plain file.
The user's file is included with FreeRADIUS, and it has a number of example entries in it. It's a good idea to keep it around for reference, but you're going to write your own simple one:
[root@radiusserver1 /usr/local/etc/raddb]# mv users users.stock [root@radiusserver1 /usr/local/etc/raddb]# vim users gooduser1 User-Password == "secret1" gooduser2 User-Password == "secret2"
So far the RADIUS server knows what APs it should be talking to, the usernames and passwords of the users, and who it should run as. You have yet to tell it anything about the specific authentication techniques you are going to use. All of this information is contained in the eap.conf file.
The first change you are going to make is to set the default EAP type to PEAP:
[root@radiusserver1 /usr/local/etc/raddb]# vim eap.conf default_eap_type = peap
The next thing you need to do is uncomment the TLS section and tell it where to find the relevant certificates and random seeds. Even though you are using PEAP, PEAP uses TLS to create the tunnel. You will need to uncomment and modify the following lines:
tls { private_key_file = ${raddbdir}/certs/radius_server_cert_plus_key.pem certificate_file = ${raddbdir}/certs/radius_server_cert_plus_key.pem CA_file = ${raddbdir}/certs/cacert.pem dh_file = ${raddbdir}/certs/dh random_file = ${raddbdir}/certs/random }
A common mistake is to forget to uncomment the closing bracket. Be careful. The next chunk of the configuration file that needs editing is the PEAP block. This section is straightforward; all you need to do is uncomment three lines:
peap { default_eap_type = mschapv2 }
Now that everything has been configured, it's time to fire up the RADIUS server. Before editing your server scripts to start the RADIUS server by default, it's a good idea to run it by hand in debugging mode to make sure everything works. If everything goes well, you should see the following output:
[root@radiusserver1 /usr/local]# ./sbin/radiusd -X Starting - reading configuration files ... Listening on authentication *:1645 Listening on accounting *:1646 Ready to process requests.
Fortunately configuring most APs is easy. This makes sense because the whole point of the 802.1X model is to let the authentication server and the client do all the heavy lifting; the AP is just proxying messages back and forth.
Figure 8-1 shows a Linksys WRT54g configured for RADIUS-based authentication. You need to decide if you are using TKIP or AES-based CCMP on the wireless side. Most people are still using TKIP because some clients don't support CCMP. The only thing the AP needs to know regarding the RADIUS server is its shared secret, the IP address, and the port. You should double-check the port since there is some confusion as to what the default should be (1645 or 1812).
There are two steps to configuring a Windows client to use PEAP authentication. The first step is to install the root CA certificate on the Windows machine. If you already have a CA for your organization and you used it to create your RADIUS server's certificate, you can skip this step. You can also skip this step if you don't want your clients to validate the RADIUS server's certificate, but doing so opens you up to the man-in-the-middle attack outlined in Chapter 7.
Copy the root certificate onto the Windows machine. For this example, you will assume it is in d:\cacert.pem. Open up the Microsoft management console by going to Start | Run mmc. Then click File | Add/Remove Snap-in and add the Certificates snap-in. Tell the snap-in to manage certificates for My User Account when it asks (this choice should be the default). Click through the rest of the dialogs until you arrive back at the main menu. At this point, you should have a screen that looks like the one shown here.
Now, right-click Trusted Root Certificate Authorities and select All Tasks | Import. Browse to your copy of the root certificate (D:\cacert.pem, for example) and tell it to place the certificate in the Trusted Root Certification Authorities store (this option should be the default). After this, just click through the boxes until you have finished. Once you have imported the certificate, you can safely delete cacert.pem; Windows has stored it inside a certificate store.
Now that Windows can verify the RADIUS server's certificate, you can configure PEAP on the client. Windows has lots of automatic login features to make the user's life easier. The Windows supplicant can try to authenticate itself automatically as a computer or as a guest. It can also try to authenticate using the user's login and password. All of these features can be handy once everything is working, but when you are trying to set things up for the first time, it's easier to turn them off and do this by hand. To set up PEAP so that you can manually enter the username and password, do the following:
First go to the Properties dialog, available by right-clicking on your wireless connection inside the control panel. From the Wireless Network tab, select the network you are interested in from the Preferred Networks List and click Properties. If you don't see the network, you can just click Add.
Set the Network Authentication type to WPA in the Wireless Network Properties dialog. Be sure to select the correct type of encryption as well (TKIP or AES). Once you've done this, you should see a screen that looks like the following:
Now click the Authentication tab. Select PEAP from the EAP Type drop-down menu. Remove the checkmark from the Authenticate as Computer… box if it is enabled. You also don't want the Authenticate as Guest… option either. Your screen should look the following when finished.
Next click the Properties button. Here, you can choose to validate the server certificate or not. I recommend disabling this for debugging purposes and then enabling it later once everything is working. The authentication method to use inside the tunnel is shown at the bottom. The default is MSCHAPv2, which is what you set up on the RADIUS server. The last thing to do is click the Confi gure… button at the bottom of the dialog. You don't want Windows to automatically use its login name and password, so remove the checkmark here. Figure 8-2 shows the end result.
After all that clicking, Windows is configured to use PEAP authentication without trying any of its automatic authentication techniques. The user will just be presented with a simple username and password dialog box when she connects.
Once you've completed this, go ahead and connect. If you successfully prevented Windows from using one of its automatic logon techniques, you should see a screen that looks like the one shown next. If you never see one of these login boxes, you probably forgot to click the Configure button next to EAP-MSCHAPv2 in the PEAP properties dialog.
Assuming everything works, Windows will show that you've successfully connected to the network. If that attempt was successful, you should go back and enable certificate validation to make sure it still works. If you didn't log in correctly, the best thing to do is look over the RADIUS server's output carefully when running in debug mode.
In order to get OS X working with PEAP you don't need to do anything. When you attempt to associate with a PEAP-connected network in OS X, it is smart enough to detect the type of authentication being used and prompt the user accordingly. Simply selecting a PEAP-protected network from the AirPort menu brings up the following login box.
Once the user presses OK, he will be prompted with a message saying the server's certificate is signed by an unknown root certificate authority. The user can either cancel or choose to continue without validating the certificate.
If the user chooses to continue, OS X will save the certificate and remember that the user trusts it from now on. I feel that this is a bit of a bad design choice because it's not at all clear that the OS is going to continue trusting this certificate forever. A dialog box similar to the one used for an SSL certificate (Accept One Time Only, Accept Forever…) would be more suitable.
Though OS X makes it easy (some might say a little too easy) to connect to the wireless network without having the root CA's certificate installed, you may still want to do so. All you need to do is go to Applications/Utilities/Keychain Access. Once Keychain Access is open, click the X509Anchors keychain and go to File | Import. Browse to the location of cacert.pem and click OK. Once you have done this, you will need to restart Keychain Access to show that the root certificate is now valid.
Caution |
It should be mentioned that even if OS X can verify the RADIUS server's certificate, it will prompt the user asking if she wants to continue. In this case, the message box will say something about trust paths instead of unknown root authority. It seems that OS X is trying to tell us that the certificate, though valid, isn't configured to be used as a RADIUS server certificate. It is not clear how to configure OS X to behave differently. |
It seems like every good idea gets at least two similar-but-different implementations on Linux, and 802.1X supplicants are no exception. The two popular ones are XSupplicant and the simply named wpa_supplicant. Most distributions ship wpa_supplicant by default, so that's what is covered here.
Configuring wpa_supplicant to support PEAP is actually straightforward. The difficult part for some users is compiling wpa_supplicant with support for your driver. In particular, wpa_supplicant needs a little help to enable MadWifi support. Before you build your own wpa_supplicant, you should see if the one you already have installed supports your wireless driver. Assuming you need to build-in support for MadWifi, this is how you would do it:
[root@phoenix:/home/johnycsh/wpa_supplicant-0.4.9]$ cp defconfig .config [root@phoenix:/home/johnycsh/wpa_supplicant-0.4.9]$ vim .config # Driver interface for madwifi driver CONFIG_DRIVER_MADWIFI=y # Change include directories to match with the local setup CFLAGS += -I/root/wi-fi/drivers/mad-wifi/2006-01-24/karma-patched/ [root@phoenix:/home/johnycsh/wpa_supplicant-0.4.9]$ make & make install
Of course, the path to your MadWifi source will vary.
Assuming you have a working wpa_supplicant installed, now you need to create its configuration file. The following config file will work with our setup:
[root@phoenix:~]$ vim /etc/wpa_supplicant.conf network={ ssid="Radium" key_mgmt=WPA-EAP eap=PEAP identity="gooduser1" password="secret1" phase1="peaplabel-1" phase2="auth=MSCHAPv2" priority=10 }
Once the file is created, you can start wpa_supplicant manually using the following command:
[root@phoenix:/home/johnycsh/wpa_supplicant-0.4.9]# ifconfig ath0 up [root@phoenix:/home/johnycsh/wpa_supplicant-0.4.9]# wpa_supplicant -Dmadwifi -i ath0 -c /etc/wpa_supplicant.conf Trying to associate with 00:16:b6:16:a0:c7 (SSID='Radium' freq=2437 MHz) Associated with 00:16:b6:16:a0:c7 CTRL-EVENT-EAP-STARTED EAP authentication started EAP-PEAP: Unsupported Phase2 method 'MSCHAPv2' CTRL-EVENT-EAP-METHOD EAP method 25 (PEAP) selected EAP-MSCHAPV2: Authentication succeeded EAP-TLV: TLV Result - Success - EAP-TLV/Phase2 Completed CTRL-EVENT-EAP-SUCCESS EAP authentication completed successfully WPA: Key negotiation completed with 00:16:b6:16:a0:c7 [PTK=TKIP GTK=TKIP] CTRL-EVENT-CONNECTED - Connection to 00:16:b6:16:a0:c7 completed (auth)
If you have trouble connecting, try appending a -d (debug) to the wpa_supplicant command line. Once wpa_supplicant is connected, you can configure your interface as usual (for example, run a dhcp client). If you successfully connect but then see a DISCONNECTED message, I have found that it helps to unload and reload the MadWifi kernel module and simply try again.
A lot can go wrong when trying to set up a RADIUS server, especially if it's your first one. Here are a few common problems and the likely culprits.
My Windows box hangs on authentication, but I swear everything is configured correctly. This is quite common. If you have another box around (a Mac would be easiest), try authenticating with that. Did it work? If so, your Windows box probably doesn't like the certificate the RADIUS server is sending (not that it will actually tell you this).
The most likely scenario is that your RADIUS server's certificate is lacking the magic server-side authentication OID (1.3.6.1.5.5.7.3.1), which is mentioned in the xpextensions file earlier. It's also possible you don't have a trusted root certificate installed on the Windows machine that can verify the certificate.
It has been my experience that when a Windows box configured to validate server certificates lacks the root certificate required to verify it, Windows will ask the user if he trusts it. Even if the user says yes, Windows will proceed to hang indefinitely during authentication. While I applaud Microsoft for not using a certificate it can't validate, asking the user and then ignoring the input is a very confusing course of action. Hanging forever also isn't as useful as, say, a pop-up box mentioning the problem.
When debugging Windows-PEAP authentication issues, the easiest thing to do is to tell Windows not to verify the server certificate. If that fixes the problem, then you know everything other than the certificate is set up correctly.
My RADIUS server seems to ignore everything coming at it. RADIUS has actually had two ports assigned to it over the years. The original port was 1645. This port was found to clash with a service called datametrics and RADIUS got bumped to 1812. It's quite possible that your APs are sending RADIUS packets to one port and you are listening on another. You need to either configure the AP to use the correct port or manually tell FreeRADIUS what port to listen on. You can tell FreeRADIUS what port to use explicitly with -p on the command line.
My RADIUS server hangs indefinitely when I start it. The ports are listening, but no one is home. If you tell FreeRADIUS to use /dev/random for the random file in the TLS section, it may hang indefinitely. On Linux systems, /dev/random will block until it has generated enough entropy. You don't want your RADIUS server waiting around all day for a few bits. Either create the random file as specified in the tutorial or use /dev/urandom instead.
It worked fine in debug mode, but now FreeRADIUS won't start. Check the FreeRADIUS log file (usually /usr/local/var/log/radius.log). Is it having a problem launching because it can't create a PID file?
When you run the server in debug mode, it runs as root. If the server fails to clean up after itself on the next run when it tries to create the PID file as nobody, it will fail. Just delete the stale PID file.