Configuring FreeRADIUS for LDAP over SSL Authentication

As a Network Engineer there will undoubtedly be a time when you need to set up your own RADIUS front-end so that 802.1x, VPN, AAA, a Wireless Controller, or all the above, can securely authenticate against the Corporate LDAP Directory Server.

I found FreeRADIUS on Ubuntu (10.04 in my environment) to be not only cost-effective, but a fairly easy installation despite the lack of solid LDAP over SSL documentation. In this post I’ll focus squarely on the configuration necessary to get FreeRADIUS authenticating against your LDAP server using SSL.

Assumptions

  • Ubuntu is already installed
  • You aren’t using EAP, TTLS, or TLS for authentication
  • You are familiar with the hierarchy of your company’s LDAP Directory Server
  • You can either bind anonymously to the LDAP Server or know the appropriate admin credentials to do so

Installation and Configuration

1. Install the freeradius package and dependencies

root@ps1607:~# apt-get install freeradius
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
freeradius-common freeradius-utils libfreeradius2 ssl-cert
Suggested packages:
freeradius-ldap freeradius-postgresql freeradius-mysql freeradius-krb5
The following NEW packages will be installed:
freeradius freeradius-common freeradius-utils libfreeradius2 ssl-cert
0 upgraded, 5 newly installed, 0 to remove and 70 not upgraded.
Need to get 1,069kB of archives.
After this operation, 4,235kB of additional disk space will be used.
Do you want to continue [Y/n]? y

2. Install freeradius-ldap package

root@ps1607:~# apt-get install freeradius-ldap
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
freeradius-ldap
0 upgraded, 1 newly installed, 0 to remove and 70 not upgraded.

3. /etc/freeradius/clients.conf

Edit the clients.conf file and add the clients (subnets, actually) along with the secret key (or keys) that will be used to communicate with this server. For the sake of simplicity, I used the same key for all clients in this example.

client localhost {
ipaddr = 127.0.0.1
secret = secretkey
nastype     = other
}

client 192.168.0.0/16 {
 secret = secretkey
nastype = other
}

client 10.0.0.0/8 {
secret = secretkey
nastype = other
}

4. /etc/freeradius/radiusd.conf

I don’t want to use EAP, so I removed the “$INCLUDE eap.conf” setting from the default configuration of radiusd.conf. Other than that, everything is at default.

prefix = /usr
exec_prefix = /usr
sysconfdir = /etc
localstatedir = /var
sbindir = ${exec_prefix}/sbin
logdir = /var/log/freeradius
raddbdir = /etc/freeradius
radacctdir = ${logdir}/radacct

name = freeradius

confdir = ${raddbdir}
run_dir = ${localstatedir}/run/${name}

db_dir = ${raddbdir}

libdir = /usr/lib/freeradius
pidfile = ${run_dir}/${name}.pid

user = freerad
group = freerad

max_request_time = 30
cleanup_delay = 5
max_requests = 1024

listen {
type = auth
ipaddr = *
port = 0
}

listen {
ipaddr = *
port = 0
type = acct
}

hostname_lookups = no
allow_core_dumps = no

regular_expressions    = yes
extended_expressions    = yes

log {
destination = files
file = ${logdir}/radius.log
syslog_facility = daemon
stripped_names = no
auth = no
auth_badpass = no
auth_goodpass = no
}

checkrad = ${sbindir}/checkrad

security {
max_attributes = 200
reject_delay = 1
status_server = yes
}

proxy_requests  = yes
$INCLUDE proxy.conf
$INCLUDE clients.conf

thread pool {
start_servers = 5
max_servers = 32
min_spare_servers = 3
max_spare_servers = 10
max_requests_per_server = 0
}

modules {
$INCLUDE ${confdir}/modules/
}

instantiate {
exec
expr
expiration
logintime
}

$INCLUDE policy.conf
$INCLUDE sites-enabled/

5. /etc/freeradius/modules/ldap

Configure the server, port, and basedn settings to match your environment and add the “set_auth_type = yes” configuration to your ldap stanza.

If you need to bind to your LDAP server with a name and password, you’ll want to un-comment the identity and password parameters from the default file and set them accordingly.

Note: I’ve stripped out the TLS configuration and all of the comments in the original file from mine. It made it easier to understand and troubleshoot.

ldap {
server = "ldap.domain.com"
port = "636"
basedn = "dc=domain,dc=com"
filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
ldap_connections_number = 5
timeout = 4
timelimit = 3
net_timeout = 1
dictionary_mapping = ${confdir}/ldap.attrmap
edir_account_policy_check = no
set_auth_type = yes
}

6. /etc/freeradius/sites-available/default

Edit the default file so that “ldap” is included in the “authorize” and “authenticate” sections. I removed “unix”  and all other options from these sections.

authorize {
ldap
}
authenticate {
Auth-Type LDAP {
ldap
}
}
preacct {
}
accounting {
}
session {
radutmp
}
post-auth {
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
pre-proxy {
}
post-proxy {
}

7. /etc/freeradius/sites-available/inner-tunnel

Same deal as we did in the previous step for the default file: add “ldap” and remove everything else from “authorize” and “authenticate” sections.

server inner-tunnel {
authorize {
ldap
}
authenticate {
Auth-Type LDAP {
ldap
}
}
session {
radutmp
}
post-auth {
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
pre-proxy {
}
post-proxy {
}
}

Verification and Testing

1. Run “freeradius -X” to verify service will start

Once you have your configuration updated, you’ll want to run FreeRADIUS in the foreground by entering “freeradius -X” from the command line to verify that it starts up correctly. You may need to first issue the “service freeradius stop” command if the service auto-started after installation.

For the sake of brevity, I removed a majority of the verbose output. You’ll know your configuration is good if you get “Ready to process requests” after everything loads.

root@ps1607:# freeradius -X
FreeRADIUS Version 2.1.8, for host x86_64-pc-linux-gnu, built on Jan  5 2010 at 02:56:18
Copyright (C) 1999-2009 The FreeRADIUS server project and contributors.

Starting - reading configuration files ...

radiusd: #### Loading Realms and Home Servers ####
radiusd: #### Loading Clients ####
radiusd: #### Instantiating modules ####
radiusd: #### Loading Virtual Servers ####
radiusd: #### Opening IP addresses and Ports ####

Listening on authentication address * port 1812
Listening on accounting address * port 1813
Listening on proxy address * port 1814
Ready to process requests.

2. Test Authentication

You’re ready to test authentication! The easiest way to test this is to open a second terminal window for your server and use the radtest command. You’ll be able to watch the debug output in your other window.

Terminal Window #2: radclient

root@ps1607:# radtest porter ldap-password ps1607 1812 secretkey
Sending Access-Request of id 37 to 10.0.0.7 port 1812
User-Name = "porter"
User-Password = "ldap-password"
NAS-IP-Address = 10.0.0.7
NAS-Port = 1812
rad_recv: Access-Accept packet from host 10.0.0.7 port 1812, id=37, length=20

Terminal Window #1: freeradius -X

Listening on authentication address * port 1812
Listening on accounting address * port 1813
Listening on proxy address * port 1814
Ready to process requests.
rad_recv: Access-Request packet from host 10.0.0.7 port 55230, id=110, length=58
User-Name = "porter"
User-Password = "ldap-password"
NAS-IP-Address = 10.0.0.7
NAS-Port = 1812
+- entering group authorize {...}
++[preprocess] returns ok
[ldap] performing user authorization for porter
[ldap]     expand: %{Stripped-User-Name} ->
[ldap]     ... expanding second conditional
[ldap]     expand: %{User-Name} -> porter
[ldap]     expand: (uid=%{%{Stripped-User-Name}:-%{User-Name}}) -> (uid=porter)
[ldap]     expand: dc=domain,dc=com -> dc=domain,dc=com
[ldap] ldap_get_conn: Checking Id: 0
[ldap] ldap_get_conn: Got Id: 0
[ldap] attempting LDAP reconnection
[ldap] (re)connect to ldap.domain.com:636, authentication 0
[ldap] setting TLS mode to 1
[ldap] bind as / to ldap.domain.com:636
[ldap] waiting for bind result ...
[ldap] Bind was successful
[ldap] performing search in dc=domain,dc=com, with filter (uid=porter)
[ldap] No default NMAS login sequence
[ldap] looking for check items in directory...
[ldap] looking for reply items in directory...
WARNING: No "known good" password was found in LDAP.  Are you sure that the user is configured correctly?
[ldap] Setting Auth-Type = LDAP
[ldap] user porter authorized to use remote access
[ldap] ldap_release_conn: Release Id: 0
++[ldap] returns ok
Found Auth-Type = LDAP
+- entering group LDAP {...}
[ldap] login attempt by "porter" with password "ldap-password"
[ldap] user DN: uid=porter,ou=people,dc=domain,dc=com
[ldap] (re)connect to ldap.domain.com:636, authentication 1
[ldap] setting TLS mode to 1
[ldap] bind as uid=porter,ou=people,dc=domain,dc=com/ldap-password to ldap.domain.com:636
[ldap] waiting for bind result ...
[ldap] Bind was successful
[ldap] user porter authenticated successfully
++[ldap] returns ok
+- entering group post-auth {...}
Sending Access-Accept of id 110 to 10.0.0.7 port 55230
Finished request 0.
Going to the next request
Waking up in 4.9 seconds.

Finishing Up

Kill your freeradius foreground process and restart the service. You’re all set!

13 comments

  1. Hi !

    Thank you for this nice tutorial.
    I have only one comment, I run a “tcpdump -A” on the both sides (freeradius server and ldap server) and I can confirm that the password is transmitted in plaintext. There seems to be no SSL tunnel between them.
    Is there something I misunderstood ? Or did you forget something ?

    Thanks in advance !

  2. Hi,

    first of all thank you for this tutorial!

    I did it accordingly but i get following error:

    > [ldap] ldap_search() failed: Operations error
    [ldap] search failed
    [ldap] ldap_release_conn: Release Id: 0
    ++[ldap] returns fail

    Then I set up “identity + Password” in ldap which could be necessary to gain full Access to LDAP for search .. but again an error:

    > [ldap] LDAP login failed: check identity, password settings in ldap section of radiusd.conf
    [ldap] (re)connection attempt failed

    Do you have any ideas?

    Thank you in advance!

  3. Sorry but I forgot to say that uid + pw credentials okay and verified. 🙂

    This is the main part of ldap config-file:

    ldap {

    server = “zentyaldc.domain.local”
    port = “636”
    #identity = “cn=Freeradius,ou=Radius,do=domain,dc=local”
    #password = “password”
    basedn = “ou=Users,dc=domain,dc=local”
    filter = “(uid=%{%{Stripped-User-Name}:-%{User-Name}})”
    #base_filter = “(objectclass=radiusprofile)”
    groupmembership_attribute = “cn=Radius,ou=Radius,dc=domain,dc=local”

    ldap_connections_number = 5

    timeout = 4

    Thanks!

  4. Hi Folks,
    I just wanted to understand the benefits of using LDAP for Radius authentication.
    One of our client is using Radius in back end its LDAP and then ldap is integrated with MySQL.

    so flow is like Node->Radius->LDAP->MySQL.

    cant this could be Node->Radius->MySQL

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s