Tuesday, September 6, 2011

Radius and 802.1X

Notes for FreeRadius configuration on OS X

If you are like me and you have various WiFi enabled devices at your home, then managing long pre-shared access keys for your network is challenging. If you change the key, then all of the devices can no longer connect. Access rules on your router might allow you to whitelist specific hardware MAC addresses and there might be a firewall application built into your home router. Easier device management and increased wireless security can be easily accomplished with an inexpensive computer running Linux or FreeBSD computer and a Netgear WNR3500U/L router. You can image the router via guides available on myopenrouter.com. Imaging the router with a Linux distribution will allow you to catapult its features into the enterprise space. For the purposes of what I am doing here, I needed Radius and WPA2 Enterprise support on the router.

My goal for this setup was to setup a root Certificate Authority, issue individual client device certificates, and then sign those certificates with my CA. A FreeRadius server is running on a spare Mac OS X 10.6 Imac. I have a WNR3500L/U running dd-wrt, w/ Radius and WPA2 Enterprise support. I will issue and sign certificates for a Nexus S 4G, a couple of MacBooks, and an iPad. FreeRadius is highly customizable and offers different methods of authentication. The WNR3500L/U is connected to the Radius authentication server using a Pre shared key over port 1812/1813. Ipfw works well to lock down source and destination addresses over port 1812. dd-wrt supports iptables. note: I am running the FreeRadius server on OS X 10.6 Desktop (not server). FreeRadius is configured for EAP-TLS authentication and the dd-wrt router (actually I'm running dd-wrt on two WNR3500L/Us chained together) is configured for WPA2 Enterprise w/ AES/TKIP. OpenSSL key and cert configuration details are below. I've left off the config for radiusd.conf. I suggest running FreeRadius server with the default config first and then locking it down to just the protocols you want/need. I also suggest setting your OpenSSL key gen preferences in openssl.cnf prior to running these commands; namely, turn up the key strength, and lock it down. Also, store your passphrases in a safe place after generating them (i.e. openssl rand -base 64 37 | shasum-5.12 -a 512 | cut -c1-32). Last of all, chmod -R 0400 your private keys and config files, and chown -R freeradius:freeradius appropriately. I've left off the output of the commands below for clarity. The common name must be unique between client certificates. Last, the iPhone configuration utility is needed for creating configuration profiles on OS X 10.7+ and iPad/iPhones. Here are the steps.

1. Generate a new self-signed root CA, write the encrypted private key to CA/private/cakey.pem, and then write the Base-64,ASN.1-encoded, self-signed certificate to CA/cacert.pem. This certificate will be used for signing client and server certificates.
# openssl req -new -x509 -extensions v3_ca -keyout CA/priv/cakey.pem \
  -out CA/cacert.pem -days 730 -config openssl.cnf 
# openssl x509 -in cacert.pem -noout -text 
# openssl x509 -in cacert.pem -noout -dates
# openssl x509 -in cacert.pem -noout -purpose
# openssl x509 -in cacert.pem -noout -issuer 
# openssl rsa -noout -modulus -in CA/priv/cakey.pem | openssl sha1
# openssl x509 -noout -modulus -in CA/cacert.pem | openssl sha1
Check the modulus and public exponent in the private key and certificate to make sure they match.
# openssl rsa -noout -modulus -in CA/priv/cakey.pem | openssl sha1
# openssl x509 -noout -modulus -in CA/cacert.pem | openssl sha1
2. Export the root CA signing certificate to ASN.1, DER encoded format so that clients can import it.
# openssl x509 -in CA/cacert.pem -outform DER -out clientCerts/myRootCA.der
2a. Convert the DER encoded CA back to pem format and place in a .crt file so that Android can read it. (This is an extra, un-needed step as cacert.pem can be copied and renamed to .crt). (Android does not understand pem files so write the DER encoded certificate to PEM format in a file with extension .crt).
# openssl x509 -inform der -in clientCerts/myRootCA.der -out clientCerts/myRootCA.crt
3. Generate radius server certificate (i.e. signing request) and private key in unencrypted format.
# openssl req -new -nodes -keyout tempCerts/radius_key.pem \
  -out tempCerts/radius_req.pem -days 730 -config openssl.cnf
4. Sign the radius server certificate. note: if you have any Microsoft clients, you'll need to create an xpextensions file and then add '-extensions xpserver_ext -extfile ./xpextensions' to the following command.
# openssl ca -out tempCerts/radius_cert.pem -infiles tempCerts/radius_req.pem \
  -config openssl.cnf
5. Install the root CA signing certificate, Radius server private key, and Radius server signed certificate.
# cp tempCerts/radius_cert.pem /etc/radwl/certs/server/
# cp tempCerts/radius_key.pem /etc/radwl/certs/server/
# cp CA/cacert.pem /etc/radwl/certs/server/
6. Create the client certificate (i.e. signing request) and private key. note: match the output file names with the client identity or common name.
# openssl req -new -keyout tempCerts/myandroid_key.pem \
  -out tempCerts/myandroid_req.pem -days 730 -config openssl.cnf
7. Sign the client certificate.
# openssl ca -out tempCerts/myandroid_cert.pem -infiles tempCerts/myandroid_req.pem \
  -config openssl.cnf
8. Export the signed client certificate and private key to pkcs #12 format
# openssl pkcs12 -export -in tempCerts/myandroid_cert.pem -inkey \
  tempCerts/myandroid_key.pem -out clientCerts/myandroid_cert.p12 -clcerts
9. Install the signed client certs on the Radius server.
# cp tempCerts/*_cert.pem /etc/radwl/certs/clients
10. Copy the client pkcs#12 certificate to appropriate device.
# cp clientCerts/myandroid_cert.p12 DEVICE
11. Copy the CA signing certificate to the same device.
# cp clientCerts/myRootCA.crt DEVICE
12. on OS X, use the following commands to add the freeradius user to the freeradius group. Also run chsh freeradius and set the shell to /sbin/nologin
# dscl . append /Groups/freeradius GroupMembership freeradius