Saturday, July 23, 2011

Exploring IIS7

While working on URLRewriteModule to route all HTTP requests to HTTPS. The very first solution that came to my mind was to develop an 'HttpModule' to handle all the redirection stuff. For this I wrote an custom HttpModule in C#.


//Inside HttpModule
public void OnBeginRequest(Object sender, EventArgs e)
{
   HttpApplication HttpApp = (HttpApplication)sender;
   string HttpUrl = HttpApp.Request.Url.ToString();
   if (!IsSecureRequest(HttpApp.Request)))
   {
     HttpUrl = HttpUrl.Replace("http:", "https:");
     HttpApp.Response.Redirect(HttpUrl.ToString(), true); 
     HttpApp.Response.End();
   }
}

private static bool IsSecureRequest(HttpRequest request)
{
   bool HTTPSServerVar;
   bool RequestIsSecure;

   HTTPSServerVar = String.Compare(request.ServerVariables["HTTPS"], "on", true) == 0;
   RequestIsSecure = request.IsSecureConnection;

   return (HTTPSServerVar | RequestIsSecure);
}

//Web.Config changes

<system.webServer>
<modules>
<add name="urlrewriter" type="HTTP_TO_HTTPS.redir" />
</modules>
</system.webServer>


After testing the solution I was about to deploy it to staging server. So as to avoid pitfalls I rang up our solution architect to get inputs on, performance and security related stuff on my custom HttpModule. His feedback almost made me to scrap my custom HttpModule, the reason being Microsoft had come up with a URLRewrite module for IIS which could be downloaded and installed on an IIS machine. Moreover this module delivers the same functionality which I was trying to implement using custom HttpModule. While the best thing with Microsoft URLRewrite module is that, you could achieve HTTP to HTTPS redirection just by adding rule entries to your applications web.config file. Here's how to get this done.

<rule name="HTTP to HTTPS redirect" stopProcessing="true">
  <match url="(.*)" />
  <conditions>
    <add input="{HTTPS}" pattern="off" ignoreCase="true" />
  </conditions>
  <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>


Exploring IIS 6/7 Request Pipeline:
Out of curiosity I decided to dig into the internals on how IIS6/7 hands HTTPS requests. Sometime back I heard that IIS is handling HTTP requests at the kernel level. After going through MSDN I was amazed to find that, with IIS 7 the way HTTPS requests were handled where completely revamped when compared with IIS 6. Let me first show you how SSL requests were handled in IIS 6.

 IIS 6 - HTTPS Request\Response pipeline:
1. Encrypted request received from client by the OS. (Kernel Mode)
2. A kernel mode driver HTTP.SYS accepts the encrypted request. (Kernel Mode)
3. HTTP.SYS passes over the encrypted request to HTTPFilter to decrypt. (User Mode)
4. HTTPFilter passes the decrypted request back to HTTP.SYS. (Kernel Mode)
5. HTTP.SYS forwards the decrypted request to IIS->W3WP.exe (User Mode)
6. HTTP.SYS receives the processed response comes back from IIS->W3WP.exe (Kernel Mode)
7. HTTP.SYS passes on the response to HTTPFilter for encrypting (User Mode)
8. HTTP.SYS receives the encrypted response from HTTPFilter (Kernel Mode)
9. HTTP.SYS sends out the encrypted response back to client (Kernel Mode)


In the above HTTPS request processing you could see that, a context switch is happening between the kernel mode(HTTP.sys) and user mode(HTTPFilter  i.e.   HTTP SSL windows service) for decrypting and encrypting requests. Which is  very expensive and could lead to poor performance under high loads. So as get this resolved, IIS 7 had taken a new approach while handling SSL requests.


 IIS 7 - SSL Request\Response Pipeline:
1. Encrypted request received from client by the OS. (Kernel Mode)
2. A kernel mode driver HTTP.SYS accepts the encrypted request. (Kernel Mode)
3. HTTP.SYS decrypts the request using SChannel. (Kernel Mode)
4. HTTP.SYS forwards the decrypted request to IIS->W3WP.exe (User Mode)
5. HTTP.SYS receives the processed response comes back from IIS->W3WP.exe (Kernel Mode)
6. HTTP.SYS encrypts the response using SChannel. (Kernel Mode)
7. HTTP.SYS sends out the encrypted response back to client (Kernel Mode)


Here you could see that the context switching for request\response encryption is now taken care of in the Kernel Mode itself using SChannel (Secure Channel). This makes IIS 7 more robust when it comes to serving pages under heavy load.


No comments: