Professional Documents
Culture Documents
Enterprise - Part 2
Equipment and Software Setup
Before we get into the nitty gritty of getting your own CA, public and private keys set up, here's the run down on the
equipment and software I'll be using and the typeface conventions I'll be following for the code listings.
When we're talking about setting up an industrial strength security implememtation, Linux is the natural choice. I've tried to
make this How To as general as I can, but you'll have to be aware of the little distro-to-distro differences. So I've included
my setup in Table 1.
My Setup
Distribution
Kernel
OpenSSL Version
FreeRADIUS Version
Wireless Router/AP
Slackware 10.2
2.6.21 Series (Custom Compiled)
0.9.8g
1.1.7
D-Link DGL-4300
I'm going to compile everything from source which will work on every distro. But I recommend you use your distro's
package management software such as APT, or portage, if you are familiar with using it (it will make the installation that
much easier).
It is very important that you use at least version 0.9.8g of OpenSSL, which was released just a few weeks before this
How To was published. You'll need this version or higher because some of the options we need to use didn't appear until
the 0.9.8g release.
Typeface Conventions
To make it easier to follow and copy/paste, I am going to provide copies of the actual shell commands that I used and their
output. They'll appear in blocks like this:
Code Goes in Here...
Everything you enter will appear in boldface. The output from the command will be in normal formatting.
~ $ openssl version
OpenSSL 0.9.8e 23 Feb 2007
Any parameters (such as filenames, passwords, etc.) that you'll need to adjust for your setup will be in bold-italic.
~ $ openssl sha1 myfile.txt
SHA1(myfile.txt)= da39a3ee5e6b4b0d3255bfef95601890afd80709
Ocassionally, I'll break up long commands onto multiple lines by "escaping" the newline at the end of the command. This
is done by typing a backslash (\), hitting return and continuing the command.
~ $ somecommand -that -has -a -million \
-options -and -you -have -to \
-use -them -all -on myfile.txt
For my bash shell I've set PS1 like this:
bash-3.1$ export PS1="\w \$ "
~ $
Some commands will require super-user privileges, so elevate yourself to super-users status by using:
~ $ su
Note: Ubuntu is slightly different here, you'll need to enter "sudo su", then, when prompted, enter your user
password and you'll have a root shell.
We're going to be digging into some pretty monstrous config files in a moment, so I'll print line numbers at the beginning of
the line and highlight what I've changed/added in bold-italic.
2123
post-proxy {
2124
2125
2126
2127
section, above.
2128
post_proxy_log
attr_rewrite
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
attr_filter
#
#
#
#
#
#
#
#
#
#
#
Setting up OpenSSL
The first step in getting the razor-wire set up around your wireless AP is to generate your very own CA (Certificate
Authority).
First, download the latest version of OpenSSL. As noted earlier, this is 0.9.8g as I write this.
~ $ wget http://www.openssl.org/source/openssl-0.9.8g.tar.gz
It's always good practice to verify the checksum of any source download (especially with security related software). For
some odd reason OpenSSL doesn't list a properly formatted md5 checksum file, so you'll have to eye-ball it.
~ $ cat openssl-0.9.8g.tar.gz.md5
acf70a16359bf3658bdfb74bda1c4419
~ $ md5sum openssl-0.9.8g.tar.gz
acf70a16359bf3658bdfb74bda1c4419 openssl-0.9.8g.tar.gz
Next, extract OpenSSL from the tarball.
~ $ tar xvzf openssl-0.9.8g.tar.gz
Move into the newly extracted OpenSSL directory and run the config script.
~ $ cd openssl-0.9.8g
~/openssl-0.9.8g $ ./config
Finally, compile and install OpenSSL.
~/openssl-0.9.8g $ make
...
~/openssl-0.9.8g $ su -c "make install"
Password: pA55w0Rd
...
Ok, now that we've got OpenSSL installed, we need to set up a few directories to organize the keys we're about to create.
Depending on where you look and who you ask, there are numerous ways to do this. I'm a fan of the KISS approach, so
here is how I set it up.
Change back into your home directory and create a "CA" directory with a "signed_certs" sub directory and a "private" sub
directory.
~/openssl-0.9.8g $ cd
~ $ mkdir CA
~ $ mkdir CA/signed_certs
~ $ mkdir CA/private
~ $ chmod 700 CA/private
"signed_certs" will hold copies of all the certificates that we sign with our CA. That way, if we need to revoke a certificate,
we'll have a copy locally. "private" will hold the CA's private key. It's very important to keep the CA key secret. Because if it
gets compromised, it could be used to sign untrusted certificates that might be used to trick clients into unknowingly
sharing sensitive information with a untrusted machine. I've locked it down above, by changing the permissions so that
only I can read, write and execute it.
There are quite a few command line options and even more infomation required in prompts that are pretty redundant. So
it's easiest to create a local copy of the OpenSSL config, modify it and force OpenSSL to use it with the "-config" option.
(Note: the location of the original openssl.cnf file may be different if you didn't build from source.)
~ $ cp /etc/ssl/openssl.cnf /home/brandon/CA/
Open up openssl.cnf with your favorite text editor and change the following in the "CA_default" section: (Remember that
the numbers that appear first on each line are line numbers, don't enter them into the config file.)
35
36
37
[ CA_default ]
dir
= /home/brandon/CA
38
certs
= $dir/
39
crl_dir
= $dir/crl
40
database
= $dir/index.txt
41
#unique_subject = no
42
43
new_certs_dir
= $dir/signed_certs
45
certificate
= $dir/cacert.pem
# The CA certificate
46
serial
= $dir/serial
47
crlnumber
= $dir/crlnumber
44
48
49
crl
= $dir/crl.pem
50
private_key
51
RANDFILE
= $dir/private/.rand
52
53
x509_extensions = usr_cert
If you're planning on using Windows to manage the wireless network on the clients, we need to add some additional
extensions to the end of the config file. Add the following sections to the end of "openssl.cnf" (this happens to be line 316
for me):
316
317
[ xpclient_ext ]
318
extendedKeyUsage=1.3.6.1.5.5.7.3.2
319
[ xpserver_ext ]
320
extendedKeyUsage=1.3.6.1.5.5.7.3.1
Next, head on down to line 123 and change the defaults for the "distinguished name" to suit your application. The
"distinguished name" section contains little bits of useful information for labeling public keys. As we'll see in a moment, the
keys themselves are pretty ugly (even when encoded in ASCII). To help keep track of them, they're labeled with some
information, and at this point the public key is referred to as a certificate. I'll use certificate to stay consistent with how
OpenSSL refers to them, but functionally they're equivalent.
123
[ req_distinguished_name ]
124
countryName
125
126
127
...
countryName_default
countryName_min
countryName_max
= US
= 2
= 2
You can set a default value for any of the parameters listed here by adding "_default" to the end of the variable name. In
the example above, "countryName_default" is the default value for "countryName".Finally, touch "index.txt", a simple textbased database used to track signed certificates.
~/CA $ touch index.txt
f2:c8:4a:d0:f5:09:28:b7
Validity
Not Before: Oct 24 03:17:49 2007 GMT
Not After : Oct 23 03:17:49 2008 GMT
Subject:
countryName
= US
stateOrProvinceName
organizationName
= SmallNetBuilder
organizationalUnitName
= Security Division
commonName
= CA
emailAddress
= you@example.com
X509v3 extensions:
X509v3 Subject Key Identifier:
D0:1E:BF:7B:A8:26:B9:98:B0:81:98:2E:E7:96:CA:57:3D:76:F3:02
X509v3 Authority Key Identifier:
keyid:D0:1E:BF:7B:A8:26:B9:98:B0:81:98:2E:E7:96:CA:57:3D:76:F3:02
DirName:/C=US/ST=The Great State You Live In/O ...
serial:F2:C8:4A:D0:F5:09:28:B7
X509v3 Basic Constraints:
CA:TRUE
Certificate is to be certified until Oct 23 03:17:49 2008 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
(Note that the DirName: line above was truncated [...] because it was too wide for most browser screens!)
In the command above, "-create_serial" (new in recent versions of OpenSSL) creates a hex serial number for this key. "extensions" specifies the section of the openssl.cnf config file to look in for specific extensions to append to the newly
created certificate (public key). In this case, we're using the v3_ca section which, among other things, contains this setting
on line 234:
basicConstraints = CA:true
This allows the key to be used to sign other keys, acting as the CA.
The last step is to create a copy of the CA certificate encoded in the DER format, because Windows likes only binary
encoded certificates.
~/CA $ openssl x509 -inform PEM -outform DER -in cacert.pem -out cacert.der
= US
stateOrProvinceName
organizationName
= SmallNetBuilder
organizationalUnitName
= Security Division
commonName
= server
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
71:A0:FB:1C:35:B7:B8:1D:1C:A4:C6:DF:A5:BA:80:6E:89:09:B7:CE
X509v3 Authority Key Identifier:
keyid:D0:1E:BF:7B:A8:26:B9:98:B0:81:98:2E:E7:96:CA:57:3D:76:F3:02
Note: If you're planning on using Windows to manage the wireless connection on the clients use the X509v3 extensions
we added earlier instead:
~/CA $ openssl ca -config ./openssl.cnf -extensions xpserver_ext \
-in server_req.pem -out server_cert.pem
Create key pairs for your clients using the exact same command. Just change the key filenames and the "Common
Name" to something meaningful for your application. Here's what I used for this set up:
~/CA $ openssl req -new -config ./openssl.cnf -keyout linux_laptop_key.pem \
-out linux_laptop_req.pem
...
Common Name (eg, YOUR name) []: linux_laptop
And:
~/CA $ openssl req -new -config ./openssl.cnf -keyout winxp_laptop_key.pem \
-out winxp_laptop_req.pem
...
Common Name (eg, YOUR name) []: winxp_laptop
Sign both certificate requests the same way we signed the server's certificate. Here's the command for my Linux laptop
key:
~/CA $ openssl ca -config ./openssl.cnf -in linux_laptop_req.pem \
-out linux_laptop_cert.pem
Again, use the X509v3 extensions if Windows is managing wireless on the clients:
~/CA $ openssl ca -config ./openssl.cnf -extensions xpclient_ext \
-in winxp_laptop_req.pem -out winxp_laptop_cert.pem
Now we've got both pairs of keys created and signed. Windows needs a little help to understand all this security, so we
have to package the client certificate coresponding private key into a PKCS#12 file. Linux is happy working with them
either way, so we'll package them both for consistency.
~/CA $ openssl pkcs12 -export -clcerts -in winxp_laptop_cert.pem \
-inkey winxp_laptop_key.pem -out winxp_laptop.p12
Enter pass phrase for winxp_laptop_key.pem: pA55w0rD
Enter Export Password: pA55w0rD
Verifying - Enter Export Password: pA55w0rD
The command above uses OpenSSL's pkcs12 utility to "-export" a new PKCS#12 file. "-clcerts" tells OpenSSL to only
export the client certificate and private key (in other configurations, multiple certificates and keys can be packaged into a
single PKCS#12 file). Package the Linux certificate and private key using the same command. Generating good keys
relies on having a good set of "random" data to seed the key generation. While not strictly related to generating PKI keys,
we'll need this data later on for FreeRAIDUS. We'll use OpenSSL to generate Diffie-Hellman parameters for symmetric
key generation.
First, elevate yourself to superuser and create a directory that will house the CA certificate, server public and private keys,
a dh file for Diffie-Hellman parameters and a random date file. I chose to put these in /etc/wireless; anywhere readable to
FreeRADIUS is fine.
~/CA $ su
Password: pA55w0rD
/home/brandon/CA # mkdir /etc/wireless
Now, copy the server's public and private key and the CA's certificate to /etc/wireless:
/home/brandon/CA # cp cacert.pem server_cert.pem server_key.pem /etc/wireless/
prefix = /usr/local
24
25
26
27
28
29
30
31
32
33
exec_prefix = ${prefix}
sysconfdir = ${prefix}/etc
localstatedir = ${prefix}/var
sbindir = ${exec_prefix}/sbin
logdir = ${localstatedir}/log/radius
raddbdir = ${sysconfdir}/raddb
radacctdir = ${logdir}/radacct
# Location of config and logfiles.
confdir = ${raddbdir}
34
35
36
37
38
39
40
run_dir = ${localstatedir}/run/radiusd
#
# The logging messages for the server are appended to the
# tail of this file.
#
log_file = ${logdir}/radius.log
The location of the log file on line 40 is especially important. FreeRADIUS usually isn't very informative about runtime
errors, instead writing everything the log. So if you have any problems with FreeRADIUS, take a look at the log.The rest of
this config file is huge2149 lines huge. The good news is we don't need 90% of the options FreeRADIUS has for WPA2.
So we can distill the whole config file down to around 200 lines.
You can safely comment out (or delete) just about anything that doesn't have to do with TLS or EAP (such as the module
sections dealing with PEAP, CHAP, MSCHAP, etc.). Instead of walking you through every change, here is a copy of what I
use (this is likely more than the absolute minimum even with all the comments removed).
One big change that needs to be made is changing to an unprivileged user and group on lines 109 and 110:
109
110
user = nobody
group = nobody
Next, open up clients.conf and add a section for your router. The router is the only true "client" to the RADIUS server; the
computers that connect are called users. Use the IP address of your router and a strong secret (this is the "password" that
the router will use to talk to the RADIUS server).The "shortname" variable is used only for logging, so it can be whatever
makes the most sense for you. Unless your NAS (Network Access Server) type is explicitly listed above in the clients.conf
file, use "other" for the NAS type.
client 10.20.7.1 {
secret
shortname
nastype
}
=
=
=
smallnetbuilder
wireless_ap
other
Next, edit the users file. Add the default line and lines for each of the client keys we created using the common name
supplied for the key as the user name. Have some fun with the default rejection message.
# users file for FreeRADIUS
winxp_laptop
linux_laptop
DEFAULT
Auth-type := EAP
Auth-type := EAP
Auth-type := Reject
Reply-Message := "Your Computer Ain't Welcome Here!"
Now we'll need to edit eap.conf. Change default_eap_type to TLS on line 23: default_eap_type = tls
Adjust the TLS configuration to suit your set up:
123
tls {
124
private_key_password = pA55w0rD
125
private_key_file = /etc/wireless/server_key.pem
126
127
128
129
130
name.
131
certificate_file = /etc/wireless/server_cert.pem
132
133
134
CA_file = /etc/wireless/cacert.pem
135
136
137
138
139
140
141
142
143
dh_file = /etc/wireless/dh
144
random_file = /etc/wireless/random
The "identity" field should match the common name on the client certificate and the user we set up in FreeRADIUS' users
file. Restart wpa_supplicant and connect to the network.
Enter the password for the client's private key. (You can optionally require that the password is entered everytime the key
is used, this gets annoying real quick, so I usually leave that unchecked.)
Troubleshooting
There are quite a few pieces that have to play nicely together to get WPA2-Enterprise working. Here are a few tools that
come in handy if things don't work smoothly on the first try:
Conclusion
With a little extra hardware, you can add the extra level of security that authentication provides to your wireless network.
This gives you better control over the clients that can connect to your network and also helps to keep clients from
connecting to untrusted networks. The combination of AES Encryption in WPA2 and secure authentication of clients will
help protect your network and keep your data secured from prying eyes.