Last updated 2015/09/07

Return to the Suffield Academy Network Documentation Homepage

A printable version of this document is also available.


RADIUS is a protocol used by many pieces of networking equipment to authenticate and authorize users who wish to access the network. It also forms the base of 802.1X, aka WPA-Enterprise, which is the best-known method for securing wireless networks (as opposed to pre-shared single-key systems such as WPA-Personal).

FreeRADIUS is a wonderful piece of software that acts as a RADIUS server. It allows you to authenticate against numerous back-ends (flat files, SQL, LDAP, ActiveDirectory), has built-in configurations for redundancy and failover, and even has options for embedded languages like Perl so you can write your own custom server logic.

This document describes our setup and configuration of FreeRADIUS.

A few implementation notes/assumptions; the code we use has been tested in the following environment:

We currently use Juniper gear on the wired side (EX4200/3200 switches). We also use Juniper (formerly Trapeze) wireless controllers.

We currently use a Samba-based ActiveDirectory domain for centralized authentication.

Debian Jessie is the base operating system that we run everything on.


We have two RADIUS servers that operate in parallel with each other. They are configured identically (except for minor differences like hostnames) and serve requests independently of each other.

FreeRADIUS is configured to provide the following major services (there are nearly a dozen configured modules, but these are the most important):

Setting up Samba

We're authenticating against AD, so we'll need Kerberos and Winbind stuff:

apt-get install heimdal-clients heimdal-kcm libpam-winbind libnss-winbind


If prompted, accept the default configuration for Kerberos. It doesn't matter much; we'll be paving over the config file with this (substitute your AD realm name in ALL CAPS):

# /etc/krb5.conf
        default_realm = AD.SUFFIELDACADEMY.ORG
        dns_lookup_realm = false
        dns_lookup_kdc = true

You should verify that you can get a kerberos ticket at this point:

kinit user
klist user


Next, go grab the smb.conf.member_server config file from the activedirectory repository and drop it into /etc/samba/smb.conf. Note that you may wish to set the password server option to list a preferred set of servers, followed by the '*' wildcard for auto-lookup. In this way, you can diversify the servers used from different RADIUS servers but still maintain auto-failover.

Restart samba:

/etc/init.d/samba restart

Now, join the server to the domain:

net ads join -U administrator \
        "osName=Debian GNU/Linux" "osVer=$(cat /etc/debian_version)"

Note that there might be some IPv6 errors, but those are (aparently?) harmless...

Generate a keytab:

kinit administrator
net ads keytab create

Confirm that it passed the smoke test:

net ads testjoin

If that passes, then you can be reasonably sure that you've joined the domain and are ready to move on to the next step.


Winbind is a daemon that allows you to translate between the world of UNIX authentication and ActiveDirectory authentication. You can use it to merge with NSS and other system-wide tools to authenticate users on your Linux box via ActiveDirectory.

In this case, we're setting it up so FreeRADIUS can use it to authenticate users. We won't integrate it with the system as a whole; just FreeRADIUS.

Restart winbindd:

/etc/init.d/winbind restart

A few basic tests:

wbinfo --own-domain
wbinfo --domain-info <domain>
wbinfo --dsgetdcname <domain>
wbinfo -u
wbinfo -g

wbinfo -a 'username%password'
wbinfo -K 'username%password'

You should get back sane answers from those (substitue real usernames and passwords). If you do, then auth is working and you're ready to have FreeRADIUS use it.

Building FreeRADIUS

Follow these directions to build FR from source:

(Substitute the current stable version number as found on

The "installs" dependencies are found in the source package debian/control file.

apt-get install dpkg-dev ssl-cert

apt-get install debhelper quilt dpkg-dev autotools-dev libcurl4-openssl-dev libcap-dev libgdbm-dev libiodbc2-dev libjson-c2 libjson-c-dev libkrb5-dev libldap2-dev libpam0g-dev libpcap-dev libperl-dev libmysqlclient-dev libpq-dev libreadline-dev libsasl2-dev libsqlite3-dev libssl-dev libtalloc-dev libwbclient-dev libyubikey-dev python-dev


tar -jxf freeradius-server-3.0.9.tar.bz2

cd freeradius-server-3.0.9

Note that as of this writing (FR 3.0.9) there is a bug where two of the FR packages both list the same module files, and so they conflict. Edit the debian/freeradius.install file and change:




(See for more information.)

When you're ready to build:

fakeroot dpkg-buildpackage -b -uc

If it all builds well, install the packages (path is relative to the build directory):

dpkg -i ../*freeradius*.deb

Configuring FreeRADIUS

Attempting to describe the configuration of FreeRADIUS here would take far too long and take too much space. The configuration files (in /etc/freeradius) are the best place to start. All of our changes are heavily commented (grep for "suffield:"), and in most cases we've actually made copies of entire files and renamed them with an "sa-" prefix to make them easier to find. For example, instead of changing the "eap" file in "mods-available", we made a copy named "sa-eap" and kept all our changes there.

FreeRADIUS has a few files that aren't auto-included, and so must be named by convention. radiusd.conf and clients.conf have our modifications (again, commented), but the files have not been renamed.

If you're just getting familiar with the sources, start with the sa-authz and sa-accounting files in the sites-available directory. Those are the top-level "server" files, which reference the other files we've configured. They'll give a good overview of how the configuration is organized. Additionally, the clients.conf file contains the very-necessary definition of clients that are allowed to connect to the server, as well as the shared secrets used between them.

(See TODO for more information on how this might change.)

Winbind Socket Access

If using winbind to authenticate users against AD, you must grant read permissions to the user FreeRADIUS runs as:

setfacl -m u:freerad:rx /var/lib/samba/winbindd_privileged

(Those are the default usernames and file locations under Debian Jessie.)

FreeRADIUS Configuration

To get the config up and running, make sure that all of the "sa-" files have been symlinked into their "enabled" directories (for modules and sites). The sites-enabled directory should only contain the "sa-" prefixed symlinks; remove the default and inner-tunnel links.

Other files should go where they are defined (policy.d, top-level, and others).

To test the config, run freeradius -XC. If no errors are reported, you can run the server in debug mode with freeradius -X. That will provide extensive output to the console and you can test connections to the server (many network equipment operating systems have a "radtest" or "radping" function that lets you send test queries to the server).

If all looks good, you can use the init scripts to start freeradius permanently.


Check files into source control

Right now, the /etc/freeradius files are not checked into source control. They were built as a one-off on Jacen. To make things a little better, consider the following plan:

Edit /etc/default/freeradius and have it search for a config file in /etc/freeradius/suffield/$(hostname -s).conf. If found, append the "-n $(hostname -s)" to FREERADIUS_OPTIONS.

Make a copy of the default radiusd.conf file and name it by hostname. Comment out stuff you don't need (proxy?) and include anything non-standard you want (a separate clients file?).

Maybe even have that radiusd.conf copy generic, and have a per-hostname file that sets a few global variables (like hostname) and INCLUDES it.

The only real issue left is/are the secrets in clients.conf and eap, which are coded into the file but not easy to load from somewhere else. Maybe have a SECRETS file that has all the sensitive data, and the other modules can reference the variables set there. Then that could be the only thing that ISN'T checked into source control.

Fix accounting

Right now, we've built a nice "robust" accounting server that logs in two phases: once to disk in "detail" format, and then reading that format to perform the final handling. If the second phase fails for any reason, the first continues to chug along logging to disk until it becomes available again.

We've written a basic perl script that "handles" the accounting by line logging to a file, but ideally we'd want to do some SQL logging of things. The hooks are there, but there's still some work to do:

Current plan is to let the perl "preacct" hook handle all the heavy lifting: fix any missing attributes (possibly by adding hooks and storage to the authz phases), and coalesce values into counters. Might need to invent some "SA-*" AVPs to store these (add them to our sa-dictionary).

Next, hollow out the SQL module to just do accounting updates using a new schema that references these attributes. The built-in schema is fine, but is missing some things we'd want (like NAS-Location-Id) in our reporting. Easier to just synthesize it all with something flexible like perl, and then let the SQL code just grab it and dump it in the DB.

Merge MAC-auth and CoA

Still looking to improve upon the perl authz script to deal with CoA and MAC auth. Probably use redis (or another shared key/value store) to hold the MAC/port/role/etc database.