FreeRADIUS with AD and UniFi


After having lots of connection issues with UniFi and Windows Network Policy Server (NPS - its RADIUS implementation), I found that moving back to the Linux-based FreeRADIUS greatly improved the chances of trouble-free connections.
(The most recent versions of UniFi AP firmware paired with iOS 11 and 12 may give an erroneous "Incorrect password" error. Using Windows for RADIUS authentication made this issue a lot worse. Using Linux for RADIUS authentication makes this issue occur far less frequently.)

Most of the guides I've seen for setting up Kerberos, FreeRADIUS, and Samba seemed a little over complex - the guides mentioned modifying way too many files, and adding way too much to them.

The following assume that your Active Directory is set up as "DOMAIN.LOCAL" (and that DNS is working), and that the radius server will have the hostname of "RADIUS1".

I started with a clean install of Ubuntu Server 18.04.1 (with my "Revert Networking" changes). UniFi controller version 5.8.30, and UniFi AP firmware version 3.9.54.9373.


Enable the "Universe" repository (needed for Kerberos) and install the necessary packages:

sudo add-apt-repository universe
sudo apt install winbind samba krb5-user freeradius

Add the FreeRADIUS user to the Winbind group so that it can access the winbind pipe:

sudo usermod -aG winbindd_priv freerad

Rename or remove the existing Kerberos and Samba configuration files. My working installs work with just the following in them.


/etc/krb5.conf

#
# /etc/krb5.conf
#

[libdefaults]
 default_realm = DOMAIN.LOCAL

# EoF

/etc/samba/smb.conf

#
# /etc/samba/smb.conf
#

# start of global variables
[global]

# server information, this is the domain/workgroup
workgroup = DOMAIN

# Kerberos / authentication information
realm = DOMAIN.LOCAL

# system hostname
netbios name = RADIUS1

# security used (Active Directory)
security = ADS

# EoF

You will then want to update your /etc/hosts file so that the system's FQDN is listed fist. It might look like this:

127.0.0.1    radius1.domain.local radius1 localhost.localdomain localhost

Restart Samba:

sudo service smbd restart

Now you need to bind the system to the domain.

First, you need to obtain a Kerberos ticket (replace "Administrator" in the following command with any account that has permission to join systems to the domain):

sudo kinit Administrator

Check to make sure the ticket was issued:

sudo klist

Issue this command to join the system to the domain:

sudo net ads join -U Administrator

You can then test the join with the following command:

sudo net ads testjoin

If the join is "OK", restart Winbind:

sudo service winbind restart

Test Winbind by listing domain users:

wbinfo -u

It should give you a list of domain users.


For the FreeRADIUS configuration, we will be updating three files, and adding one new one.

For the first change, it is actually an optional change. It is only to show authentication success/failures in the logs (useful for troubleshooting why someone cannot connect).
In the file /etc/freeradius/3.0/radiusd.conf, change this line:

auth = no

To this:

auth = yes

In the file /etc/freeradius/3.0/mods-available/eap, update the following lines.

Change or delete the password from this line:

private_key_password = 

Change these lines to point to your keys:

private_key_file = /your_private_key_location.key
certificate_file = /your_certificate_file.cert

Change or comment-out this line:

# ca_file = /etc/ssl/certs/ca-certificates.crt

For the next file, there are multiple possible changes that you might want to make. If you allow all users to connect to WiFi, then edit /etc/freeradius/3.0/mods-available/mschap and uncomment out these two lines:

winbind_username = "%{mschap:User-Name}"
winbind_domain = "%{mschap:NT-Domain}"

This uses the built-in Winbind support of FreeRADIUS to authenticate. This can be quicker/more reliable than the older "ntlm_auth" method.

The ntlm_auth method allows you to require a specific group-membership for connection, though, without requiring any other configuration changes (I use to have to use LDAP to query group membership, for example).

If you require specific group membership (such as a "WiFi Users" group), then you will want to instead update /etc/freeradius/3.0/mods-available/mschap to uncomment and change the following line (making note of the "require-membership-of" part):

ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --domain=%{mschap:NT-Domain} --require-membership-of='DOMAIN\WiFi Users' --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"

Again, just make one of the two changes to the mschap file (enable winbind or ntlm_auth, but not both).


The last file is the WiFi configuration for your site.

Create the file /etc/freeradius/3.0/sites-available/wifi and place the following in it (adjusting for your RADIUS password and IP addresses used for APs).

#
# /etc/freeradius/3.0/sites-available/wifi
#

client UniFi-APs {
	shortname	= WiFi
	virtual_server	= wifi
	secret          = RAD1USp4ssw0rd
	# allowed clients
	ipaddr		= 10.0.0.0/24
}
server wifi {
	authorize {
		# cleans up attributes, required
		preprocess
		# we use eap authentication, required
		eap 
	}
	authenticate {
		# mschap authentication
		Auth-Type MS-CHAP {
			mschap
		}
		# eap, this is required
		eap
	}
}

# EoF

Then create a symbolic link for it in the /sites-enabled/ directory:

sudo ln -s ../sites-available/wifi /etc/freeradius/3.0/sites-enabled/wifi

Enable the FreeRADIUS service and restart it:

sudo systemctl enable freeradius.service
sudo service freeradius restart

(Updated February 2019)