Forum Discussion

Matt_70198's avatar
Matt_70198
Icon for Nimbostratus rankNimbostratus
Sep 26, 2013

redirecting to different port based on URL

Hello,

 

Did a bit of searching on this before-hand to come up with what I've got, wanted to run it by you to see if it will hold water.

 

There are a large number of URLs, around 80, which share around 10 public IPs. The web servers themselves will listen on different ports for each URL.

 

So there is something like this, ssl certs will be tied to these VIPs

 

vip: 10.10.10.10:8010 (url aaa.com) pool: aaa-pool

 

vip: 10.10.10.10:8020 (url bbb.com) pool: bbb-pool

 

vip: 10.10.10.10:8030 (url ccc.com) pool: ccc-pool

 

aaa-pool members: serverA:8010, serverB:8010

 

bbb-pool members: serverA:8020, serverB:8020

 

ccc-pool members: serverA:8030, serverB:8030

 

Clients will hit the url on 80 and/or 443, the requirement is to redirect them to the proper port based on url. So I created the following:

 

vip: 10.10.10.10:80, iRule: redirect-80-to-8xxx

 

vip: 10.10.10.10:443, iRule: redirect-443-to-8xxx

 

iRule redirect-80-to-8xxx below:

 

when HTTP_REQUEST {

 

switch [HTTP::host] {

 

"aaa.com" {

 

HTTP::redirect http://[getfield [HTTP::host] ":" 1]:8010[HTTP::uri]

 

}

 

"bbb.com" {

 

HTTP::redirect http://[getfield [HTTP::host] ":" 1]:8020[HTTP::uri]

 

}

 

"ccc.com" {

 

HTTP::redirect http://[getfield [HTTP::host] ":" 1]:8030[HTTP::uri]

 

}

 

}

 

}

 

Is that syntax correct? To pick out the url, and then forward to the proper vip.

 

If this iRule for http and https were to get loaded up with 80 matches, would that have an adverse impact on the LB?

 

Edit: sorry for funky formatting there

 

Thanks!

 

3 Replies

  • That should technically work. So for example, if the user requested "http://aaa.com/foo", your iRule would redirect them to "http://aaa.com:8010/foo" - presumably another VIP.

    You could get around the whole non-standard port thing by simply sending to different pools based on the host. I'd also use a data group for such a large set of services:

    Data group (ex. my_host_dg)

    aaa.com := aaa_pool
    bbb.com := bbb_pool
    ccc.com := ccc_pool
    

    And then an iRule that looks like this:

    when HTTP_REQUEST {
        if { [class match [string tolower [HTTP::host]] equals my_host_dg] } {
            pool [class match -value [string tolower [HTTP::host]] equals my_host_dg]
        }
    }
    

    You'd need one VIP for port 80 traffic, one pool for each application (listening on the appropriate port), and one data group entry to map the host to the pool.

    As for SSL traffic, you could the same with a few additional options:

    1. Create a single SSL profile that contains a "Subject Alt Name" (SAN) certificate - a cert that contains all of the server names.

    2. If you're on a v11 F5 box and don't have to worry about clients that can't do TLS (WinXP and below), you can use Server Name Indicator (SNI), create separate client SSL profiles for each server certificate/key, and apply all of those client SSL profiles to the port 443 VIP. The VIP will choose the correct client SSL profile based on the client's request.

  • In case you want to redirect your clients to SSL, you would follow your initial approach of using the HTTP::redirect. The term 'forward' is not matching here. Indeed the client will get a notification (302/301 'redirect') via location header to connect to the specified URL. The client will open a new connection to a different port. Kevin´s solution is providing a transparent pool selection instead.

    Assigning a
    HTTP::redirect "https://[HTTP::host][HTTP::uri]"
    is a common solution on a :80 virtual server to force a client to use SSL.
  • For HTTP traffic it's pretty straight forward. The client navigates to http://aaa.com, which resolves to a VIP. The VIP looks at the requested host name (aaa.com), looks that up in the data group, and then sends the traffic to the corresponding pool (a bunch of servers listening on port 8010 for example). The VIP does the port translation transparently so the client doesn't deal with the non-standard port. Port 443 is only slightly different in that the HTTPS VIP must have a certificate that can serve all of the host names (wildcard, SAN, or SNI). Otherwise the logic is exactly the same.

    Redirecting users from a port 80 request to a port 443 VIP is usually a simple iRule applied to a port 80 VIP:

    when HTTP_REQUEST {
        HTTP::redirect "https://[HTTP::host][HTTP::uri]"
    }