This is a quick guide on setting up certificate-based wireless 802.1x authentication on OpenWRT with FreeRADIUS and generating certificates on a desktop PC with OpenSSL Demo CA, using decent cryptographic configuration : strong curves & strong cipher suite list.
This guide could easily be adapted to use EAP-TTLS+EAP-TLS which was my initial intent, but most of the client UIs (Android, iOS, Windows, NetworkManager, etc.) do not propose EAP-TLS authentication when chosing EAP-TTLS connection.
At the time of this writing, the current version of OpenWRT is 'Barrier Breaker/14.07' and will use this as a reference, future versions should require simliar configuration with minimal modifications.
- Initial OpenWRT configuration
Make sure you have all the OpenWRT's source repositories available in your /etc/opkg.conf
file.
src/gz barrier_breaker_base http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/base
src/gz barrier_breaker_luci http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/luci
src/gz barrier_breaker_packages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/packages
src/gz barrier_breaker_oldpackages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/oldpackages
dest root /
dest ram /tmp
lists_dir ext /var/opkg-lists
option overlay_root /overlay
And update your sources :
$ opkg update
Replace wpad-mini
with wpad
:
$ opkg remove wpad-mini
$ opkg install wpad
Update the installed OpenSSL version (this should be done regularly anyways):
$ opkg install openssl-util libopenssl
Install the FreeRADIUS packages.
$ opkg install freeradius2 freeradius2-common freeradius2-democerts freeradius2-mod-always freeradius2-mod-attr-filter freeradius2-mod-attr-rewrite freeradius2-mod-chap freeradius2-mod-detail freeradius2-mod-eap freeradius2-mod-eap-gtc freeradius2-mod-eap-md5 freeradius2-mod-eap-mschapv2 freeradius2-mod-eap-peap freeradius2-mod-eap-tls freeradius2-mod-eap-ttls freeradius2-mod-exec freeradius2-mod-expiration freeradius2-mod-expr freeradius2-mod-files freeradius2-mod-logintime
$ opkg install freeradius2-mod-mschap freeradius2-mod-pap freeradius2-mod-passwd freeradius2-mod-preprocess freeradius2-mod-radutmp freeradius2-mod-realm freeradius2-mod-sql freeradius2-mod-sql-pgsql freeradius2-mod-sql-sqlite freeradius2-mod-sqlcounter freeradius2-mod-sqllog freeradius2-utils
- Creating the EC CA
On your Desktop PC use your already-installed OpenSSL (if not, install it using your preferred distro's package manager).
This will create your root key, so make sure the directory you're working in is not world readable and the PC you're using is somewhat trustworthy.
You will need to chose a CN/Organization Name for your Root CA and for your subsequent certificates.
First, generate key curve parameters, as a curve reference for later OpenSSL commands:
$ openssl ecparam -out ecca.param -name secp384r1
Then generate your CA's EC Root key:
$ openssl req -nodes -newkey ec:ecca.param -days 3650 -x509 -sha256 -keyout ecca.key -out ecca.crt
Generate the server's own EC key:
$ openssl req -nodes -newkey ec:ecca.crt -days 3650 -sha256 -keyout serverec.key -out serverec.csr
Then, in order to use the OpenSSL Demo CA, you need to create the directory architecture for it and initialize the serial number to 01 for the first signed certificate :
$ mkdir ./demoCA/
$ mkdir ./demoCA/newcerts
$ touch ./demoCA/index.txt
$ echo 01 > ./demoCA/serial
Using OpenSSL's demo CA, sign your server's key with your Root CA key :
$ openssl ca -extensions v3_ca -days 3650 -out serverec.crt -in serverec.csr -cert ecca.crt -keyfile ecca.key
When the signing operation is complete, do verify your certificate's content using :
$ openssl x509 -in serverec.crt -text
You can also combine your Root CA key & self-signed certificate in a .pem
format, but it's not necessarily mandatory :
$ cat ecca.crt ecca.key > ecca.pem
The same goes for the server's key signed with the EC Root CA's key :
$ cat serverec.crt serverec.key > serverec.pem
- Configure FreeRADIUS on OpenWRT
First you will probably need to make sure the certificate directory exists.
$ mkdir /etc/freeradius/certs
Then SCP the necessary files over to your /etc/freeradius/certs
directory, namely the ca.crt
file and the server.pem
bundle file.
The configuration can now be modified, starting with the eap.conf
file :
eap {
...
default_eap_type = tls # Use EAP-TLS
...
tls {
...
private_key_password = # Empty since we did not specify one at creation in OpenSSL
private_key_file = ${certdir}/server.pem
certificate_file = ${certdir}/server.pem
CA_file = ${cadir}/ca.pem
dh_file = ${certdir}/dh2048.pem # Not really needed since we'll use ECDHE only
# Decent Cipher Suite List, taken from
# https://github.com/ouaibe/duraconf/blob/master/configs/nginx/nginx.COMPAT_MEDIUM_SECURITY.conf
cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA256:ECDHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;"
random_file = /dev/urandom # Be careful of not chosing a non-blocking random source
# This selects the strongest curve available
ecdh_curve = "secp384r1"
...
verify {
tmpdir = /tmp/radiusd # Used for caching
# Set the right command to verify client certificate.
client = "/usr/bin/openssl verify -CAfile /etc/freeradius2/certs/ca.pem %{TLS-Client-Cert-Filename}"
}
}
...
}
Then we will modify radiusd.conf
to add the right listening parameters :
listen {
type = auth
ipaddr = 127.0.0.1
port = 0
interface = lo
}
In order to configure the security between the AP and FreeRADIUS locally on the router, first generate a long password, it can be done on your desktop PC using the following command :
$ apg -a 1 -m 60 -x 60 -E \'\"\`
And use one of the chosen passwords in your clients.conf
file :
client localhost {
secret = <long_pw> # <-- Password goes here, without quotes
ipaddr = 127.0.0.1
require_message_authenticator = yes
nastype = other
}
Then you need to create the authenticator logic for this site, first of all create the localhost
site :
$ touch /etc/freeradius2/sites/localhost
And add the following configuration lines :
authorize {
preprocess
auth_log
eap {
ok = return
}
expiration
logintime
}
authenticate {
eap
}
preacct {
preprocess
suffix
files
}
session {
radutmp
}
post-auth {
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
Finally, edit the radiusd
startup script (/etc/init.d/radiusd), replace or comment out the line radiusd -i $IPADDR -p 1812,1813 $OPTIONS
with radiusd $OPTIONS
and add the following line :
mkdir -p /tmp/radiusd
** WARNING ** This is something you might need to re-do when updating the freeradius package on OpenWRT (since updates might replace the startup script with the original one).
- Configure OpenWRT in 802.1x
Edit the /etc/config/wireless
file, and chose the right authentication mode :
config wifi-iface
option device 'radio0'
option mode 'ap'
option network 'lan'
option ssid '<YOUR_SSID>'
option encryption 'wpa2+ccmp'
option auth_server '127.0.0.1' # <-- Same IP as clients.conf/radiusd.conf
option auth_secret '<long_pw>' # <-- Same long pw as clients.conf
Finally, you can test your config for mistakes/errors, manually starting radiusd
as follows :
$ radiusd -XX
Errors are usually pretty self-explanatory, but be ready to pop wireshark
if need be...
- Manage Client Certs.
Since we're still waiting for let's encrypt we'll have to manage clients certificates by hand using OpenSSL's bundled Demo CA (not production ready).
Don't forget to copy your self-signed ecca.crt
file to your different clients that need a client certificate to authenticate.
Create certificates for each client using the following OpenSSL Demo CA commands :
$ openssl req -nodes -newkey ec:ecca.crt -days 3650 -sha256 -keyout CLIENT.key -out CLIENT.csr
$ openssl ca -extensions v3_ca -days 3650 -out CLIENT.crt -in CLIENT.csr -cert ecca.crt -keyfile ecca.key
Sometimes (Android) you will need to bundle the client certificate in P12 format, use the following command to do so :
$ openssl pkcs12 -export -in CLIENT.crt -inkey CLIENT.key -out CLIENT.p12 -certfile ecca.crt
Sources / interesting notes : http://www.blog.10deam.com/2015/01/08/install-freeradius2-on-a-openwrt-router-for-eap-authentication/
http://blog.epijunkie.com/2013/12/freebsd-freeradius2-eap-tls-ssl-admin-a-wpa2-enterprise-guide/