WPA 2 Enterprise from scratch using a Raspberry Pi

Have you ever seen one of these username/password dialog boxes popping up when connecting to your university or work wireless network? This is commonly known as WPA2 Enterprise. Wouldn’t it be cool to have this at home, too? 🙂

Screenshot of the WPA2 Enterprise wireless login screen displayed on a MacThis blogpost will describe the steps required to setup such a system from scratch, using a Raspberry Pi (and of course a wireless router/access point). Why a Raspberry Pi? Simply because it uses a lot less power compared to a “normal” computer (compare that 5V, 1A phone charger to the 400+W power supply of your PC), meaning you should get less of a shock when you get that regular letter from your electricity supplier. Having said that, this tutorial should work for most Linux machines, there isn’t anything ARM specific here.

WARNING: This article discusses network security topics. Please do not apply this to a production environment unless you fully understand what’s going on, have read up on the topics elsewhere and are willing to take responsibility for it. I’ll try to discuss and/or point out security-related issues I’m aware of, but if something goes wrong and somebody hacks into your network, you have been warned.

Brief introduction to 802.1X, RADIUS & EAP.

I’ll try to explain how all these things fit together in a simple way. It may not be 100% correct everywhere, but it should give you an understanding of what’s going on. If you need to know more (which I thoroughly recommend if you’re thinking about deploying this in a production environment, such as at work!), there is plenty of literature available.

Diagram showing protocols involved in wired 802.1X authentication
Diagram showing protocols involved in wired 802.1X authentication, by Arran Cudbard-Bell, from Wikipedia. For the purpose of this blogpost the Supplicant will be a wireless device and the authenticator will be your wireless access point or router.

The basic idea is that you associate with your wireless network first (click on the wireless network name in your wireless utility), but that you need to be authenticated (you type in your username/password) before you are authorized to access the network (and browse the web). To make this work, you need three systems – a wireless laptop/smartphone/etc (the supplicant), an authenticator (a wireless access point (AP) or router) and a server that stores your credentials (the Raspberry Pi).

Now you somehow need to tell the authentication server who you are and what your password is, before you are actually allowed to send traffic on the network, and without broadcasting your username and password in clear text on the wireless network for everyone to see. The solution to this is that the authenticator will only forward 802.1X traffic to the authentication server until you’ve been authorized, and ideally you encrypt this traffic to prevent anyone from sniffing your username and password.

As you can see from the diagram above, the Extensible Authentication Protocol (EAP) is used for communicating all the way from the user’s laptop to the authentication server (it transports your username and password), whereas RADIUS is only used between the authenticator and the authentication server. 802.1X defines how EAP is used over ethernet and wireless networks. RADIUS also supports sending “accounting” data, such as telling a server how much you’ve been downloading.

What you’ll need

  • A Raspberry Pi – or another computer running some flavour of Linux. There exist RADIUS servers that run on Windows as well, but you’ll need to look elsewhere for tutorials on those.
  • A nice access point (AP) or wireless router, i.e. one that supports RADIUS and 802.1X.
  • Some Ethernet cables maybe
  • A wireless laptop/phone/iPod or some other device that supports WPA2 enterprise. The PS3 unfortunately doesn’t ;).
  • Some understanding of Linux and networking.

I’m assuming that you’ll be using a Raspberry Pi for this, running Arch Linux (it should be pretty similar on Debian though, except you’ll need to use apt-get to download the packages, which might have slightly different names). I’ll be using a Cisco 871W router (which has now been End-of-Life’d 🙁 ), though the tutorial should work on “similar-ish” Cisco devices running IOS (I recommend checking before buying). I’ve also tested this on a D-Link DIR-615.

Picture showing the DIR-615, C871 and Raspberry Pi
Test equipment: the DIR-615, C871 and Raspberry Pi

Step-by-step guide

I’ll guide you through setting up the various components one by one in an incremental way, testing the setup as we go along: first, we’ll setup FreeRADIUS with “hardcoded” user & cleartext password, then the wireless network. Once that works, we’ll configure a MySQL database for storing usernames, passwords and accounting data, setup the DaloRADIUS  web-GUI and point FreeRADIUS to the database. I’ll finish off with discussing some further points about security, give some debugging tips and point you to some further information (so feel free to scroll to the end if you get stuck!).

Many of the files and folders in the FreeRADIUS installation directory are owned by root and cannot be cd’ed or viewed by non-root users (this has good reasons). Normally I would recommend running as much as possible under a non-privileged user and using sudo only where necessary, but you’ll probably find yourself needing to do a lot as root, so switching to root may be convenient. Please be careful if you do so.

Installing FreeRADIUS…

  1. First, we’ll need some packages: FreeRADIUS, make (for “building” the certificates), inetutils (for the hostname command):
    # pacman -S freeradius make inetutils
  2. Following the advice from these instructions, I “created” a test user with the username ‘hello’ and password ‘world’ by adding the following to the top of /etc/raddb/users:
    hello Cleartext-Password := "world"
  3. cd into /etc/raddb/certs and run ‘./bootstrap’. This will generate the test certificates.
  4. Somehow the run info directory wasn’t created on my system, so let’s fix that:
    # mkdir /var/run/radiusd
  5. Start FreeRADIUS (in debugging mode). You should see “Ready to process requests.” at the end of the output!
    # radiusd -X

Testing the (very) basic config:

Execute the following to test the basic config:

% radtest -x hello world localhost 0 testing123

As you can probably tell, ‘hello’ and ‘world’ are the username/password, localhost is the RADIUS server’s address and ‘testing123’ is the shared secret (this was the default in my FreeRADIUS configuration). If all goes well, you should get an output similar to:

% radtest -x hello world localhost 0 testing123
Sending Access-Request of id 52 to 127.0.0.1 port 1812
User-Name = "hello"
User-Password = "world"
NAS-IP-Address = 127.0.0.1
NAS-Port = 0
Message-Authenticator = 0x0000000000000000000000000000000

If, instead, you get the following:

% radtest -x hello world localhost 0 testing123
radclient:: Failed to find IP address for raspi
radclient: Nothing to send.

You’ll need to add your hostname (in my case ‘raspi’) to /etc/hosts:

#
# /etc/hosts: static lookup table for host names
#

#<ip-address>   <hostname.domain.org>   <hostname>
127.0.0.1       localhost.localdomain   localhost raspi

If something else happens, take a look at the output of your running ‘radiusd -X’ process and see if that gives any clues.

Congratulations, you have a FreeRADIUS server running! (although with a very simple config – we’ll make it more sophisticated later)

Configuring wireless authentication

FreeRADIUS

So far, we’ve only authenticated a user on the machine that FreeRADIUS was running on, i.e. the supplicant, authenticator and authentication server were all on the same box.  What we want to do next is configure FreeRADIUS in such a way, that it processes AAA requests from your router/wireless Access Point. This is done by adding something like the following to the /etc/raddb/clients.conf file:

# my router
client myrouter {
   ipaddr = <IPv4 address of your router/AP>
   #or ipv6addr = 2001::1
   secret = <myultrasecretsecret>
   nastype = cisco # see the localhost example for other values.
}

I like to use ‘openssl rand -base64 <number of characters>’ for generating a random <myultrasecretsecret> 🙂

These changes will require a restart of radiusd. You can just kill the process with CTRL+C.

On your router/AP

Next, you’ll need to configure your router/AP:

General router/AP:
  • Security mode: WPA2, or WPA2/WPA
  • Cipher: AES-CCMP (TKIP is WPA)
  • use EAP rather than PSK.
  • 802.1X settings:
    • RADIUS server IP: your Raspberry Pi’s IP
    • Port: 1812 is the default port for authentication, 1813 for accounting
    • The shared secret is whatever you set <myultrasecretsecret> to.
D-Link DIR-615 (stock firmware):

The D-Link DIR-615 (H/W Ver. D4) stock firmware unfortunately only supports authentication/authorization, but not RADIUS accounting 🙁 – maybe I should experiment with DD-WRT.

Screenshot of a WPA2 Enterprise configuration for D-Link DIR-615
Screenshot of the D-Link DIR-615 wireless setup menu, showing how to configure a WPA2 Enterprise wireless network.
Cisco Router configuration

The basic idea is to define some AAA (Authentication, Authorization & Accounting) server groups and parameters, then to setup the wireless network and lastly to configure some more detailed RADIUS settings, like which additional attributes to include and what the shared secret is. Note that this is by no means a complete config – you’ll for example probably want to configure a DHCP server, NAT etc, but it should show the wireless and AAA/RADIUS bits that you need. This also probably isn’t the only way of configuring WPA2 Enterprise, but it’s roughly the way how I configured my router 🙂

!
aaa new-model
aaa local authentication attempts max-fail 5
!
! you probably don't need separate groups for accounting and logins
aaa group server radius rad_acct
 server 192.168.1.3 auth-port 1812 acct-port 1813
!
aaa group server radius rad_main
 server 192.168.1.3 auth-port 1812 acct-port 1813
!
aaa authentication login eap_logins group rad_main
aaa authentication login mac_methods group rad_main
aaa authentication ppp default local
aaa authorization ipmobile default group rad_main
aaa accounting update newinfo periodic 5
aaa accounting include auth-profile framed-ip-address
aaa accounting network acct_methods start-stop group rad_acct
!
! you may want to consider this, depending on your setup:
! aaa accounting delay-start
!
aaa session-id common
!
!
dot11 ssid yourwpa2
 vlan 3
 authentication open eap eap_logins
 authentication network-eap eap_logins
 authentication key-management wpa
 accounting acct_methods
 guest-mode
!
!
!
!
interface Dot11Radio0
 no ip address
 beacon period 2000
 no dot11 extension aironet
 !
 encryption vlan 3 mode ciphers aes-ccm
 !
 ssid yourwpa2
 !
 station-role root
 no cdp enable
!
interface Dot11Radio0.3
 encapsulation dot1Q 3
 ip address 192.168.3.1 255.255.255.0
 ip nat inside
 ip virtual-reassembly in
 no cdp enable
!
!
!
ip radius source-interface <radius source interface>
!
!
radius-server attribute 8 include-in-access-req
radius-server attribute 32 include-in-access-req
radius-server attribute 31 send nas-port-detail
radius-server host 192.168.1.3 auth-port 1812 acct-port 1813 key <myultrasecretsecret>
radius-server retransmit 5
radius-server vsa send accounting
radius-server vsa send authentication
!

The <radius source interface> is the interface on which the IP address is configured that your router uses to talk to FreeRADIUS (in my case the one with 192.168.1.1/24).

And finally, connecting your first wireless client…

Mac

Just click on the airport icon, select your network and enter your username and password. If you’re asked to accept an untrusted certificate feel free to do so; this is the test certificate we generated earlier.

Linux

You probably know how to do this already. I recommend using networkmanager if in doubt.

Windows 7
  1. Go to control panel->network and internet
  2. Click on “manage wireless networks”
  3. Click “add” and choose “Manually connect to a wireless network”. Enter your SSID, choose WPA2-Enterprise as security type, AES as encryption type.
  4. Click on “Change connection settings”. Go to the “Security” tab.
  5. Click on ‘Settings’ next to “Choose a network authentication method” (you can leave that set to PEAP).
  6. Untick “Validate server certificate” (the test certificate will fail the validation).
  7. Under “Select authentication method”, click on “Configure” and untick “When connecting: Automatically use my Windows logon name and password (and domain if any)”.
  8. Click OK.
  9. Back on the “Security” tab of the “wireless networks properties”, click on the “Advanced settings” button.  Tick “specify authentication mode” and select “user or computer authentication”, and click on the “save credentials” button. Enter your username/password.

The connection should now succeed.

DaloRADIUS & MySQL setup

DaloRADIUS is a nice frontend to a FreeRADIUS MySQL database, which seems to be designed for people running hotspots. Because I have no intention of billing anyone 🙂 , I won’t need half the features, but it’s still the nicest GUI I’ve found so far. Here’s what it can look like:

Screenshot of the daloRADIUS user accounting admin GUI
Screenshot of the daloRADIUS user accounting admin GUI
  1. Install Apache, MySQL and PHP. PHPMyAdmin (and php-mycrypt) are optional if you’re happy using the MySQL command line.
    # pacman -S apache php php-apache mysql phpmyadmin php-mcrypt php-gd php-pear
    # pear install DB
  2. Run the following to prevent bad surprises:
    # /usr/bin/mysql_secure_installation
  3. Edit /etc/httpd/conf/httpd.conf – change your server admin email address and the like, and follow the instructions on how to enable PHP from the ArchLinux wiki entry on LAMP. I recommend you follow the basics first, make sure you test your php installation with the <?php phpinfo() ?> script and then activate GD.
  4. If you want your webserver to be accessible from the outside, you’ll need to update /etc/hosts.allow by adding e.g. “httpd: 192.168.1.0/24” to allow connections from any machine with an IP address of the form 192.168.1.*. Please adjust this according to your needs.
  5. Optional: follow the following instructions for setting up PHPMyAdmin.
  6. Log into PHPMyAdmin (or using the mysql CLI), create a database called “radius” as well as two user accounts: “freeradius” and “daloradius”. Grant them both all privileges on the radius DB (I recommend you fine-tune these permissions later).
  7. Download the latest DaloRADIUS version to your Raspberry Pi. You may want to get the direct link and use wget/curl to download it, if you didn’t install any desktop environment on your Raspberry Pi.
  8. Extract the archive into /srv/http, and rename daloradius-version to daloradius. Then, run the following:
    % cd /srv/http/daloradius/contrib/db
    % mysql -u root -p radius < fr2-mysql-daloradius-and-freeradius.sql
  9. Edit /srv/http/daloradius/library/daloradius.conf.php, and update the database connection credentials so that they match the ones you set up earlier.
  10. Login to your daloRADIUS installation (http://your-raspberry-pi-ip/daloradius) with the username “administrator” and password “radius”. Make sure the login succeds. If it doesn’t, you’ve most likely got a problem with your database connection – check that MySQL is running, that you installed the required PHP libraries and that /srv/http/daloradius/library/daloradius.conf.php contains the correct connection credentials.
  11. Under Management->Users, add a new test user. Use a cleartext password again, just to make troubleshooting easier.

Making Freeradius use the MySQL database for authentication, authorization & accounting

  1. Edit /etc/raddb/sql.conf so that the database connection parameters (username, password) match with what you setup earlier.
  2. Uncomment the line ‘$INCLUDE sql.conf’ in /etc/raddb/radiusd.conf
  3. Uncomment the ‘sql’ lines in the authorize and accounting sections of /etc/raddb/sites-enabled/default
  4. In /etc/raddb/sites-enabled/inner-tunnel, uncomment the ‘sql’ lines in the authorize and post-auth sections. In the session section, comment “radutmp” and uncomment “sql”. This is so that tunneled authentication mechanisms (such as TTLS) also use the MySQL database.
  5. Restart Freeradius (‘/etc/rc.d/radiusd restart’ or CTRL+C, radiusd -X depending on how you are running it)
  6. Use the radtest utility to check that you can use the username/password you added with DaloRADIUS: ‘radtest <username> <password> localhost 0 testing123’. You should also test that you can use this username/password on your wireless network 🙂

Finishing touches on DaloRADIUS

  • Add the details of your NAS (this is the authenticator, i.e. your router/wireless Access Point) into the radius database. You’ll find these settings under Management->Nas->Add NAS.
  • Define your NAS as a “hotspot”, I think DaloRADIUS thinks of everything as a hotspot.
  • Cisco devices do not seem to send IP address information in network accounting packets, at least not with my setup. It is however possible to send DHCP server accounting information to a radius server, so you can configure that (add ‘accounting …’ to your DHCP pool). Unfortunately, this information will have a different accounting session ID to the network accounting session ID, so you’ll need to correlate the information yourself (this is outside the scope of this tutorial).

Last but not least… Securing it.

  • Use proper certificates. For more information on how to set these up, see the /etc/raddb/certs/README file and the certificate configuration guide on deployingradius.com
  • On Arch Linux, the radiusd user and group are created for Freeradius. It’s a good idea not to run Freeradius as root (remember, it can receive traffic from unauthenticated wireless clients, i.e. anybody near your antennas!). You may need to chown the certs directory though, and make sure that the permissions of /var/run/radiusd and /var/log/radius are correct. To make Freeradius run under the radiusd user and group, uncomment the “user = “and “group = ” lines in /etc/raddb/radiusd.conf and set them equal to “radiusd” rather than “radius”.
  • Store passwords in a responsible manner. The EAP method/password storage compatibility matrix @ deployingradius.com however paints a pretty scary picture; I’m inclined to go with TTLS using PAP or MSCHAPv2 for inner authentication, storing the passwords with SHA sums in the DB (or ntlm hashes in case of MSCHAPv2). The easiest way to create a user with a hashed password is to just select the hashing method from the drop-down menu DaloRADIUS gives you when creating a user, and then to copy/paste the hash of the password into the text field.
  • Disable insecure EAP methods.
  • Limit the permissions of the “freeradius” and “daloradius” database users. Freeradius probably shouldn’t be able to create new users…
  • Make sure you do some negative testing as well, i.e. check that logging in with invalid credentials fails!

Congratulations, you should now have a working WPA2 Enterprise wireless network!

Helpful links, references & further reading

In no particular order:

Debugging tips

Enable debugs everywhere:

  • Run “radiusd -X” on the Raspberry Pi.
  • Enable debugs on your router (if possible). Here are some for Cisco devices:
    • debug aaa authentication
    • debug aaa authorization
    • debug dot11 aaa authenticator all
    • debug aaa accounting
  • Check the logs on your wireless client (the supplicant).

Full disclosure

I am currently a Cisco employee, and the views expressed on this blog are mine and do not necessarily reflect the views of Cisco.

13 Replies to “WPA 2 Enterprise from scratch using a Raspberry Pi”

  1. I just want to thank you. It to people like you that make me love humanity, thanks for your work. I will try the setup when i have my pi.

  2. I don’t want to be greedy, but do you have a SD-Card image from your project? This would save a lot of time! In anyway thanks for sharing this great information!

    1. Hi Tim,
      Thank you for your comment!

      I unfortunately don’t have an SD card image from my project (I’ve re-formatted my Raspberry Pi since I did this). I did think that this would be a good opportunity for me to learn how to use Chef/Puppet and put together a chef recipe/puppet manifest which can be used to automatically set this up. The next time I set this up I’ll do it with one of those automation tools, or at least script-ify the installation.
      Best regards,
      Michiel

  3. How good is the performance on the Rasberry Pi? I’ve been looking to have a dedicated Radius Server, but couldn’t think to spend the money and build my own hardware, and I didn’t have any “spare” computers that I could use for just the server. As in, if you have less than 5 users/devices on at the same time on your network, is the performance badly affected, or is there any affect on the actual err browsing experience for those on the network?

    Also, could you use the Rasberry Pi for anything else once it became a Radius server? Like on Arch, could you create and install extra modules to the kernel on to the Pi, like a moderately sized project, maybe even running a little LCD. My second question is, on the Pi once you’re running the server, can you still operate the more Microcontroller portions of the Pi, like send data through SPI or I2C, without it affecting the operation of the server?

    thanks!

    1. Hi Victor,
      Excellent question. The Raspberry Pi doesn’t act as a wireless controller, it just acts as an authentication server. Once your wireless client has been authenticated, traffic goes directly from the client via the router/AP to the destination, it doesn’t have to pass through the FreeRADIUS server.

      Because of that, I’d expect the steady-state load to be fairly minimal, it should only consist of periodic accounting requests (if you’ve set that up) and perhaps the occasional authentication event when a device goes to sleep or goes out of range and comes back into range.

      I don’t remember what the steady-state RAM requirements were (especially if you setup Apache+MySQL for DaloRADIUS), but I used a 256MB Raspberry Pi and I could at least let it control a 7-segment display at the same time, so I think you should be OK :). Of course it depends a bit what you do with your LCD display, playing CPU and RAM intensive games on a high-res LCD display would probably push the Pi to its’ limits, but I suspect that’s the case whether or not you run FreeRADIUS on it. Periodically displaying some text on an 18×2 display shouldn’t be an issue though.

  4. I add the users then when I try executing radius -X I get this error
    libssl version mismatch. built: 1000109f linked: 1000107f

    any ideas

    1. You need compile the freeradius from their site tarball (need to handle some dependencies) and its usually get installed to /usr/local/etc/raddb/

      Thanks to author for this article , Helped a lot

  5. Just to let you know: meanwhile one has to switch additonally from “mysql” to “mysqli” in daloradius.conf.php. Else the “DB Error: extension not found” is shown only on login.

  6. I already had Rasbian installed on my pi so I used that instead of switching. Works a treat. Even got Radius VLans working! Using 3 different routers… EA3500 Linksys firmware, EA3500 Openwrt and Unifi AP AC.

    Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *