Fiddler SNI problem

8 posts, 0 answers
  1. Simon
    Simon avatar
    5 posts
    Member since:
    Oct 2014

    Posted 02 Oct 2014 Link to this post

    Hi,

    I have two websites, 1.com and 2.com, running as virtual hosts on the same IP address.  Both sites are SSL, so the SSL extension Server Name Indication (SNI) is used to indicate which host a connection is requesting.  The test instances for these sites are set up with the same names as production but on a different IP address.  To access the test sites without hacking my hosts file I use fiddler with a customized CustomRules.js to override the host the requests are sent to.

    static function OnBeforeRequest(oSession: Session)
    {
      if (oSession.HostnameIs("1.com") ) {
        oSession.bypassGateway = true;
        oSession["x-overrideHost"] = "10.0.0.1:" + oSession.port;

      }
      if (oSession.HostnameIs("2.com") && oSession.uriContains("/blah/"))  {
        oSession.bypassGateway = true;
        oSession["x-overrideHost"] = "10.0.0.1:" + oSession.port;
      }



    This works perfectly when I enable one or the other redirection at a time.  However, there is a page on 1.com which contains iframes which loads content from both sites and when I enable both redirects I get continuous "400 Bad Response" errors in the iframes for content from 2.com and the web server logs the error "Hostname 1.com provided via SNI and hostname 2.com provided via HTTP are different"

    If I remove the test << && oSession.uriContains("/blah/" >> from the fiddler script, content loads most of the time from 2.com, but there are still sporadic 400 bad response errors.

    Can anybody help please?

    thanx
    Simon

  2. Eric Lawrence
    Admin
    Eric Lawrence avatar
    833 posts

    Posted 03 Oct 2014 Link to this post

    Hi, Simon--

    You can simplify your code a bit like so:

      if (oSession.HostnameIs("1.com") ||
         (oSession.HostnameIs("2.com") && oSession.uriContains("/blah/"))) 
      {
          oSession.bypassGateway = true;
          oSession["x-overrideHostname"] = "10.0.0.1";
      }

    Could you send me a Fiddler SAZ file demonstrating this problem, using the Help > Send Feedback option in Fiddler?

    thanks a bunch!

    Regards,
    Eric Lawrence
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. Simon
    Simon avatar
    5 posts
    Member since:
    Oct 2014

    Posted 06 Oct 2014 in reply to Eric Lawrence Link to this post

    Hi Eric,

    Sorry for the delay in replying, we just had a long weekend here :-)

    There's actually more logic around those two If statements, hence why they are separated out as they are, I just minimized the code as far as possible whilst still reproducing the problem for the test case.  I did try your suggested code and it still causes the 400 Bad Request response from the web server.

    Yes, I can send you a saz file but would prefer it to remain private.  What the best way to send it to you directly?

    thanx
    Simon
  4. Simon
    Simon avatar
    5 posts
    Member since:
    Oct 2014

    Posted 06 Oct 2014 in reply to Simon Link to this post

    Hi Eric,

    I've done some more investigating and run a wireshark trace at the same time as fiddler. Whilst wireshark can't decrypt the SSL traffic it does help to show what's going on.

    Fiddler captures 2x HTTP CONNECTs (establishing the SSL tunnel) to 1.com, 1x HTTP CONNECT to 2.com, 6x https requests to 1.com and 1x https request to 2.com.  The solitary connection to 2.com is a POST request with approx 5K of POST data.

    Wireshark captures 3x TCP connections to the shared IP address.  Two with an SNI of 1.com and the third with an SNI of 2.com.  Looking at the pattern of the data sent and received on each connection I can work out that the first TCP connection has 5 requests and responses in it and the 2nd TCP connect has two requests and responses. Of the requests in the first connect, the fifth request sends a lot of data to the server, approx 5.5K worth - significantly more than any of the other requests.  This would indicate the POST request for 2.com was sent through the tunnel established to 1.com, thus resulting in the Bad Request response.

    The 3rd TCP connection only appears to have one request & response in it, with the request being rather small (286 bytes) and the response extremely small (47 bytes).  My best guess is that the request is a "null" request to shutdown the connection that wound up not being used for an actual request.

    To test further, I disabled Keep Alives on the web server and the requests worked as expected and did not generate the 400 Bad Response for the request to 2.com.


    My best guess as to what's happening is that Fiddler is utilizing Keep Alives and sending multiple requests down the same connection (as expected).  When the request comes in for 2.com, the Fiddler script redirects 2.com to the shared IP address, Fiddler determines it already has a connection open to that IP address and decides to reuse that connection, the only problem is that the connection it uses is for a different hostname and the error results.

    I'm further guessing that the time taken to execute the extra test [&& oSession.uriContains("/blah/")] allows the requests on the first TCP connection to complete such that the connection is now idle and can be reused for the next request which Fiddler then reuses once it's ready to forward the request for 2.com onto the server. Removing the extra test speeds up Fiddler's processing such that the first TCP connection is still busy when fiddler wants to forward the 2.com request and it has to use another connection, and in those instances it usually winds up being the third TCP connection which is the correct one for 2.com.

    Does this make sense?


    Also, sorry, I just reread your response and noticed that you mentioned how to send the saz file through to you.  I've now sent the saz file.

    thanx
    Simon
  5. Eric Lawrence
    Admin
    Eric Lawrence avatar
    833 posts

    Posted 07 Oct 2014 Link to this post

    Thanks for the capture.

    Your theory is likely correct.

    For the moment, you might try adding the following to the OnPeekAtResponseHeaders block: 

      if (oSession.HostnameIs("1.com") ||
         (oSession.HostnameIs("2.com") && oSession.uriContains("/blah/"))) 
      {
           if ((null != oSession.oResponse) &&
               (null != oSession.oResponse.pipeServer))
       
           {      
              oSession.oResponse.pipeServer.ReusePolicy = Fiddler.PipeReusePolicy.MarriedToClientPipe;
           }
      }


    Regards,
    Eric Lawrence
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  6. Simon
    Simon avatar
    5 posts
    Member since:
    Oct 2014

    Posted 07 Oct 2014 in reply to Eric Lawrence Link to this post

    Thanx for the workaround, Eric.  That seems to have done the trick!

    Thanx for you help
    Simon
  7. Eric Lawrence
    Admin
    Eric Lawrence avatar
    833 posts

    Posted 08 Oct 2014 Link to this post

    Simon-- Thanks for reporting this bug and confirming the workaround. I hope to fix the problem for the next build.

    Regards,
    Eric Lawrence
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  8. Simon
    Simon avatar
    5 posts
    Member since:
    Oct 2014

    Posted 08 Oct 2014 in reply to Eric Lawrence Link to this post

    No probs, happy to help.  And thank you for taking my problem report seriously and the fast action on it, something that's not as common as it can be these days :-(

    thanx
    Simon
Back to Top