With the release of Netscaler 11 build 64.34, the requirements and configuration for NTLM authentication have changed.
In this blog post, I will take you through an example configuration where we’ll authenticate via Kerberos when internal on the network but fallback to NTLM when external and the users active directory is unreachable.
We will make things a little more interesting by doing single sign-on to the back-end resource using Kerberos Constrained Delegation.
I have found this particular configuration is something a lot of people struggle with, so hopefully this breakdown will be of benefit.
First things first , lets cover the requirements for this working example, you will need ….
- A load-balanced virtual server
- A back-end resource with “Windows Authentication” enabled and the correct providers set (Negotiate and NTLM)
- AAA vserver for authentication
- An authentication negotiate policy
- An authentication negotiate server
- A NTLM path URL
- A session policy for single sign on
- A kerberos account
- Some SPN’s
To better understand the full communication flow, I am showing the relevant packets from a packet capture.
First, the client issues a GET request for the target resource, which the LB responds to with a “401 Unauthorized.”
As the client is external to my network, it obviously cannot reach my Active Directory/Kerberos Distribution Center to request a ticket, so it responds saying it wants to authenticate using NTLM.
(Here is the same response at the header level)
Now for the clever part. The Netscaler will now send a GET request to the backend server defined in the “NTLM Path” and specify it wants to use NTLM authentication.
The backend server responds with an NTLM challenge that the netscaler forwards to the client. The client responds with its credentials, which are then sent back to the server and if successful, a “200 OK” is returned, the Netscaler treats this as a successful logon.
Our client has now successfully authenticated, but in this example (to make things a little more interesting), the target resource will now be requested using Kerberos Constrained Delegation (KCD).
Here are the config steps:
#create backend server using FQDN and then create service
add server GARY-DC gary-dc.garyslab.net (gary-dc is my target webserver)
add service gary-dc GARY-DC HTTP 80
#Add Negotiate authentication policy and action
add authentication negotiateAction administrator -domain garyslab.net -domainUser administrator -domainUserPasswd 8ad14a780a85….*truncated* -encrypted -encryptmethod ENCMTHD_3 -NTLMPath “http://192.168.0.1/index.html”
add authentication negotiatePolicy Kerberos-auth-policy ns_true administrator
#Create you kerberos account and session policy for SSO
add aaa kcdAccount KCD -realmStr GARYSLAB.NET -delegatedUser kerberos -kcdPassword 4924…*truncated* -encrypted -encryptmethod ENCMTHD_3 -userRealm GARYSLAB.NET ** Please note, in case of multiple domains, we need a kcdAccount for each client realm to override client’s domain. Alternatively, ssoDomain setting of session policy can be used too.**
add tm sessionAction mysso -SSO ON -ssoDomain garyslab -kcdAccount KCD
add tm sessionPolicy sso_session_pol ns_true mysso
#Create AAA vserver
add authentication vserver aaa_vserver SSL 126.96.36.199 443 -AuthenticationDomain aaa.garyslab.net
#bind the auth and SSO policies
bind authentication vserver aaa_vserver -policy Kerberos-auth-policy -priority 100
bind authentication vserver aaa_vserver -policy sso_session_pol -priority 100
#Create the LB vserver and bind the AAA vserver
add lb vserver LB_HTTP HTTP 188.8.131.52 80 -persistenceType NONE -lbMethod ROUNDROBIN -cltTimeout 180 -authn401 ON -authnVsName aaa_vserver
Some important points to remember
- Make sure to add your services using FQDN and not IP
- Set the relevant SPNs , in this lab I set them for my LB and for my AAA
- This is done on your AD using “setspn -A host\lb.garyslab.net garyslab\kerberos” and “setspn -A http\lb.garyslab.net garyslab\kerberos” , do this for both the LB FQDN and the AAA fQDN, failure to do this will result in principal unknown errors in a trace. (garyslab\kerberos is my delegated user)
In setting this up, I ran into two issues that I would like to address here and hopefully save you from a few days of frustration.
Pay special attention to the NTLM path **it must have a full FQDN and PATH , ie http://FQDN/PATH.html** , initially I was only using the http://FQDN but this was resulting in a “Http/1.1 Internal Server Error 43550” error upon logging in.
Secondly, be sure to add a service principal name for the AAA itself, not just the LB FQDN. I could see a “principal unknown” error in a trace after a failed login attempt.
In setting up the requirements for the KCD part of this demonstration, I performed the following steps.
In AD create an account for performing the actual delegation, in my case I named this account “kerberos”, under the delegation tab set the delegation to “Trust this user for delegation to the specified services only” and “Use any authentication protocol”. Then add the service that you are load balancing, in my case it is my IIS server so I added the server GARY-DC.GARYSLAB.NET with the service type as HTTP
Set the SPNs for the external FQDN of the LB and the AAA as described earlier.
Now, on the Netscaler add this newly created account to your “KCD Accounts”, you can use keytab but I find it easier to just define the user. This is the account that you will specify in your SSO policy.
And now you should be all set ….