NPS

As a commercial alternative to FreeRADIUS, Microsoft does a decent RADIUS implementation as part of their Network Policy Server. It scales well and you can install and configure it with a few simple commands or use the GUI. It’s much simpler than FreeRADIUS.

I’ve scaled to to thousands of requests per second and it’s proven to work well with Aruba APs. But I’ve also had issues with Unifi Access Points. So it’s not always the best answer. Though that wa circa 2018 and it’s probably better now.

Here, we’ll configure it with the minimum needed to process RADIUS requests from the VPN server.

Installation

If you haven’t already, log into your Windows server, add the NPS role and register it with the domain1, The Windows firewall will auto-config2.

In an administrative powershell window:

Install-WindowsFeature NPAS -IncludeManagementTools
netsh nps add registeredserver YOURDOMAIN YOURNPSSERVER

Configuration

NPS configuration has three parts; Who are my clients? When are they allowed to connect? and Should we give the end-user the thumbs up? This feels a little strange at times, but you get used to it.

Add A Client

The first step is to add the vpn server as a client3. The RADIUS server won’t even acknowledge your connection attempt unless it knows about you. In an admin powershell window:

# Add the client. Use the actual IP address to avoid Event ID 13 Errors
netsh nps add client name=<client name> address=<ip address> sharedsecret=<password>

Add A Connection Policy

The next component is a Connection Policy4. In practice, this is seldom used as anything other than a catch-all-allow-connect as the default policy shows. Though when in a federation, it determines how to route your connection. I.e. should your request be processed here, or should I proxy your request to an external server based on your ID.

Here, we add a very simple policy that looks at the IP and by default accepts the connection.

# Add a Connection Policy
#  The default connection policy is sufficient but let's add an explicit one.
#  Processing order doesn't work as documented. You must clear existing ones or
#  explicitly specify processing order.

netsh nps reset crp
netsh nps add crp name = "VPN Connection" conditionid = "0x100c" conditiondata = "SomeIpAddress"

Add A Network Policy

The last step is to add a Network Policy5. This determines if you are both Authentic and Allowed to connect. That’s an important point: the authorization decision is made at the RADIUS server, not the VPN server. You could in theory return a set of attributes to the VPN server. But in practice that’s not the approach that’s used6.

In this example we assume you have a group in AD to control access and looked up it’s SID.

# Add a Network Policy
netsh nps reset np
netsh nps add np
name = "Allow VPN Access"
conditionid = "0x1fb5" conditiondata = "S-1-5-21-1566005089-1651370962-3825839635-513" `
profileid = "0x100f" profiledata = "True"
profileid = "0x100a" profiledata = "1A000000000000000000000000000000"
profileid = "0x1009" profiledata = "0x5"

The Condition ID above isn’t documented but adding the condition from the GUI and issuing netsh nps show np reveals it. To see what attributes these profileid’s are setting, do a show np to see the desc.

Enterprise Authentication 802.1x

The traditional way of providing a name and password is with 802.1x. It’s done by chaining together a few protocols to get “PEAP-MS-CHAPv2”. This allows you transmit a name and password from the client to the RADIUS server without the AP in middle seeing it.

One of the things you need is a certificate with an extension that specifically allows for server authentication.

Let’s Encrypt works fine.

The Hard Way

If you want to go a different route, MS documentation identify that as Server Authentication purpose in Extended Key Usage (EKU) extensions. (The object identifier for Server Authentication is 1.3.6.1.5.5.7.3.1.) And the server certificate is configured with a required algorithm min value of RSA 2048. The Subject Alternative Name (SubjectAltName) extension, if used, must contain the DNS name of the server.

You can also do it the old way with MS’s cert req.

# Don't add the SAN as the provider will do tha in a web form usually
certreq -new radius.inf radius.csr 

certreq –accept radius.cer 
;----------------- request.inf ----------------- 
[Version] 
Signature="$Windows NT$" 

[NewRequest] 
;Change to your,country code, company name and common name 
Subject = "CN=radius.marietta.edu,OU=Information Technology,O=Marietta College,L=Marietta,S=Ohio,C=US,[email protected]" 
KeySpec = 1 
KeyLength = 2048 
Exportable = TRUE 
MachineKeySet = TRUE 
SMIME = False 
PrivateKeyArchive = FALSE 
UserProtected = FALSE 
UseExistingKeySet = FALSE 
ProviderName = "Microsoft RSA SChannel Cryptographic Provider" 
ProviderType = 12 
RequestType = PKCS10 
KeyUsage = 0xa0 

[EnhancedKeyUsageExtension] 
OID=1.3.6.1.5.5.7.3.1 ; this is for Server Authentication / Token Signing 
;-----------------------------------------------  

Operation

Performance Tuning

If you expect a lot of traffic you should increase the number of concurrent connection to AD so you don’t bottle-neck7. This is critical on a large install when you have more than a hundred authentications per second. (say, 10,000+ devices). This is unlikely for a VPN but wireless transaction can easily hit the limit.

# Edit the registry to increase the number of concurrent connections to AD
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters 5

Issues

When using with Unifi, if the communication between the authenticator (the AP) and the RADIUS server has any issues, the AP will give up after 3 tries and won’t try again. Packet captures make it seem like the they disagree on how to implement the protocol in some cases. This happened to about 1% of our APs a day.

In these cases - a reboot of the AP was the quick fix.

No such problems with FreeRADIUS.

References

You may notice we’re referring to older docs here. The most current don’t have the details from the older docs when it comes to the netsh commands.


Last modified March 25, 2026: Cert inclusion with NPS (c410d8e)