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):
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 [libdefaults] 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.
Follow these directions to build FR from source:
http://wiki.freeradius.org/building/Build#Building-Debian-packages
(Substitute the current stable version number as found on http://freeradius.org/download.html)
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 wget ftp://ftp.freeradius.org/pub/freeradius/freeradius-server-3.0.9.tar.bz2 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:
usr/lib/freeradius/proto*.so
to
usr/lib/freeradius/proto_vmps.so
(See https://github.com/FreeRADIUS/freeradius-server/issues/1125 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
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.)
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.)
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.
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.
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.
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.