Gong Cheng [hacking]
3/9/2008

HOWTO: Incremental Setup of FreeRADIUS Server for EAP Authentications

fsmsh.com/2760 [freeradius]

Introduction

If you are like me and need to set up a FreeRADIUS server for EAP authentications every so often, each time do you also find yourself having a little hard time trying to refresh your memory? Well, after that happened to me for a couple of times, I found that a incremental and systematic way of setting up and testing FreeRADIUS server could make it easier to remember and easier to debug. Here is what I do and I hope it can benefit others as well.

Step 1. Set up and test local authentication without EAP, using radtest tool. Step 2. Set up and test remote authentication without EAP, using radtest tool. Step 3. Set up and test simple EAP method EAP-MD5 (without certificates), using radeapclient tool. Step 4. Install necessary certicates, set up and do full tests of more sophisticated EAP methods like EAP-TLS, PEAP and EAP-TTLS, using the eapol_test tool from the wpa_supplicant project.

If this approach seems to make sense to you, I have more details below on each step.

A Few Things First

Before going to the steps, there are a few things I'd like to set aside:

The Steps

Step 1. The most basic: Local authentication without EAP

In this step, all the configurations you need is to add a test user at the end of your users file with its password listed, like this:

testuser Cleartext-Password := "password"

We don't need to configure the clients.conf file because FreeRADIUS server's default clients.conf already has an entry for local authenticators: 127.0.0.1. For each authenticator/NAS in the file, a shared secret with the FreeRADIUS server needs to be provided too, and for 127.0.0.1 it is by default "testing123".

Now go ahead and restart your server.

There is a included tool in FreeRADIUS package (normally found in /usr/local/bin) called radtest that is very convenient. In Step 1, we invoke the radtest tool locally on the same host your FreeRADIUS daemon is running:

radtest testuser password 127.0.0.1 1812 testing123

The syntax is straightforward:

radtest <user name> <user password> <server IP address> <server UDP port> <shared secret>

You should see an output like this:

Sending Access-Request of id 11 to 127.0.0.1 port 1812

User-Name = "testuser"

User-Password = "password"

NAS-IP-Address = 127.0.1.1

NAS-Port = 1812

rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=11, length=20

It succeeds if an Access-Accept is received like the above.

There is something extra here for FreeRADIUS 1.x users: your default users file that you change upon might came with a line like

  DEFAULT Auth-Type = System

That line could ruin a simple radtest test like the above. What it means is that by default a user will use local Unix password system for authentication unless the "Auth-Type" is overwritten later with a different value. It does affect a request coming from radtest and will require your local Unix system to have a user named testuser and with password "passowrd" to make our test succeed. That is not very likely to be the case unless you create such a user. An easy solution is to comment out that line by putting a "#" at the beginning. You could also add a "Auth-Type := Local," in your testuser entry but you will have to remember removing that for the EAP tests we have later.

You might also see people use "User-Password :=" rather than using "Cleartext-Password". Both work for older versions but you should stick to the latter in latest versions.

Step 2. One step further: authenticate via a remote authenticator

Once you passed Step 1, we can go one step further by invoking radtest from another host. This does mean that you need to have a FreeRADIUS installed, preferably matching versions, on another host that is network reachable.

Before you fire your radtest on another host, you need one more configuration change: Add your test authenticator host at the end of your clients.conf and assign a shared-secret. This is what I use for a host at 192.168.1.100

  client 192.168.1.100 {

      secret = testing123

      shortname = 192.168.1.100

   }

Suppose the server itself is at 192.168.1.1, then all you need is to change 127.0.0.1 from previous test into 192.168.1.1 (I am using same shared secret here), and do it from 192.168.1.100:

radtest testuser password 192.168.1.100 1812 testing123

Again, it succeeds only if an Access-Accept is received.

Step 3. Getting the simplest EAP method into the picture: EAP-MD5

Now we are ready to try out the basic EAP functionality. EAP-MD5 is among the simplest EAP methods available, but it does allow you to exercise your FreeRADIUS server's EAP module without requiring things like certificates. You should be warned though that EAP-MD5 is not considered an secure authentication method. We only use it for testing here.

FreeRADIUS came with another tool that can be used to test EAP-MD5: radeapclient You can normally find it at /usr/local/bin too if you've installed FreeRADIUS.

For our purpose, the tool can be used like this:

This is what works:

( echo "User-Name = \"testuser\""; \

  echo "Cleartext-Password = \"password\""; \

  echo "EAP-Code = Response"; \

  echo "EAP-Id = 210"; \

  echo "EAP-Type-Identity = \"testuser\""; \

  echo "Message-Authenticator = 0x00"; ) | \

radeapclient -x 127.0.0.1 auth testing123

It is a command the accepts input from standard input which is generated from a series of echo commands printing RADIUS attributes.

The command succeeds if you see an Access-Accept packet with EAP-Code = Success.

You might have noticed that command is issued from local host. You could repeat the same test on a different host. Just change 127.0.0.1 to the server IP address, and make sure you have an entry for your authenticator in clients.conf, just like before.

Step 4. Full swing with EAP-TLS, EAP-TTLS and PEAP

We are almost ready for testing more sophisticated EAP methods, with two more preparations to be done.

Firstly, install your certificates and update your eap.conf to reflect the paths to necessary files. If you have your own certificate generation mechanism already in place, and in that case, you need to copy three files onto your FreeRADIUS server's host:

diff -upNr /usr/local/etc/raddb.orig/eap.conf /usr/local/etc/raddb/eap.conf

--- /usr/local/etc/raddb.orig/eap.conf 2008-02-28 16:44:51.000000000 -0800

+++ /usr/local/etc/raddb/eap.conf 2008-02-28 18:10:26.000000000 -0800

@@ -145,7 +145,8 @@

cadir = ${confdir}/certs



private_key_password = whatever

- private_key_file = ${certdir}/server.pem

+ #private_key_file = ${certdir}/server.pem

+ private_key_file = /home/gcheng/myCA/radiusd_serverkey.pem



# If Private key & Certificate are located in

# the same file, then private_key_file &

@@ -157,7 +158,8 @@

# only the server certificate, but ALSO all

# of the CA certificates used to sign the

# server certificate.

- certificate_file = ${certdir}/server.pem

+ #certificate_file = ${certdir}/server.pem

+ certificate_file = /home/gcheng/myCA/radiusd_servercert.pem



# Trusted Root CA list

#

@@ -174,7 +176,8 @@

# not use client certificates, and you do not want

# to permit EAP-TLS authentication, then delete

# this configuration item.

- CA_file = ${cadir}/ca.pem

+ #CA_file = ${cadir}/ca.pem

+ CA_file = /home/gcheng/myCA/cacert.pem



#

# For DH cipher suites to work, you have to

Once your certificate and eap.conf is ready, you can restart your FreeRADIUS server and it is ready for EAP testing. The tool I found very convenient is called eapol_test that came with the wpa_supplicant project. unfortunately, it is not included in a wpa_supplicant binary package. But not to worry, just building it from source is not that hard either, and the following is all I needed:

wget http://hostap.epitest.fi/releases/wpa_supplicant-0.5.10.tar.gz

tar xvf wpa_supplicant-0.5.10.tar.gz

cd wpa_supplicant-0.5.10/

cp defconfig .config

make eapol_test

A binary eapol_test will be generated if the build was successful, and I'd copy it to /usr/local/bin:

ls eapol_test

cp eapol_test /usr/local/bin/

Now that your eapol_test is installed, you need to prepare a configuration file for it for each EAP method you want to test. The file format is very simple, and if you are already family with the wpa_supplicant configuration file format, it will look familiar to you. For example, the following is for PEAP testing:

$ cat eapol_test.conf.peap

network={

eap=PEAP

eapol_flags=0

key_mgmt=IEEE8021X

identity="testuser"

password="password"

ca_cert="/home/gcheng/myCA/cacert.pem"

phase2="auth=MSCHAPV2"

anonymous_identity="anonymous"

}

And this is how you invoke the command to start the test:

eapol_test -c eapol_test.conf.peap -a127.0.0.1 -p1812 -stesting123 -r1

Like in all authentication tests, Access-Accept is the indication of authentication success.

You might have noticed a couple of things in the configuration file:

$ cat eapol_test.conf.tls

network={

eap=TLS

eapol_flags=0

key_mgmt=IEEE8021X

identity="testuser"

ca_cert="/home/gcheng/myCA/cacert.pem"

client_cert="/home/gcheng/myCA/testuser_cert.pem"

private_key="/home/gcheng/myCA/testuser_key.pem"

private_key_passwd="whatever"

}



$ cat eapol_test.conf.ttls_md5

network={

eap=TTLS

eapol_flags=0

key_mgmt=IEEE8021X

identity="testuser"

password="password"

anonymous_identity="anonymous"

ca_cert="/home/gcheng/myCA/cacert.pem"

phase2="auth=MD5"

}



$ cat eapol_test.conf.ttls_mschapv2

network={

eap=TTLS

eapol_flags=0

key_mgmt=IEEE8021X

identity="testuser"

password="password"

anonymous_identity="anonymous"

ca_cert="/home/gcheng/myCA/cacert.pem"

phase2="auth=MSCHAPV2"

}

It is worth mentioning that the configuration file of EAP-TLS has not only the ca_cert path like in PEAP and EAP-TTLS configuration files, it also has paths to client certificate and private key. This is because in EAP-TLS, not only does the supplicant verify the server's certificate, the RADIUS server usually verifies the supplicant's certificate too. Also the word "client" here is not to be confused with the "client" in FreeRADIUS configuration files: they are referring to supplicant and authenticator respectively. Please also note that the client's certificate must have been signed by (one of) the root CA listed in the root CA certificate file, otherwise it won't be accepted by the server.

For each of the above configuration file, just invoke the eapol_test command

eapol_test -c <eapol_test config file> -a127.0.0.1 -p1812 -stesting123 -r1

Again, instead of using 127.0.0.1 on the local machine, you can do the test from a different host.

About the tools

When we use radeapclient and eapol_test tools, an observant reader might wonder why there are only two parties involved in the 3-party model testing? The answer is that those tools are specially made to combine the supplicant and authenticator so they are co-located. However, that doesn't affect our testing of RADIUS server functionalities.

Conclusion

If you have passed all the above tests, congratulations! now you have some level of confidence that your freeRADIUS server can perform the basic functions of EAP authenticaitons. Of course, to get the server working with real authenticators and real supplicants, to get it support real world requirements for authentication and attribute assignements, to get it working with other applications like MySQL server, LDAP server, there are a lot more to do. But this is a start and can serve as a reference point. Thanks to its creators and maintainers, FreeRADIUS has become a nice, powerful and robust server, and I wish we all enjoy using it!

Finally, this is all the configuration changes we needed today for the single test user:

$ diff -upNr /usr/local/etc/raddb.orig/ /usr/local/etc/raddb/

diff -upNr /usr/local/etc/raddb.orig/clients.conf /usr/local/etc/raddb/clients.conf

--- /usr/local/etc/raddb.orig/clients.conf 2008-02-28 16:44:51.000000000 -0800

+++ /usr/local/etc/raddb/clients.conf 2008-02-28 17:00:45.000000000 -0800

@@ -227,3 +227,8 @@ client localhost {

# secret = testing123

# }

#}

+

+client 10.166.255.145 {

+ secret = testing123

+ shortname = 10.166.255.145

+}

diff -upNr /usr/local/etc/raddb.orig/eap.conf /usr/local/etc/raddb/eap.conf

--- /usr/local/etc/raddb.orig/eap.conf 2008-02-28 16:44:51.000000000 -0800

+++ /usr/local/etc/raddb/eap.conf 2008-02-28 18:10:26.000000000 -0800

@@ -145,7 +145,8 @@

cadir = ${confdir}/certs



private_key_password = whatever

- private_key_file = ${certdir}/server.pem

+ #private_key_file = ${certdir}/server.pem

+ private_key_file = /home/gcheng/myCA/radiusd_serverkey.pem



# If Private key & Certificate are located in

# the same file, then private_key_file &

@@ -157,7 +158,8 @@

# only the server certificate, but ALSO all

# of the CA certificates used to sign the

# server certificate.

- certificate_file = ${certdir}/server.pem

+ #certificate_file = ${certdir}/server.pem

+ certificate_file = /home/gcheng/myCA/radiusd_servercert.pem



# Trusted Root CA list

#

@@ -174,7 +176,8 @@

# not use client certificates, and you do not want

# to permit EAP-TLS authentication, then delete

# this configuration item.

- CA_file = ${cadir}/ca.pem

+ #CA_file = ${cadir}/ca.pem

+ CA_file = /home/gcheng/myCA/cacert.pem



#

# For DH cipher suites to work, you have to

diff -upNr /usr/local/etc/raddb.orig/users /usr/local/etc/raddb/users

--- /usr/local/etc/raddb.orig/users 2008-02-28 16:44:51.000000000 -0800

+++ /usr/local/etc/raddb/users 2008-02-28 16:47:28.000000000 -0800

@@ -201,3 +201,5 @@ DEFAULT Hint == "SLIP"

# Service-Type = Administrative-User



# On no match, the user is denied access.

+

+testuser Cleartext-Password := "password"



#restart radiusd



# use eapol_test

License

Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice is preserved.