Whilst working at a client doing some performance testing of an intranet, web-based, application we came across a little documented way to improve the network performance of the application if the web server is running IIS 6.0 on the Windows Server 2003 platform.
When the IIS 6.0 web server uses Windows Integrated authentication to log users onto a web application it goes through the following process, which is different to how it behaved on IIS 4.0, IIS 5.0 and IIS 5.1 (the versions that run on Windows NT 4.0, Windows 2000 and Windows XP):
- Client connects to the web server with an anonymous connection for the first object required.
- The web server rejects the connection with a 401 status message, which means that authentication is required.
- The client sends the request for the page to the server again, along with the current authentication information. The format of this authentication will differ based on whether NTLM or Kerberos is being used.
- Server responds with a 200 status indicating success and the object is transferred from the server to the client.
- So far nothing has changed in IIS 6.0 compared to the earlier versions of the software, but now the client makes the request for the second object (maybe a graphic within the page, or a second page on the same server). This second request, even if it is across the same HTTP session as the first, will be seen by the server as an anonymous request and it will be rejected with a 401 status message. In earlier versions of IIS this second (and subsequent requests on the same HTTP connection) were treated as being authenticated because the first object request was successfully authenticated.
This can be seen using the following information from an IIS 6.0 log file that was generated by a web browser making a GET request for four pages called auth1.htm through to auth4.htm.
cs-uri-stem cs-username sc-status sc-bytes cs-bytes /auth1.htm - 401 1872 516 /auth1.htm DOMAIN\user 200 509 2307 /auth2.htm - 401 1872 557 /auth2.htm DOMAIN\user 200 510 2348 /auth3.htm - 401 1872 557 /auth3.htm DOMAIN\user 200 510 2348 /auth4.htm - 401 1872 557 /auth4.htm DOMAIN\user 200 510 2348
The client makes a request for the page auth1.htm. This page is only available to a user via Windows Integrated authentication and so the request is seen as rejected with a 401 status. The second line shows the successful request for the same page and the fact that a Windows domain account was used to authenticate the request. From that point on, each request can be seen first as an authentication failure and then a success. This means additional round trips to the web server, and longer page load times – especially to web servers that are across low latency WAN connections. For example, the above log data shows that the total bytes sent and received by the web server (the sum of the sc-bytes and the cs-bytes columns) is 21065 bytes. We will compare this value to one where the IIS 6.0 server has had performance changes made to it later in this article.
IIS 4.0, IIS 5.0 and IIS 5.1 worked by allowing all subsequent requests for objects over a single HTTP session that had already been authenticated to use the authentication information of the first successful request. With the increase in security that is part of IIS 6.0 this potential security hole has been closed – it might be possible to take over another session and become authenticated with the credentials of that previous session. This security improvement though, as with many security changes, decreases performance by an increases the number of round trips to the server and the bytes transferred on the network. If the risk is considered unlikely within your environment and users connect to the web server from remote locations then you can set the IIS metabase setting AuthPersistSingleRequest to false. This means that the IIS 6.0 web server acts in terms of authentication persistence like an IIS 5.0 web server.
The two metabase keys that need to be set are:
NTAuthenticationProviders can be set at the web service or web site level and AuthPersistSingleRequest can be set at the web service, web site, virtual or real directory or at the file level.
To set these two metabase values open a command prompt, change to the \inetpub\adminscripts folder and run each of the following commands:
- cscript adsutil.vbs SET w3svc/1/NTAuthenticationProviders “NTLM”
- cscript adsutil.vbs SET w3svc/1/AuthPersistSingleRequest FALSE
The “1” in both the above commands will cause the property to be set on the Default Web Site. Change “1” to affect another web site or remove “1/” from the command to affect the entire server.
Once the two commands have been executed enter the following to ensure that they have run correctly:
- cscript adsutil.vbs GET w3svc/1/NTAuthenticationProviders
- cscript adsutil.vbs GET w3svc/1/AuthPersistSingleRequest
Finally run IISRESET from the command line to restart the web server.
The following data from an IIS 6.0 log file shows the same sequence of GET requests as described above after the NTAuthenticationProviders value has been set to NTLM and the AuthPersistSingleRequest value set to false.
cs-uri-stem cs-username sc-status sc-bytes cs-bytes /auth1.htm - 401 2043 622 /auth1.htm DOMAIN\user 200 259 774 /auth2.htm DOMAIN\user 200 260 557 /auth3.htm DOMAIN\user 200 260 557 /auth4.htm DOMAIN\user 200 260 557
This data can be compared to that above quite easily. First you can see that the number of round trips is just over half the number on an IIS 6.0 server in its default configuration, as only the first request fails with a 401 status message – the subsequent requests now use the authentication of the first request within the session rather than per request authentication. Secondly the total number of bytes required within the HTTP session to download these four objects is 6149 bytes. This is 29% of the bytes transferred under the default IIS 6.0 configuration.
Therefore, if you run web applications that use NTLM authentication and have high latency networks then you can generate significant improvements in page load time at the browser, and at the client I am working at we reduced page load times from their India offices to the USA servers from 18 seconds to less than 10 seconds.