Doing network authentication properly!

I don’t like Microsoft NPS.

That’s not to say that it’s a very convenient server role, which it absolutely is, or that it doesn’t have a place, which it sort of does. It’s just that it’s almost always, in my own opinion, a better idea to go with another option.

So what’s wrong with using NPS?

  1. Requires a full windows license. Personally, I have an aversion to throwing away money, even if it’s somebody else’s money.
  2. Isn’t available on Server Core. This is a big one for me, as it conflicts with my preferred deployment method of using MDT or another provisioning tool to do the “push off,” let the system install, and configure the rest through Server Manager on a remote system.
  3. Can only really process one transaction at a time. While this is only really a problem on large deployments, it can cause really weird problems sometimes.
  4. Requires updating and patching a Windows box.

Okay, so that’s the negatives of it. But let’s talk about what it’s good for:

  1. It’s easy. A reasonably competent technician can throw one up in about half an hour
  2. It works okay. For most cases, it’s about enough.
  3. It can do just about everything. It can’t do it all extremely well, but it’s certainly able to get the job done.

The biggest reason to use it is indeed point number 1. It’s easy. The way that I’m about to show is very very hard. So please keep that in mind, if you want an easy system that works okay, just use NPS.

Authentication with FreeRadius

Yep. You knew it was coming… But if you’re not familiar with it, their own website has a very good introduction to the system and why it’s so widely used.

Here’s why FreeRadius is better than NPS:

  1. It’s free! It’s even in the name! The only thing it costs is your time.
  2. It’s multithreaded, so it can actually process more than one transaction at a time.
  3. It uses far less memory, CPU, takes no time at all to update, and most importantly…
  4. Uses not one single CAL. Since it’s free under the GPL, there is absolutely no license expense associated with the system, whether it’s being used to authenticate a single device or thousands.

Of course, it doesn’t have to be done in the very basic vanilla way, there are plenty of nice front ends and GUIs for it. Another open source project, PacketFence provides a full network access control server suite along with a great web interface for FreeRadius.

Integrating with Active Directory

This is a big one. Users expect to have a single set of credentials that follow them to all corners of the network, and beyond. To give them the ability to log into the Wi-Fi or VPNs with these credentials is not only a great convenience, it’s a necessity for security and administrative overhead.

As always, there are lots and lots of ways to get the job done, and I’m certainly not going to say that my way is the best. It’s a way and that’s all.

The general idea is to use NTLM and Kerberos to securely communicate between the Radius server and Active Directory, and then use PEAP/MSCHAPv2 to communicate between the client and the Radius server. This requires a few dependencies on the Linux server as well as some basic setup within Active Directory. For this example, let’s use the tried and true Winbind method. There are others, but this is fully supported by FreeRadius.

After Winbind, Samba, and Kerberos dependencies are installed, the config files should look something like this:


    workgroup = EXAMPLE
    security = ads
    winbind use default domain = no
    realm = AD.EXAMPLE.COM
    password server = *


    default_realm = AD.EXAMPLE.COM
    dns_lookup_realm = true
    dns_lookup_kdc = true

        kdc = DC1.AD.EXAMPLE.COM:88
        kdc = DC2.AD.EXAMPLE.COM:88
        admin_server = DC1.AD.EXAMPLE.COM:749
        default_domain =

[domain_realm] = AD.EXAMPLE.COM = AD.EXAMPLE.COM

    profile = /var/kerberos/krb5kdc/kdc.conf

At this point, we should be able to test that NTLM is able to successfully authenticate users:

ntlm_auth --request-nt-key --domain=AD.EXAMPLE.COM --username=testuser

Certificate requirements for PEAP

One of the most important elements of MSCHAPv2 is the use of TLS certificates.

While it is possible to just use the snakeoil certificates built into OpenSSL, I think it’s a much better idea to use a certificate either issued by your own internal certificate authority, or one issued by a public trusted authority. In this demonstration, I’ll create a certificate signing request and issue a certificate from a Windows 2016 cert authority.

$ openssl genrsa -out freeradius.key 2048
$ openssl req -new -sha256 -key freeradius.key -out freeradius.csr

This certificate should have the common name of the server as the common name of the certificate. I have tried using wildcard certs in the past for this and Windows 10 clients were unable to successfully join the network.

Once the request is created, the .csr file is taken to a secured management workstation to issue the certificate.

certreq.exe -submit -attrib "CertificateTemplate:WebServer" freeradius.csr freeradius.cer

Now that we have a certificate ready to go, we can take it back to the freeradius server and stick the cert files where they need to go:

$ sudo cp ~/freeradius.cer /etc/ssl/certs/
$ sudo cp ~/freeradius.key /etc/ssl/private/

Note that if using a Windows Active Directory Certificate Services authority, the CA certificate will also have to be trusted by server. In my case, it looks like this:

$ sudo cp ~/example-internal.cer /usr/local/share/ca-certificates/
$ sudo update-ca-certificates --fresh

Now that we have all the PKI requirements taken care of, let’s get FreeRadius installed.

FreeRadius Server Configuration

Depending on the distribution used, the name for the package may change. On Ubuntu 18.04 LTS, it’s simply freeradius.

$ sudo apt install freeradius

First, the service is configured to use basic MSCHAP authentication:


winbind_username = "%{mschap:User-Name}"
winbind_domain = "%{mschap:NT-Domain}"
with_ntdomain_hack = yes
ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%
{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Respo
nse}:-00} --domain=%{mschap:NT-Domain}"

Next, the more advanced EAP parameters can bet set such that MSCHAP can make use of PEAP. Also note that this configuration moves the certificates to the directory


tls-config tls-common { 
    private_key_file    = ${certdir}/freeradius.key
    certificate_file    = ${certdir}/freeradius.cer
    ca_file             = ${certdir}/example-internal.cer
eap {
    default_eap_type = peap

Radius Client configuration

Depending on the environment, there may be a single radius client, or several. Generally, controller based wireless solutions will have a single appliance or a highly available pair. In any case, each will need to. be defined in the FreeRadius client configuration file.

client {
        secret          = 492f5835-b922-4e2d-adea-5acc9a5a3ce1
        shortname       = wireless-controller   
        nastype         = cisco

Testing the Radius server

Before trying integrate with the radius client, it’s a good practice to test the radius server itself. By default, FreeRadius will accept connections from itself with the pre-shared key, testing123.

$ radtest -t mschap testuser testpassword 0 testing123

Unfortunately, this only tests the functionality of MSCHAP. To test PEAP/MSCHAPv2, some additional tinkering is required.

Testing MSCHAPv2

Unfortunately, there is no built in test for MSCHAPv2 within FreeRadius. For this, it is required to build the eapol_test program from source (part of the wpa_supplicant tooling). I usually do this on a testing server or workstation, simply to keep the amount of installed binaries on my production gear to a minimum.

Luckily, Eduroam has created some tooling to install eapol_test on a system, which is available from the FreeRadius documentation, as well as the Github repository directly.

Once installed and configured, it can be used to test either a remote or local FreeRadius server’s PEAP authentication.

$ wpa_supplicant/eapol_test -c eapol.conf -a -p1812 -s testing123 -r1

The -v or -vv flags can also be used for more verbose output, which is very helpful in pinpointing exactly why the server might not be working as expected. For example, the test client might not trust the CA certificate when using Active Directory certificate services. It’s also possible that the server is expecting usernames or passwords in a different format, so using verbose output and the FreeRadius logs to debug is invaluable.

If it all comes up green, congratulations on the working FreeRadius server!


Though more work initially, FreeRadius is a much more stable and reliable alternative to Microsoft NPS. Not only does it use far less compute and storage resources, it’s a free, open source solution that doesn’t dip into the Windows Server licenses or CALs.