Wireless Lan with 802.1x

Share wlan with a single mac80211 capable nic and networkmanager

In this example we used wlan0 with networkmanager to connect to an upstream wlan service. We created a wlan1 with bridge ext0 interface to host a copy for clients.

Networkmanager needs to be told to ignore interfaces used to provide the accesspoint, otherwise they may be used as secondary station interfaces. Insert to /etc/NetworkManager/NetworkManager.conf to do that. I also removed references to ifupdown

[keyfile]
unmanaged-devices=interface-name:ext0;interface-name:wlan1;interface-name:mon.wlan1

Hostapd has to be told to use the same radio channel as the upstream service, so it was useful to script this to make it easy to roam between upstreams.

We added a small delay to limit the rate at which our AP stomps on traffic from our station side, since by necessity it is all on the same channel. This has the tendency to prioritise the ap-station's own traffic over its own clients.

D-Bus can be used to dump stations from wpa-supplicant without upsetting networkmanager.

Also the accesspoint interface needed to have a different mac mainly to satisfy networkmanager, though some code in certain linux kernel releases may also complain unnecesarily. We would rather not do that, as the one MAC address that properly belongs to this NIC is the one in ROM.

iface wlan1 inet manual
#       pre-up /sbin/iw phy phy0 interface add wlan1 type __ap
        pre-up /sbin/iw phy phy0 interface add wlan1 type managed
        pre-up ifconfig wlan1 hw ether $(eval `cat /sys/class/ieee80211/phy0/macaddress | sed -s "s/^/printf \"%02x%s\" \\$(( 2^0x/;s/:/)) :/;"`)
        pre-up iwconfig wlan1 retry 16 power on txpower auto
        pre-up sed -si "s/^channel=.*$/channel="`iwgetid -r --channel`"/" /etc/hostapd/hostapd.conf
        pre-up sleep 1
        post-down /sbin/iw dev wlan1 del
        hostapd /etc/hostapd/hostapd.conf

iface ext0 inet static
#       pre-up sysctl net.ipv6.conf.default.forwarding=1
        pre-up sleep 1
        up tc qdisc add dev ext0 root netem delay 250ms
        address 192.168.1.1
        bridge_ports wlan1
        bridge_stp off
        bridge_ageing 0
        bridge_bridgeprio 34000
        bridge_fd 0
        #bridge_gcint 0
        bridge_hello 0
        bridge_maxage 0
        bridge_maxwait 0

IPtables NAT masquerade is then setup with wlan0 as the external interface and ext0 as the internal, with dhcp and possibly DNS service.

Epilogue

Recent editions of network manager allow the instantiation of interfaces in ad-hoc and AP mode, using functionality embedded in wpa_supplicant.

This did not have quite the same feature level as hostapd.

Other Implementatiions

TheCloud

UK free wlan operator www.thecloud.net used to have an Android application that enabled FastConnect, and gave an encrypted session between station and AP, a peek in settings revealed some details for creating a profile manually, on both Android and in Network Manager.

ESSID
_The Cloud X
EAP method
PEAP
Phase 2 authentication
PAP (MSCHAPv may also work)
Identitiy (when this was first seen, it was written MYCLOUD/)
mycloud/registered_e-mail
Anonymous Identitiy
Used the same as the Identity
Password
registered_password

OpenSSL

This program creates the certificates used by FreeRADIUS and other programs.

Add object identifiers to tell Windows XP clients what the certificates are for: cat /usr/share/doc/freeradius/examples/scripts/xpextensions >> /etc/ssl/openssl.cnf

Then alter the other options in openssl.conf, especially paths for certificates in CA_default and defaults for new certiciates in req_distinguished_name

First, you probably want a root certificate if you dont already have one. This is used to sign the other certificates, so clients only need to trust it, so that trust is implied for the other certificates. I used this script from the Jabber server. It asks for a password, but the password is taken off when it is requested again.

#!/bin/sh
## This generates the cert and key
## The key will be valid for 3650 days.
## Be sure to enter the FQDN of your Jabber
## server as the "Common Name".
# -x509 means make root selfsigned cert
#
openssl req -new -x509 -newkey rsa:1024 -days 3650 -keyout privkey.pem -out key.pem
## This will remove the passphrase
openssl rsa -in privkey.pem -out privkey.pem
## Put it all together
cat privkey.pem >> key.pem
## Cleanup
rm privkey.pem

I rename key.pem to root.pem and it goes in the /etc/ssl/certs/ directory. If other users on the system cannot be trusted, then the private key can be split off the certificate and kept in /etc/ssl/certs/private/ directory. Do remember to edit [ CA_default ] in /etc/ssl/openssl.conf to tell it where the root certificate is.

Now a server certificate for freeradius can be made, with a common root. Server certs for other SSL using things like imaps, https, jabber are made similarly.

## This generates the cert and key
## The key will be valid for 3650 days.
## Be sure to enter the FQDN of your Jabber
## server as the "Common Name".
# -x509 means make root selfsigned cert
#
openssl req -new -newkey rsa:1024 -days 3650 -keyout privkey.pem -out key.pem

## This will remove the passphrase
# if you bother keeping this ... it matches that specified in /etc/freeradius/eap.conf as "private_key_password ="
# however it also ask for a challenge which is what xsupplicant might ask about
openssl rsa -in privkey.pem -out privkey.pem

## Put it all together
cat privkey.pem >> key.pem

# You may need to create these files as so if this is the first cert.
#echo > /etc/ssl/index.txt
#echo 01 > /etc/ssl/serial

# -extensions read in from section in openssl.cnf
# -extensions xpclient_ext if generating for supplicant, -extensions xpserver_ext if generating for FreeRADIUS
# XP does not recognise Radius or choose its certificate otherwise.
#
openssl ca -extensions xpserver_ext -policy policy_anything -out signedkey.pem -infiles key.pem

cat privkey.pem >> signedkey.pem
rm privkey.pem
rm key.pem

-extensions xpserver_ext is only used when making the FreeRADIUS server certificate. It is needed for Windows XP clients to be able to use the access point.

Windows XP seems to like its certificates provided in p12 files though... In this case the passphrase has to be used to encrypt the private key, but windows lets the user remove it when this certificate/private-key is imported!

#!/bin/sh

openssl req -new -keyout newreq.pem -out newreq.pem -days 3650
openssl ca -extensions xpclient_ext -policy policy_anything -out newcert.pem -infiles newreq.pem
openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -out cert-clt.p12 -clcerts
openssl pkcs12 -in cert-clt.p12 -out cert-clt.pem

To complete the XP setup, the public portion of the root certificate is also imported to trust it, then Certificate authentication is set up in wireless lan settings, with My key is provided for me

Freeradius Setup

I have patched freeradius 1.5.0. We want EAP-TLS to be built.

I like to keep all my certificates together in OpenSSL, so in the tls section of eap.conf I write:

tls {
# password is not needed if the certificate does not have one
# private_key_password = cats
private_key_file = /etc/ssl/certs/radius.pem
certificate_file = /etc/ssl/certs/radius.pem
CA_file = /etc/ssl/certs/root.pem
# CA_path = /etc/ssl/certs/
dh_file = /dev/urandom
random_file = /dev/urandom
fragment_size = 1024
# include_length = yes
# check_crl = yes
check_cert_cn = %{User-Name}
}

Freeradius with SQL

Firstly it’s needed to give Freeradius access to an SQL database. I’m using MySQL, so to do that do like:

create database freerad;
GRANT ALL ON freerad.* TO freerad@localhost IDENTIFIED BY 'password';
use freerad;
\. /usr/share/freeradius-dialupadmin/sql/userinfo.sql
\. /usr/share/freeradius-dialupadmin/sql/badusers.sql
\. /usr/share/freeradius-dialupadmin/sql/totacct.sql
\. /usr/share/freeradius-dialupadmin/sql/mtotacct.sql
-- import the following, though it's needed to gunzip db_mysql.sql.gz and uncomment all the tables in that.
\. /usr/share/doc/freeradius/examples/db_mysql.sql.gz

The dbms login details, i.e. server, database, username, password are also specified in the /etc/freeradius/sql.conf file. Also, for security, I activate the default profile features, so usernames that are not authorised are rejected, rather than default accepting them.

default_user_profile = "DEFAULT"
query_on_not_found = yes

Add a 802.1x user (I use EAP) to a Freeradius SQL Database.

It can be tested by trying to auth the user User's Laptop. DELETE FROM radcheck; should result in the auth attempt being rejected instead. The =27 is a mime HEX-escape for a ', and they are only used to check the UserName column. Thereafter the PHP dialupadmin provided with freeradius can be used to admin which usernames are authorised to connect via 802.1x

-- Here is the first SQL that I had FreeRADIUS accepting iff a given username is mentioned in the table

DELETE FROM radcheck;
DELETE FROM radreply;
DELETE FROM usergroup;
DELETE FROM radgroupcheck;
DELETE FROM radgroupreply;

INSERT INTO radcheck (UserName, Attribute, op, Value) VALUES
        ('User=27s Laptop', 'User-Name', '==', 'User''s Laptop'),
        ('User=27s Laptop', 'Auth-Type', ':=', 'EAP');

INSERT INTO radreply (UserName, Attribute, op, Value) VALUES
        ('User=27s Laptop', 'Reply-Message', '=', 'Welcome user %u on the laptop');

INSERT INTO usergroup (UserName, GroupName) VALUES
        ('DEFAULT', 'DEFAULT');

INSERT INTO radgroupcheck (GroupName, Attribute, op, Value) VALUES
        ('DEFAULT', 'User-Name', '!=', 'DEFAULT'),
        ('DEFAULT', 'Auth-Type', ':=', 'Reject');

INSERT INTO radgroupreply (GroupName, Attribute, op, Value) VALUES
        ('DEFAULT', 'Reply-Message', '=', 'You have no account!');

Some more openssl commands

openssl x509 -inform PEM -in root.pem -outform DER -out /tmp/root.cer