Recently came across a small issue when using back-end IIS instances with my ELB and the fact that Windows Auth(NTLM) will not work.

Normal behavior

In a normal NTLM connection. The client request will attempt to negotiate (NTLMSSP_NEGOTIATE) during the initial connection. The server will send back a NTLMSSP_CHALLENGE (401 Unauthorized) asking the user to authorize. The client will send a NTLMSSP_AUTH with the authorized user.
The IIS server will send back a 200 OK and the connection will be authorized using NTLM.


Client -> HTTP GET, NTLMSSP_NEGOTIATE
IIS -> HTTP 401 Unauthorized, NTLMSSP_CHALLENGE
Client -> HTTP GET, NTLMSSP_AUTH
IIS -> HTTP 200 OK

This was a test directly to one of my back-end IIS instances bypassing the ELB. Working connection

ELB Behavior

When more than one IIS instance is behind the ELB the ELB treats this NTLM connection as two separate connections. When testing this on my instances I can see the NTLMSSP_NEGOTIATE come in on one back-end but the NTLMSSP_AUTH is sent by the other back-end instance.


(connection 1 -> IIS Instance 1)
Client -> HTTP GET, NTLMSSP_NEGOTIATE
IIS -> HTTP 401 Unauthorized, NTLMSSP_CHALLENGE

Negotiation

Auth


(connection 2 -> IIS Instance 2)
Client -> HTTP, NTLMSSP_AUTH
IIS -> HTTP 401 Unauthorized :because it did not originate from the first connection.

So WTH

Due to the design of the NTLM protocol. Pass-through authentication will not work with Layer 7-HTTP proxies. This is because the NTLM protocol uses a connection oriented authentication flow. Reverse proxies not aware of NTLM will distribute the HTTP requests they are proxying for a client attempting to use NTLM over HTTP across multiple TCP connections to the back-end instances. This process of course breaks the NTLM flow resulting in failed authentication and the client is presented with constantly being asked to re-authenticate.

Work-arounds


Enable stickiness
Use a TCP listener.
Set up Physical Path Credentials basically a pre-authentication in IIS.
Use HAProxy

Stickiness - Edit

So I spoke to soon. Testing this with curl and enabling stickiness on the ELB it does work properly. So if I get the cookie with curl -v then pass it with -b it works.


curl -v –ntlm –user evan:mypass http://myelb.us-west-2.elb.amazonaws.com/
curl -v –ntlm –user evan:mypass http://myelb.us-west-2.elb.amazonaws.com/ -b “AWSELB=thecookiereturnedfromGET”

Some helpful links that discuss the same issue:


https://msdn.microsoft.com/en-us/library/dd925287%28v=office.12%29.aspx
https://github.com/nodejitsu/node-http-proxy/issues/362
https://commscentral.net/tech/?post=52