You are hereForums / Computers / CentOS server setup and maintenance notes / WPA Radius, CentOS 5 and ndiswrapper

WPA Radius, CentOS 5 and ndiswrapper


By admin - Posted on 21 October 2008

Believe it or not, it actually can be made to work. I should know. This is the second time I've fumbled my way through configuring three different pieces of software (openssl, wpa_supplicant and freeRADIUS) and three different pieces of hardware (the laptop, my server and my wireless access point) to get it working. The first time I got it working, I think I was still running Fedora Core 5 (FC5) on the laptop. I upgraded the laptop to FC6 and it stopped working. I putzed with the configuration for long enough to remember the pain I'd gone through the first time and decided the WPA pre-shared keys (WPA PSK) was sufficient.

I had always wanted to get WPA Radius working again but it never made it to the top of the priority queue. My previous job was working at a company called Vericept that is in the information protection business. I developed a healthy level of paranoia while I worked there so that was probably one of the drivers for me getting WPA Radius working again. That and I hate to have something like this that should work but doesn't.

Oh, yeah, back to why I write this blog. Knowing that I had gotten WPA Radius working once and had not been able to get it working again was one of the specific instances I was thinking of when I decided to start blogging about the various technical things I had done, things I had gotten to work, etc. Hopefully, the next time this comes up I'll have this blog entry to help me get things working again. Enjoy!

I relied heavily on a three part series of articles that appeared in Linux Journal under the title "Paranoid Penguin - Securing Your WLAN with WPA and FreeRADIUS." Part I provides a good overview of the whole WPA Radius set up while Part II and Part III provide detailed instructions on how to set up WPA Radius. The only problems are the articles appeared in Linux Journal in March and April of 2005 so they're now somewhat dated and the author wrote specifically for SuSE Linux.

The other problem I ran into is that the three pieces of software (and a fourth if you count the firmware on the Linksys WAP) were each written by completely different teams with very different purposes. Thus, openssl is a fine tool for generating SSL certificates, keys and such but the directions for how to use it are generic. Likewise, wpa_supplicant is a general purpose tool for attaching to a WPA or WEP network but it's instructions assume you have the various SSL certificates and keys created by openssl and understand which password goes where for each file and configuration option. The documentation and configuration files for freeRadius make a similar assumption plus provide documentation on a variety of uses for the freeRadius server that aren't of interest to me.

The pieces to be configured are:

  1. the SSL certificates,
  2. the freeRadius server (radiusd),
  3. the wireless access point or WAP, and
  4. wpa_supplicant on the laptop.

Just to make matters even more interesting, my laptop is an HP Pavilion zv6015 with a built-in Broadcom wireless NIC (BCM4306). I have never gotten the NIC to work correctly with either the BCM43XX driver module or the newer BC43 module for this NIC. The best I was able to get was the BCM43XX module would connect at 10mbs and then only if I ran my WAP wide open (no encryption, no authentication). I've got enough data like bank records and such on other systems attached to my network that that this is unacceptable. I was previously successful at getting WPA Radius working with ndiswrapper and, up until now, ndiswrapper has worked just fine with WPA pre-shared keys (WPA PSK) so I had no reason to believe that ndiswrapper wouldn't work now.

Peliminaries

You will need to install freeRadius on the system that will be your radius server and wpa_supplicant on any systems that will be connecting wirelessly to your WLAN. These may already be present but you can use yum to install the freeradius and wpa_supplicant RPMs if not. It's also a good idea to make sure the laptop(s) or wireless remote systems can connect to your WAP using a less complicated protocol such as WEP or WPA PSK. Otherwise, if (when?) things goes wrong, you won't be wondering if the systems can't talk even without the added complexity of WPA Radius.

The SSL certificates

Generating the SSL certificates went pretty much as described in Part II of the Paranoid Penguin articles referenced above. The first tricky thing is that all of the SSL certificate stuff for setting up WPA Radius is under the directory /etc/pki/tls. The first step is to generate your certificate authority using the CA shell script in /etc/pki/tls/misc. The easy part is running the script:

/etc/pki/tls/misc/CA -newca

Unless you like typing the same information over and over you might want to edit the file /etc/pki/tls/openssl.cnf and provide the default values to use when generating certificates. I also changed the value of "dir" from:

dir           = ../../CA              # Where everything is kept

to:

dir           = /etc/pki/CA           # Where everything is kept

I like absolute paths for things like this; especially when I debugging and not really sure where things will/should end up. Now that you have a cacert.pem in /etc/pki/CA. As per the Paranoid Penguin articles, you can choose to have your certificates end up in a directory other than /etc/pki/CA by making the appropriate changes to this file. The cacert.pem file needs to be copied to /etc/raddb/certs on the system that will be the radius server and each wireless client. On my laptop, I put the file in /etc/wpa_supplicant.

If you will have Windows as well as Linux wireless client, follow the articles for setting up the xpextensions file. I don't have an XP or Vista laptop to confirm that the instructions in the article still work. Let me know if you get a Windows wireless client to work and what you had to do and I will add it to this article.

The next step is to generate the actual certificates. From Part II of the Paranoid Penguin articles:

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:

  1. Generate a signing request, that is, an unsigned certificate.
  2. Sign the signing request with your CA key.
  3. Copy the signed certificate to the host on which it will be used.

The signing request is created by running the following command in the /etc/pki/tls directory:

openssl req -new -nodes -keyout server_key.pem \
            -out server_req.pem -days 730 -config ./openssl.cnf

Sign the request with:

openssl ca -config ./openssl.cnf \
           -policy policy_anything -out server_cert.pem \
           -extensions xpserver_ext -extfile ./xpextensions \
           -infiles ./server_req.pem

Open the 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

The server key/certificate also needs to be copied to /etc/raddb/certs.

The client certificate is created in more or less the same manner starting with a signing request:

openssl req -new -keyout client_key.pem \
            -out client_req.pem -days 730 -cofig ./openssl.cnf

which is then signed:

openssl ca -config ./openssl.cnf \
           -policy policy_anything -out client_cert.pem \
           -extensions xpclient_ext -extfile ./xpextensions \
           -infiles ./client_req.pem

The certificate file for the client still needs to have the same clean up as the certificate file for the server but wpa_supplicant.conf has separate items for the certificate and key files so a combined file isn't required for the client. There are additional steps in the Part II article for the certificate for an XP client. Let me know if they work for either XP or Vista. I used scp to put a copy of the client key and certificate files on the laptop which then got moved to /etc/wpa_supplicant.

freeRadius

Getting the freeRadius server running is easy. Getting it running with the correct configuration for WPA Radius authentication and encryption is the hard part. There are four configuration files in /etc/raddb that need to have site specific settings added:

  1. radiusd.conf (the main configuration file),
  2. eap.conf (settings specific to EAP authentication),
  3. clients.conf (where to define your WAP), and
  4. users (contains information about specific network users).

Configuring radiusd.conf was easy since the only change I needed to make was to set the bind address to the internal side of my little network. Configuring eap.conf wasn't much harder since I only needed to uncomment the lines within the tls stanza and point it at the server certificate/key file generated in the SSL certificates step (above) step:

# certificate_file = ${raddbdir}/certs/cert-srv.pem
certificate_file = ${raddbdir}/certs/server_keycert.pem
#  Trusted Root CA list
CA_file = ${raddbdir}/certs/cacert.pem

Given the problems I remembered from my previous attempt at getting WPA Radius working, I decided to leave the certificate checks commented out:

#       check_cert_issuer = "/C=GB/ST=Berkshire/L=Newbury/O=My Company Ltd"
#       check_cert_cn = %{User-Name}

If I get brave (or foolhardy), I may try getting things working with certificate checks enabled.

The final file to configure was the users file. Getting this right was what took the longest. The final answer was to add a line for my laptop that looks like:

spindle         Auth-type := EAP, User-Password == "any-random-string"

The idea is that EAP-TLS doesn't need a password and, in fact, wpa_supplicant doesn't send one. But I went through a lot of banging my head against the wall trying to figure that out. All of the examples in the users file include a password but none of them specify EAP. It urns out that an Auth-Type of EAP doesn't need a password but, and here's the kicker, the parser for the radiusd configuration files rejects the file if there isn't a password present. This appears to just be a vestige of how the parser was set up. Even on successful authentication, the radiusd debug still notes that no client password was provided.

Finally, you also need to define a connection for your WAP in clients.conf. This will look like:

client 192.168.0.0/16 {
        secret          = this-is-our-secret
        shortname       = Linksys-WAP54G
}

The "secret" is the shared secret that your WAP uses to authenticate itself to the radius server.

At this point you should be able to start the radiusd service with something like "service radiusd start." I'd suggest you hold off for a little bit until you have the other pieces (WAP and laptop) configured.

The WAP

Configuring the WAP is probably the easiest part:

WAP54G Advanced security settings

That's it.

wpa_supplicant

You can also use NetworkManager and NetworkManageDispatcher services as a GUI for configuring the laptop's access through WPA Radius. What I like about just editing the wpa_supplicant.conf file is the connection isn't tied to a particular user. To me, NetworkManager is a spill over of Microsoft's view that a computer and a user are one and the same; especially for clients.

My laptop's wpa_supplicant.conf file looks like:

ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
ap_scan=2
network={
        ssid="pr3v3ct"
        proto=WPA
        key_mgmt=WPA-EAP
        eap=TLS
        identity="spindle"
        ca_cert="/etc/wpa_supplicant/cacert.pem"
        client_cert="/etc/wpa_supplicant/client_cert.pem"
        private_key="/etc/wpa_supplicant/client_key.pem"
        private_key_passwd="My private key's password"
        pairwise=TKIP
        group=TKIP
}

Where:

  • ssid is the SSID of your network
  • proto sets the protocol as WPA
  • key_mgmt sets the key management to WPA-EAP (match EAP authentication for radiusd)
  • eap is set to TLS. See the eap.conf file for alternatives. Other choices may not be available depending on your access point and MD5 is not recommended.
  • identity matches the user set up in /etc/raddb/users file as described above for configuring radiusd.
  • The cacert and client certificate and key files from the SSL key and certificate generation section discussed first.
  • private_key_password is the pass phrase used to generate the client certificates. I have my wpa_supplicant.conf file owned by root:root with permissions 600 (only readable and writeable by the owner).
  • pairwise and group set the WPA Algorithm to match the setting at the WAP.

You also need to confirm the /etc/sysconfig/wpa_supplicant is configured correctly. On my laptop, this file looks like:

cat /etc/sysconfig/wpa_supplicant
INTERFACES="-ieth1"
DRIVERS=-Dwext

Adjust the interface setting as needed for your system. Some alternatives are wlan0 and wifi0. I found that the generic driver setting (-D) of wext (wireless extensions) works better than ndiswrapper.

Making it work

In theory, you should be able to just start everything (radiusd on the server, the WAP with it's WPA Radius security enabled and wpa_supplicant on the laptop) and everything will just work. Yeah, right. That's why I said not to start radiusd once it's configuration was done. On the radiusd serve, as root, issue the following command:

radiusd -sfxxyz -l stdout

This starts radiusd in single thread mode (s) in the foreground (f) with lots of debug (xx) and details about authentication (y) including passwords (z). radiusd will spew lots of information about its configuration and you should end up with something like:

...
Listening on authentication 192.168.255.254:1812
Listening on accounting 192.168.255.254:1813
Ready to process requests.

If you don't, look for error messages and correct the problems.

The next step is to make sure the WAP and radius server recognize each other. That is, the WAP sends it's shared secret to the radius server and the radius server authenticates it. After the "... Ready to process requests" you should see:

>>>I'm still trying to figure out how to force the WAP to re-authenticate to the radiusd server.<<<

Again, if this isn't what you see, you need to figure out what isn't set up correctly and fix it.

Finally, run wpa_suppliant on the laptop. Change the settings for interface (-i) and driver (-D) as needed. The -dd asks wpa_supplicant to supply lots of debug:

/usr/sbin/wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -ieth1 -Dwext -dd

You should see something like the following as the output of wpa_supplicant on the client:

...
WPA: Key negotiation completed with 00:12:17:7a:b6:f6 [PTK=TKIP GTK=TKIP]
Cancelling authentication timeout
State: GROUP_HANDSHAKE -> COMPLETED
CTRL-EVENT-CONNECTED - Connection to 00:12:17:7a:b6:f6 completed (auth)
EAPOL: External notification - portValid=1
EAPOL: SUPP_PAE entering state AUTHENTICATED
EAPOL: authWhile --> 0
EAPOL: startWhen --> 0
EAPOL: idleWhile --> 0

Likewise, you should see a lot of spewage from radiusd and:

rad_recv: Access-Request packet from host 192.168.0.250:3074, id=0, length=139
        User-Name = "spindle"
        NAS-IP-Address = 192.168.0.250
        Called-Station-Id = "0012177ab6f6"
        Calling-Station-Id = "00904bac8f67"
        NAS-Identifier = "0012177ab6f6"
        NAS-Port = 4
        Framed-MTU = 1400
        State = 0xe420195868d91fe99c33a60f877d0bf1
        NAS-Port-Type = Wireless-802.11
        EAP-Message = 0x020500060d00
        Message-Authenticator = 0xcef818bf470d15d3a49b9d01341827b4
  Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 5
  modcall[authorize]: module "preprocess" returns ok for request 5
  modcall[authorize]: module "chap" returns noop for request 5
  modcall[authorize]: module "mschap" returns noop for request 5
    rlm_realm: No '@' in User-Name = "spindle", looking up realm NULL
    rlm_realm: No such realm "NULL"
  modcall[authorize]: module "suffix" returns noop for request 5
  rlm_eap: EAP packet type response id 5 length 6
  rlm_eap: No EAP Start, assuming it's an on-going EAP conversation
  modcall[authorize]: module "eap" returns updated for request 5
    users: Matched entry spindle at line 97
  modcall[authorize]: module "files" returns ok for request 5
modcall: leaving group authorize (returns updated) for request 5
  rad_check_password:  Found Auth-Type EAP
auth: type "EAP"
  Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 5
  rlm_eap: Request found, released from the list
  rlm_eap: EAP/tls
  rlm_eap: processing type tls
  rlm_eap_tls: Authenticate
  rlm_eap_tls: processing TLS
rlm_eap_tls: Received EAP-TLS ACK message
  rlm_eap_tls: ack handshake is finished
  eaptls_verify returned 3
  eaptls_process returned 3
  rlm_eap: Freeing handler
  modcall[authenticate]: module "eap" returns ok for request 5
modcall: leaving group authenticate (returns ok) for request 5
Login OK: [spindle/<no User-Password attribute>] (from client Linksys-WAP54G port 4 cli 00904bac8f67)
Sending Access-Accept of id 0 to 192.168.0.250 port 3074
        MS-MPPE-Recv-Key = 0x3e63f967eccc4746a858804d2dd67cd232cafe29225363a2b2312b7d2e9a9dba
        MS-MPPE-Send-Key = 0x3b9ebd9e7b6c0e85e31a3d5aac7a757e61e65f4cc5a09a794946072829c4b20f
        EAP-Message = 0x03050004
        Message-Authenticator = 0x00000000000000000000000000000000
        User-Name = "spindle"
Finished request 5
Going to the next request
Waking up in 6 seconds...
--- Walking the entire request list ---
Cleaning up request 5 ID 0 with timestamp 47b79dd3
Nothing to do.  Sleeping until we see a request.

and /var/log/radius/radiusd.log should have an entry that looks like:

Sat Feb 16 05:56:53 2008 : Auth: Login OK: [spindle/<no User-Password attribute>
] (from client Linksys-WAP54G port 4 cli 00904bac8f67)

Note the "no User-Password attribute" in the message. No user password is provided because one isn't needed. If everything is working you should see something like the following from iwlist:

iwlist eth1 scan
eth1      Scan completed :
          Cell 01 - Address: 00:12:17:7A:B6:F6
                    ESSID:"pr3v3ct"
                    Protocol:IEEE 802.11g
                    Mode:Managed
                    Frequency:2.462 GHz (Channel 11)
                    Quality:53/100  Signal level:-62 dBm  Noise level:-96 dBm
                    Encryption key:on
                    Bit Rates:1 Mb/s; 2 Mb/s; 5.5 Mb/s; 11 Mb/s; 18 Mb/s
                              24 Mb/s; 36 Mb/s; 54 Mb/s; 6 Mb/s; 9 Mb/s
                              12 Mb/s; 48 Mb/s
                    Extra:bcn_int=100
                    Extra:atim=0
                    IE: WPA Version 1
                        Group Cipher : TKIP
                        Pairwise Ciphers (1) : TKIP
                        Authentication Suites (1) : 802.1X

At this point you can kill the command line instances of radiusd and wpa_supplicant, configure radiusd and wpa_supplicant to run as services on the respective systems and start the services.

Finally, wpa_supplicant puts out a spurious error message when used with ndiswrapper. If you see:

ioctl[SIOCSIWPMKSA]: Invalid argument

it is probably not relevant.

Cheers,
Dave