This document describes the basic elements of WPA wireless security, mainly because it's somewhat confusing and the necessary information is scattered around the Internet. For implementation, I'm primarily concerned with Debian Linux - especially the current unstable (note: appropriate packages will likely be in "etch", which is currently the testing release).
*BSD users are, unfortunately, screwed.
/etc/wpa_supplicant.conf/etc/default/wpasupplicantRecently my employer changed their campus-wide wireless network. While the previous authentication system is still maintained, it requires setting a machine's ESSID explicitly, and will likely not be maintained for much longer. The new authentication scheme is based on 802.1x and WPA, necessitating some end-user self-education. Given that the new system allows for seamless roaming, and supports 802.11g (as opposed to just 802.11b), learning about WPA seemed prudent. Since others at work also have Debian laptops, this little guide was born.
Much of the text below constitutes some personal notes on WPA in general. If you're looking for just the basic information, and you're in a rush to just turn things on, you may want to skip to section 3.
In the beginning, there was WEP - Wired Equivalent Privacy. Problem is, it really wasn't (equivalent to wired). The crypto used to ensure privacy wasn't very robust, was deployed in an extremely poor manner, and relied on shared secrets for any authentication. Not quite what you'd want for a robust wireless system.
This deficiency led to the development of 802.1x - an authentication protocol for ethernet (wired or wireless). It allows for a few different mechanisms for password comparison, several types of encryption (including key rotation plans, where necessary) and much other goodness. Unfortunately, this took a while to develop. Companies developing wireless products grew somewhat impatient and decided to start shipping an agreed-upon subset of 802.1x's capabilities. This is now known as WPA - basically 802.1x, but missing a few authentication mechanisms and lacking heavy crypto for packet encryption (like AES, for example). Upcoming wireless products will (eventually) support WPA2, which is basically full-blown 802.1x.
Today's WPA offers both a shared secret and support for real user authentication, usually through a RADIUS server on the backend. While packet encryption options are a bit limited, it does offer extended key lengths over plain ol' WEP, and provides a key rotation procedure (called TKIP) to avoid weaknesses inherent in both WEP's crypto and its implementation. It's generally considered to be a good enough solution for now, and should last until well after WPA2 support starts appearing in commercial products.
Like WEP, WPA requires hardware support to help with the packet encryption. Unfortunately, that means only newer 802.11[abg] equipment will work with WPA - older gear won't work, for a variety of reasons (key length, key rotation schedules, encryption types, etc.) 802.11g gear is likely to be a safer bet, although some of the very first 802.11g equipment predates WPA support.
The Atheos 802.11abg NIC (using the "madwifi" driver) in my IBM ThinkPad X40 works just fine with WPA.
Naturally, WPA support must be present on both the NIC (wireless adapter) and on the access point. As this page is solely focused on the client drivers, I'll assume whoever operates your favorite access points (you, perhaps) already knows what he or she is doing.
Obviously, you'll need a Linux driver for your WPA-enabled wireless card that supports the WPA features. I use the madwifi drivers for my Altheos 802.11[abg] card, but that's just me. You'll also need a recent Linux kernel, with a fairly recent wireless ethernet API. As of this writing, I'm using 2.6.13, so anything around that vintage (or newer) should work.
You'll also need a supplicant - a daemon program that authenticates your
ethernet (wired or wireless) connection. The supplicant will set up all
aspects of an authentication connection, and convince the authenticator
on the network that your network port is valid. Since this occurs at the
ethernet layer, you will probably need to DHCP after authenticating (unless
your network uses static IP addressing) - but any standard DHCP client
(pump or dhclient, for example) will work at that
point.
Like most things in the open-source world, there are two different packages to choose from for a supplicant: wpa_supplicant and open1x.
2.3.1wpa_supplicant
wpa_supplicant started life as a WPA layer for open1x's
xsupplicant. It's since evolved into its own 802.1x-compatible
supplicant, and no longer needs (in fact, no longer even supports) open1x.
wpa_supplicant supports nearly every WPA and WPA2 (and 802.1x)
authentication mode, and is the supplicant described in the text below.
xsupplicant
Open1x is still maintained, and now includes proper WPA support (now that
it is independent from wpa_supplicant). The open1x developers
have made some progress toward a GUI to manage the supplicant, but open1x's
xsupplicant supposedly supports fewer authentication modes than
wpa_supplicant.
If you're using Debian, congratulations. The good news is,
wpa_supplicant is already in Debian's package repository.
The bad news is, you may need to get it from Debian unstable (aka "sid").
It's not in the sarge release, but will likely be in the upcoming etch
release.
If you're not using Debian, well, good luck. :-)
apt-get install wpasupplicant
Make sure /etc/init.d/wpasupplicant starts at boot-time. As
I write this, 0.4.4 is the current version. Earlier versions of the
wpasupplicant package will have problems (with madwifi cards, at least).
/etc/wpa_supplicant.conf
wpa_supplicant uses a single config file to store descriptions
of all wireless networks, along with (optionally) the credentials used to
access each. Wireless networks are listed in order of increasing priority;
SSIDs near the bottom of the file are preferred to those listed near the
top. As an example, let's consider the following config file:
# Minimal /etc/wpa_supplicant.conf to associate with open
# access points. Please see
# /usr/share/doc/wpasupplicant/wpa_supplicant.conf.gz for more complete
# configuration parameters.
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=20
#ap_scan=1
#eapol_version=2
#fast_reauth=1
### Associate with any open access point
### Scans/ESSID changes can be done with wpa_cli
network={
ssid=""
key_mgmt=NONE
}
network={
ssid="PAL2.0"
scan_ssid=1
key_mgmt=WPA-EAP
eap=PEAP
identity="someguy"
password="somepass"
ca_cert="/etc/ssl/certs/ca-certificates.crt"
}
Ignoring the comment lines, here's what everything means.
ctrl_interface=/var/run/wpa_supplicant ctrl_interface_group=dialout
wpa_supplicant uses a named pipe to communicate with a text-based
client interface, wpa_cli. wpa_cli can be used to
select networks, to provide authentication credentials (if they aren't already
in the config file), and to force the supplicant to jump through a variety of
hoops. The above two lines indicate that the pipe will be named
/var/run/wpa_supplicant, and that it will be owned by group
"dialout". The group ownership is merely personal preference
on my part - the supplicant runs as root, so any group can be used for the
pipe.
#ap_scan=1 #eapol_version=2
These are a few useful global options. These just restate default settings, but are worth mentioning.
Modern access points (like those my employer has deployed) are able to
broadcast more than one network ID (SSID), and potentially respond to
several more. To find
these alternate SSIDs, the supplicant must poll access points.
ap_scan=1 turns on this capability, and indicates that
wpa_supplicant (not the driver) should handle AP scanning.
eapol_version indicates which version of the polling protocol
should be used. Version 2 exists (and is defined in the 802.1x spec), but
not many access points support it yet - hence using version 1.
If you operate in an environment with many hidden SSIDs, you'll probably want
to set ap_scan=2. With that, when a new access point is detected
the supplicant will iterate through every network defined in the config file
to see if a proper network connection can be made (rather than just relying
on broadcasted SSIDs).
#fast_reauth=1
Reauthenticate quickly, when asked. The default is to enable this, but it's a useful tweakable parameter (which is why I'm mentioning it here).
network={
ssid=""
key_mgmt=NONE
}
This stanza defines a network without an SSID. Without an SSID, this will
bond to any open broadcast network. Without a key_mgmt scheme,
no authentication will be attempted. Since this is the first network defined
in the config, any other networks will take priority over this one.
network={
ssid="PAL2.0"
scan_ssid=1
key_mgmt=WPA-EAP
eap=PEAP
identity="someguy"
password="somepass"
ca_cert="/etc/ssl/certs/ca-certificates.crt"
}
This defines a network requiring authentication. Obviously, this network
is named "PAL2.0", and requires WPA-EAP to
set up the authentication connection. Credentials are exchanged using the
PEAP method (one of several options with WPA-EAP).
WPA-EAP uses an X509 certificate to protect the authentication
session. This certificate should be verified by the supplicant -
otherwise you may be sending your credentials to any network with a matching
SSID. Not good. That's why you point ca_cert to Debian's
CA certificate file.
The scan_ssid=1 line indicates that local access points will
probably not broadcast this network by default - that access points must be
polled to see if they support this SSID.
Note that both the username and password to be used for this network are
stored, in the clear, in the config file. If you'd rather not do this, you
can omit one or both of these. You can then use wpa_cli to
add an identity and password on a per-network basis at runtime, so they
will only be cached in the supplicant daemon. Obviously, authentication
won't work until you do this, but it does avoid having cleartext credentials
in the config file.
/etc/network/interfaces
With the latest wpasupplicant packages, Debian controls daemon
command-line options through options in your
/etc/network/interfaces file.
My interfaces file currently has a stanza like this:
# Wireless interface #auto ath0 iface ath0 inet dhcp wpa-driver madwifi wpa-conf /etc/wpa_supplicant.conf
Most of this is self-explanatory. Note that ath0 is the
network device for my madwifi-powered 802.11 NIC. If you need to change
the driver, do so with a different wpa-driver option.
There are a variety of extra options that are supported here. For more
info, consult /usr/share/doc/wpasupplicant/README.Debian.gz.
With your supplicant running, you should be able to ifup
<iface> and watch your NIC authenticate. Add an
auto ath0 line to your /etc/network/interfaces
to automatically bring up ath0 (or whatever your NIC is called)
at boot - though that's probably more trouble than it's worth.
At this point you should familiarize yourself with wpa_cli.
Start it with no arguments, while wpa_supplicant is running, to
get an interactive prompt. A few useful commands:
help | Prints a command summary |
|---|---|
scan | Starts a scan for new SSIDs/networks |
scan_results | Lists the SSIDs wpa_supplicant can currently find |
list_networks | Lists networks defined in your config, and the number wpa_supplicant will use to refer to them |
select_network <num> | Select a particular network to use. Useful if wpa_supplicant isn't authenticating to the network you want in a busy environment |
terminate | Causes wpa_supplicant (not wpa_cli) to quit |
quit | Causes wpa_cli to exit |
I've already run into a few frequent hangups with wpa_supplicant,
and WPA support in general. If you have problems, and solutions, please let
me know and I'll add them to the list below.
wpa_supplicant isn't locking on to my network
If you have several networks defined - especially if one of them is an open
broadcast network (no SSID specified) - or if the SSID you're looking for
isn't the default broadcast SSID of a nearby access point,
wpa_supplicant may not lock onto the network you want. Fire up
wpa_cli, use the list_networks command to find the
internal number of the network you want, and use the select_network
command to choose that network (and disable all others). Then be patient
while wpa_supplicant find the network you want and authenticates.
To hasten that along, use the scan command to start another SSID
scan.
Don't forget that you've selected one network when you later try to use a
different net. You'll probably need to select another network, or use
the enable_network command if you move to a different wireless
coverage area.
wpa_supplicant authenticated to the right network, but I have the wrong IP
If wpa_cli status indicates you've authenticated, and
wpa_cli list_networks shows you're using the network you think
you should be using, but you've got the wrong IP, then you probably just need
to re-DHCP.
wpa_supplicant may not scan or authenticate correctly until
the wireless NIC is up (note: I'm referring to the interface being active - it
may not yet have an IP address). If you just started DHCPing on that interface,
it's possible that DHCP picked up an IP address from a network you weren't
intending before wpa_supplicant found and authenticated the correct
network. DHCP will keep its erroneous IP until the lease timeout expires, so
you'll probably want to re-DHCP.
If this keeps happening (which is likely if the network you want isn't the
default broadcast IP on nearby access points) you may want to use the
select_network command in wpa_cli to disallow all
other networks while you DHCP.
wpa_supplicant's
scan doesn't pick up any new access points
This is most likely a minor driver problem. WPA support for Linux is fairly
new, as is suspend-to-disk, so this may happen occaisionally. Remove the
driver module for your wireless NIC and reload it (e.g., rmmod
ath_pci, modprobe ath_pci). That usually clears things
up for me, though your mileage may vary.
If that doesn't work, check wpa_cli list_networks to make sure
you haven't inadvertently disabled all the networks that exist at your
present location. Frequent use of select_network can cause some
confusion.