Forum Discussion

Miron_du_Plessi's avatar
Miron_du_Plessi
Icon for Nimbostratus rankNimbostratus
Nov 03, 2007

HTTP Redirect based on URI

Hi,

 

 

I have a webserver behind our LTM. Access to the webserver is working correctly when users use the full url of

 

 

https://remedy.xxx.net/arsys/home

 

 

however we are trying to ensure that they reach the correct webpage even if they type.

 

 

https://remedy or

 

https://remedy.xxx.net

 

 

However when they type this they are directed to the default apache page.

 

 

To do this on the load balancer instead of the webserver I thought that the following irules should solve the problem.

 

 

However it appears to have no effect, and im thinking that the problem may lie with the if statements. I did try and test if the redirect will work without the if statements which appeared to work obviously with errors as expected.

 

 

****************************************************

 

 

when HTTP_REQUEST {

 

set uri [HTTP::uri]

 

if { $uri ends_with "/remedy" } {

 

HTTP::redirect "https://remedy.xxx.net/arsys/home"

 

} elseif { $uri ends_with "/remedy.xxx.net" } {

 

HTTP::redirect "https://remedy.xxx.net/arsys/home"

 

}

 

}

 

 

****************************************************

 

 

 

when HTTP_REQUEST {

 

if { [HTTP::uri] ends_with "/remedy"} {

 

HTTP::redirect "https://remedy.xxx.net/arsys/home"

 

} elseif { [HTTP::uri] ends_with "/remedy.xxx.net"} {

 

HTTP::redirect "https://remedy.xxx.net/arsys/home"

 

}

 

}

 

 

I know there are a few topics already on this subject, which seem to suggest that it is quite easy.

 

 

Any ideas.

 

 

Regards

 

 

Miron

10 Replies

  • Hi Miron,

    You can add log statements to your rule and then tail the /var/log/ltm log file (tail -f /var/log/ltm) to see what values you're getting:

    
    when HTTP_REQUEST {
       log local0. "URI: [HTTP::uri]"
       if { $uri ends_with "/remedy" } {
          log local0. "URI: [HTTP::uri] matched /remedy check"
          HTTP::redirect "https://remedy.xxx.net/arsys/home"
       } elseif { $uri ends_with "/remedy.xxx.net" } {
          log local0. "URI: [HTTP::uri] matched /remedy.xxx.net check"
          HTTP::redirect "https://remedy.xxx.net/arsys/home"
       }
    }

    I think you're mixing up the Host header value and the URI that HTTP::uri returns. If a client requests https://test.example.com/path/to/file.ext, [HTTP::host] will return "test.example.com". [HTTP::uri] will return "/path/to/file.ext".

    You probably want to try something like this:

    
    when HTTP_REQUEST {
       log local0. "Host: [HTTP::host], URI: [HTTP::uri]"
       if { [string tolower [HTTP::host]] eq "remedy"} {
          log local0. "Host: [HTTP::host] matched remedy check"
          HTTP::redirect "https://remedy.xxx.net/arsys/home"
       } elseif { [string tolower [HTTP::host]] eq "remedy.xxx.net" } {
          log local0. "Host: [HTTP::host] matched remedy.xxx.net check"
          HTTP::redirect "https://remedy.xxx.net/arsys/home"
       }
    }

    Alternately, if you want to redirect any request to the VIP that's not made to remedy.xxx.net, you could just do a single test:

    
    when HTTP_REQUEST {
       log local0. "Host: [HTTP::host], URI: [HTTP::uri]"
       if { not ([string tolower [HTTP::host]] eq "remedy.xxx.net")} {
          log local0. "Host: [HTTP::host] didn't match remedy.xxx.net; redirecting."
          HTTP::redirect "https://remedy.xxx.net/arsys/home"
       }
    }

    Aaron
  • Aaron ,

     

     

    Thanks for the device ill try it out. Looks like ill have to include some statement that checks if the uri is null otherwise it would loop.

     

     

    Would this be a simple

     

     

    if { [string tolower [HTTP::host]] eq "remedy" AND [string tolower [HTTP::uri]] eq null} {

     

     

    Regards

     

     

    Miron
  • Aaron,

     

     

    Thanks I got it working,what looks like correctly.

     

    I couldnt use null so just Anded with "/" which seems to work.

     

     

    I will play with the logging which looks usefull.

     

     

    when HTTP_REQUEST {

     

    if { [string tolower [HTTP::host]] eq "remedy" and [string tolower [HTTP::uri]] eq "/" } {

     

    HTTP::redirect "https://remedy.xxx.net/arsys/home"

     

    } elseif { [string tolower [HTTP::host]] eq "remedy.xxx.net" and [string tolower [HTTP::uri]] eq "/"} {

     

    HTTP::redirect "https://remedy.xxx.net/arsys/home"

     

    }

     

    }
  • Regarding the null...

     

     

    Per the HTTP Spec, the URI must always at least be a slash "/". HTTP::uri can never be an empty string.

     

     

    -Joe
  • Joe/Aaron,

     

     

    Thanks for the help.

     

    I have one small issue now. if a user just types in the following:

     

     

    http://10.100.100.100

     

    https://10.100.100.100

     

    http://remedy

     

    https://remedy

     

     

    They are presented with a certificate error(btw the 10.100.100.100 is the remedy server)

     

    but can click okay to accept cert and proceed.

     

    I presume this is because the client is expecting a different certificate. We currently use a wildcard cert

     

    for the *.xxx.net domain

     

     

    Do you have any advice on how to resolve this.

     

     

    Miron

     

  • If the client makes a request to the VIP address over HTTPS with a host header value that doesn't match the cert's CN, they'll get the browser prompt to accept the mismatched cert. There isn't anything you can do to eliminate that.

     

     

    You can try to eliminate the scnearios whereby a user would make a request to the VIP via HTTPS with the wrong Host header value though.

     

     

    If the client is first making a request via HTTP to the VIP address, you could redirect them to the correct host via HTTPS (https://remedy.xxx.net). They wouldn't get the cert warning then.

     

     

    Aaron
  • Aaron,

     

     

    So if I can eliminate the the cert warning coming up for:

     

     

    http://remedy

     

    http://10.100.100.100

     

     

    That would be usefull

     

     

    On my standard VIP for port 80 I have the following I rule.

     

    you will notice that I tried to include the third statement instead of the secondhowever this did not work. In fact you couldnt access the webpage at all if you included the third statement instead of the second one

     

     

    when HTTP_Request{

     

    HTTP::redirect https://[getfield [HTTP::host] "." 1][HTTP::uri]

     

    HTTP::redirect "https://remedy.xxx.net/arsys/home"

     

     

    Miron
  • The second redirect should work:

    
    when HTTP_Request{
       HTTP::redirect "https://remedy.xxx.net/arsys/home"
    }

    Do you have the rule assigned to an HTTP virtual server on the same IP as the https virtual server? Do you see any errors in /var/log/ltm?

    Can you use a browser plugin to LiveHttpHeaders for Firefox or HTTPwatch for IE to see what response is coming back from the VIP? Else, you can use this Codeshare example to log the headers to /var/log/ltm. (Click here)

    Aaron
  • Aaron,

     

     

    I found the problem in the rule I submitted. As I had the following when i was

     

     

    when HTTP_Request{

     

    HTTP::redirect https://[getfield [HTTP::host] "." 1][HTTP::uri]

     

    HTTP::redirect "https://remedy.xxx.net/arsys/home"

     

    }

     

     

    This was not running the 3rd statement possibly because it reads it similar to java (ie only the first statement)

     

     

    Anyways that worked well to redirect , however after that the login did not work and the website seemed to be looping the client.

     

     

    I have added the Firefox live headers output from the two tests

     

     

    Test 1 - Redirect.txt (Login Fails)

     

     

    when HTTP_Request{

     

    HTTP::redirect "https://remedy.xxx.net/arsys/home"

     

    HTTP::redirect https://[getfield [HTTP::host] "." 1][HTTP::uri]

     

    }

     

     

    Test 2 - NoRedirect.txt (Login Works)

     

     

    when HTTP_Request{

     

    HTTP::redirect https://[getfield [HTTP::host] "." 1][HTTP::uri]

     

    HTTP::redirect "https://remedy.xxx.net/arsys/home"

     

    }

     

     

    Besides for this problem it looks like it may be beneficial to capture the 302 from the server and replace the http with https. Might just clean up the communication.

     

     

    After that I can look at protecting the webserver identity.

     

     

    Miron
  • Jo_Anglin_5148's avatar
    Jo_Anglin_5148
    Historic F5 Account
    Miron,

     

     

    Thanks for sharing your corrected Irule. It worked wonderful for me too.