Forum Discussion

CraigM_17826's avatar
CraigM_17826
Icon for Altostratus rankAltostratus
Feb 03, 2010

Odd issue with pools and a redirect

Hi all,

 

 

Sorry if this is a bit of a rambling post, but it's quite an odd issue I am seeing and I wanted to explain what we are doing and why. Hopefully it's not too confusing.

 

 

One of the current tasks I have been assigned to modify an existing rule so that when the URI contains some specific text, a server side redirect to a external URL occurs so that the content displayed is actually comming from an external server but the clientside URL must still show our corporate URL. For example

 

 

If the user enters https://www.amce.com.au then the content comes from our web servers. If they enter https://www.acme.com.au/site1 then the content displayed comes from the external web server but the URL presented to the user is still https://www.acme.com.au/site1

 

 

In a nutshell part of our website is being hosted elsewhere but my company doesn't want the end users to be aware of this, they want it to appear to be comming from us.

 

 

Now I thought the easiest way would be to create a pool with a single node that resolves to the external server and then in the iRule check thhe URI for the matching text and then use that pool.

 

 

The external server is running Oracle Application Server with a self signed SSL cert.

 

 

For the Pool I created a node for the remote server and specified the operating port as 443. I also installed the companys CA for their self signed cert so the BigIP would trust their certificate.

 

 

In the iRule I have

 

 

when HTTP_Request {

 

 

if { [string tolower [HTTP::uri]] starts_with "/site1" } {

 

pool "External_Site1"

 

return

 

}

 

 

when SERVER_CONNECTED {

 

if { [string tolower [LB::server pool]] eq "External_Site1" } {

 

SSL::profile "External_Site1"

 

} else {

 

SSL::disable serverside

 

}

 

}

 

 

Now what is happening is that the remote server is also attempting to load balance their site and for resaons out of my control it is issuing a client side redirect to their backend servers on port 82. I don't know why this is occuring and neither do they, but apart from the obvious issues this will cause, one odd thing is that even though they claim the redirects to their backend servers are over HTTP to port 82, the BigIP seems to be enforcing a HTTPS connection for the redirect. This is what I see with HTTPWatch under IE if I go direct to their website, bypassing our BigIP

 

 

redirect to http://backendserver1.com.au:82/site1

 

 

If I go to the our bigip URL then I see

 

 

redirect to https://backendserver1.com.au:82/site1

 

 

and then the error ERROR_INTERNET_SECURITY_CHANNEL_ERROR (this error is from HTTPWatch) which I gather is because the BigIP is attempting a SSL connection on port 82 and on a server that doesn't have a SSL cert installed.

 

 

My question is why is the redirect being forced to HTTPS by the BigIP and is there a way to stop this?

 

 

Any comments welcome.

 

 

Regards

 

 

Craig

 

7 Replies

  • Hi Craig,

    I think you have rewrite redirects enabled on the HTTP profile associated with the VIP.

    If you want to confirm what LTM gets in the server response headers you could use a debug logging iRule like this:

    http://devcentral.f5.com/wiki/default.aspx/iRules/LogHttpHeaders.html

    Also, you can make the iRule slightly more efficient by tracking the serverside SSL requirement with a variable instead of the pool name:

     
     when HTTP_REQUEST {  
      
        if { [string tolower [HTTP::uri]] starts_with "/site1" } {  
           pool "External_Site1" 
           set usessl 1 
        } else { 
           set usessl 0 
        } 
     } 
     when SERVER_CONNECTED {  
        if { $usessl } {  
           SSL::profile "External_Site1"  
        } else {  
           SSL::disable serverside  
        }  
     }  
     

    Aaron
  • Also note that if you want LTM to rewrite the server redirects from http://backendserver1.com.au:82/site1 to /site1 (ie, make the redirect a local reference without the protocol, host or port), you could check for a redirect using HTTP::is_redirect and check the Location header value for backendserver1 or some other incorrect value:

     
     when HTTP_RESPONSE { 
      
         Check if response is a redirect 
        if {[HTTP::is_redirect]}{ 
      
            Check if Location header has :82/ in it 
           if {[HTTP::header Location] contains ":[TCP::server_port]/"}{ 
      
               Rewrite the location header. Use getfield to split the header value on the string ":82/" 
       where 82 is the server port.  Prepend a forward slash as it will be removed by getfield 
      HTTP::header replace Location "/[getfield [HTTP::header Location] ":[TCP::server_port]/" 2]" 
           } 
        } 
     } 
     

    The browser will use the original protocol and host to generate the next request to the local Location URI.

    Aaron
  • Hi Aaron,

     

     

    once again thanks for your replies. I'll give them a shot but in all honesty I hope the people running the servers at the other end can get their load balancing working properly. If they can get rid of their redirects then I don't think I'll have a problem.

     

     

    ta

     

     

    Craig
  • Yes, the most efficient solution would be to fix the app. But it should be relatively simple to use an iRule to work around the problem in the meantime.

     

     

    Aaron
  • Hi Aaron,

     

     

    My appologies up front for what I am about to ask, but I'm stuck for time.

     

     

    The developers of this external site maintain they can't stop their redirects to a their specific base URL. So what happens is the client browser is honouring the redirects and navigating away from our URL. What I need is some iRule code that will allow me to detect these redirects and replace their base URL (external-server.acme.com.au) with our own (www.mycomp.com.au) so the end user always sees our base URL. The URI part is to remain unchanged. The port 82 dependancy has been removed which is one good thing, I'm just not sure of how to code for this. I'm using your example as a base but am not sure of what the HTTP::header replace statement should look like.

     

     

    This is what I have so far

     

     
     when HTTP_RESPONSE {  
       if {[HTTP::is_redirect]}{   
       if {[HTTP::header Location] contains "external-server.acme.com.au"}{   
          HTTP::header replace Location       
     

     

     

    which isn't much. I'm just not sure on how to construct the HTTP::header replace statement.

     

     

    Regards

     

     

    Craig

     

  • Hi Aaron,

    ok I think I have it, this is what I have done. I would appreciate your comments.

    Note to myself, learn to use the F5 wiki more often!

     
     when HTTP_RESPONSE { 
     if { [HTTP::is_redirect] } { 
        if { [HTTP::header Location] contains "external_server" } { 
            HTTP::header replace Location [string map -nocase {external_server our_server} [HTTP::header value Location]] 
       return    
        } 
      } 
     } 
     

    So far it seems to be working.

    Regards

    Craig
  • Hi Craig,

     

     

    Your rule looks good. Glad you figured it out.

     

     

    You don't need to use the return command unless there is code afterward in the same event. Return will just exit the current event of the current rule.

     

     

    Aaron