Forum Discussion

Brian_Moore_603's avatar
Brian_Moore_603
Icon for Nimbostratus rankNimbostratus
Jan 14, 2008

iRule for Multiple Pools

Is there any way to get traffic for a single IP VIP to multiple pools?

 

 

www.xyz.com/a---> poola

 

www.xyz.com/b---> poolb

 

www.xyz.com/c---> poolc

 

 

I found a potential iRule however in my setup I am using an iRule redirect from port 80 to 443 and trying to place the "pontential" iRule on the 443 VIP which doesn't seem possible given that the traffic is encrypted at this level. I need a way to pick the pool prior to doing the SSL redirect but I am lost on how to make that happen?

 

 

 

BM

1 Reply

  • Are you able to decrypt the SSL traffic on the BIG-IP? If so, you can use a rule like this:

    
     Parse the URI to determine which pool to send requests to.
     The pool string should be the second character in the URI.
      Example: The pool for URI '/A/path/to/file.ext' is pool_A
      
     Change "default_pool" to the pool which should be used if the parsed pool name doesn't exist.
    when HTTP_REQUEST {
        Check if requested path is at least two characters long
       if {[string length [HTTP::path]] > 1}{
           Parse first character after the leading slash
          set pool_string [string toupper [string range [HTTP::path] 1 1]]
           Try to set the pool based on the URI.  If the pool name doesn't exist, catch the error.
          if { [catch {pool pool_${pool_string}}]}{
              The pool parsed from the URI didn't exist
     log local0. "Error assigning pool to pool_${pool_string}"
              Assign a default pool for this request
             pool default_pool
          }
       }
    }

    If you aren't decrypting the HTTPS you could check the initial HTTP request and select a pool based on that. But there are some significant limitations.

    You would need to select a pool based on the URI in the initial HTTP request. You could use the session table to store the client IP address and selected pool. After redirecting the client from HTTP to HTTPS, you would continue to set the same pool for the life of the session table entry for all requests from that same client IP address. The downside to this is that you can't differentiate between multiple clients coming from the same IP address. Nor can you parse the HTTP headers or requests. So you couldn't send some HTTPS requests from the same client IP address to one pool and some to another pool. Also, if the session entry times out and the client makes an HTTPS request without first making an HTTP request, you wouldn't necessarily know which pool to send the request to.

    Here's a rough example:

    
    when RULE_INIT {
        Define a list of ports which should be parsed as HTTP, and redirected to HTTPS
       set ::http_ports [list \
          80 \
          8080 \
       ]
        Define a list of ports which should be parsed as HTTPS
       set ::https_ports [list \
          443 \
          8443 \
       ]
        Timeout for session table entries
       set ::session_timeout 3600
        Default pool to use if pool name can't be parsed from the URI or there isn't a session table entry for the client IP
       set ::default_pool default_https_pool
        Log debug messages to /var/log/ltm? 1=yes, 0=no
       set ::pool_selector_debug 1
    }
    when CLIENT_ACCEPTED {
        Check if request was made to an HTTP port
       if {[matchclass [TCP::local_port] equals $::http_ports]}{
           Check if requested path is at least two characters long
          if {[string length [HTTP::path]] > 1}{
              Parse first character after the leading slash
             set pool_string [string toupper [string range [HTTP::path] 1 1]]
              Check if pool exists before adding session table entry
             if {not ([catch [LB::status pool_${pool_string}]])}{
                 Add a session table entry with the client IP address and parsed URI
                session add uie [IP::client_addr] pool_${pool_string} $::session_timeout
             }
          }
           Redirect request to HTTPS
          HTTP::redirect https://[HTTP::host][HTTP::uri]
       } elseif {[matchclass [TCP::local_port] equals $::https_ports]}{
           Request was made to an HTTPS port, so check the session table for the client IP address and set the pool
          set saved_pool [session lookup uie [IP::client_addr]]
          if {$saved_pool ne ""}{
      Pool found in the session table so use it
             pool $saved_pool
          } else {
              No valid pool was found in the session table, so use the default pool
             pool $::default_pool
          }
       } else {
           Request was made to an undefined port, so drop it
          drop
       }
    }

    This is untested and could probably use a bit more debug logging for testing...

    Aaron