Forum Discussion

dani82_22742's avatar
dani82_22742
Icon for Nimbostratus rankNimbostratus
Jan 15, 2008

Redirect HTTP and HTTPS traffic to the same node in different pools

I have two pools with the same servers but with other ports. I need, that a client, which is connected with http ends on the same server, if it change to https. An I would use cookie-persistence and not ip-persistence. How can I do that?


pool my-http {
   lb method predictive
   members
      serverA:http
      serverB:http
      serverC:http
}
pool my-https {
   lb method predictive
   members
      serverA:81
      serverB:81
      serverC:81
}
virtual mySite-http {
   snat automap
   pool my-http
   destination w.x.y.z:http
   ip protocol tcp
}
virtual mySite-https {
   snat automap
   pool my-https
   destination w.x.y.z:https
   ip protocol tcp
}

5 Replies

  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    If you use a port 0 pool, you can share the pool (and the related cookie) between 2 virtual servers and set both to use cookie insert persistence.

     

     

    For the HTTP virtual server, no iRule would be required, since the port will pass through unchanged and the persistence will work as usual.

     

     

    For the HTTPS virtual, you'll need an iRule to look for an existing cookie, decode the server IP and select the correct pool member specifying port 81.

     

     

    The Persistence Cookie Logger iRule (Click here) has the logic to extract the IP address of the node.

     

     

    You can use the node command (Click here) to specify a node by IP + port. (Logic to catch a dead server can be added in LB_FAILED event as demonstrated there.)

     

     

    HTH

     

    /deb
  • A related suggestion...

    If you're able to use only HTTP on the back end to the servers, you could define the pool members on the same HTTP port and avoid using an iRule altogether. Just the two VIPs, the same cookie insert persistence profile and the same pool would work.

    And if you wanted to use one VIP on port 0, with one cookie persist profile and one pool with the members defined on an HTTP port, you could use a rule like this:

    
    when CLIENT_ACCEPTED {
        Make decisions based on the destination port
       switch [TCP::local_port] {
          80 {
              Need to disable client SSL for HTTP requests
             SSL::disable
          }
          443 {
              Do nothing, request will be decrypted and sent to pool
          }
          default {
              Reset the request as it's not to an allowed port
             reject
          }
       }
    }

    Aaron
  • Hi tried the solution from deb. The only problem is, if a user connect the first time direct with https, then the lb can't find any cookie and he never add one.

    
    when RULE_INIT {
       see SOL6917 for cookie encoding details: https://tech.f5.com/home/solutions/sol6917.html        
      set ::myCookieName BigIP_cash_cms
      set ::debug 1
    }
    when HTTP_REQUEST {
     grab encoded cookie value & parse into relevant pieces
    if {[HTTP::cookie exists $::myCookieName]}{
    scan [HTTP::cookie $::myCookieName] "%d.%d.%d" myIpE myPortE unused
    if {$::debug != 0}{log local0. "myIpD=$myIpE   myPortE=$myPortE  unused=$unused"}
     calculate IP
    set myIpH [format %x $myIpE]
    if {$::debug != 0}{log local0. "myIpH=$myIpH"}
    set myIpD1 [expr 0x[substr $myIpH 6 2]]
    set myIpD2 [expr 0x[substr $myIpH 4 2]]
    set myIpD3 [expr 0x[substr $myIpH 2 2]]
    set myIpD4 [expr 0x[substr $myIpH 0 2]]
    set myIpD "$myIpD1.$myIpD2.$myIpD3.$myIpD4"
    if {$::debug != 0}{log local0. "myIpD=$myIpD"}
     set node
    node $myIpD 81
    } else {
    if {$::debug != 0}{log local0. "cookie $::myCookieName not found"}
    }
    }

    so i thought that i can add a cookie on the response. That's working not bad, but if I change after in the same session to http, it doesn't work. I can't find the failure.

    
    when HTTP_RESPONSE {
     add session cookie to response
    if {[HTTP::cookie exists $::myCookieName]}{
    } else {
    if {$::debug != 0}{log local0. "add cookie $::myCookieName to response"}
    if {$::debug != 0}{log local0. "cookie $::myCookieName for server [LB::server addr]"}
    scan [LB::server addr] "%d.%d.%d.%d" myIP1 myIP2 myIP3 myIP4
    set myCookieValue "[format %x $myIP4][format %x $myIP3][format %x $myIP2][format %x $myIP1]"
    HTTP::cookie insert name $::myCookieName value "[expr 0x$myCookieValue].0.0000"
    }
    }
    when LB_SELECTED {
     for the case, that no cookie was available in "HTTP:REQUEST" change here to port 81
    set myLBPort [LB::server port]
    if {$::debug != 0}{log local0. "myLBAddr=[LB::server addr] mylBPort=$myLBPort"}
    if {$myLBPort == 0}{
    if {$::debug != 0}{log local0. "myLBPort is 0"}
    set myLBAddr [LB::server addr]
    node $myLBAddr 81
    LB::reselect
    }
    }
  • The solution from hoolio only works if http and https traffic are forwarded to port 80. But not if https traffic must be forwarded to port 81
  • Deb_Allen_18's avatar
    Deb_Allen_18
    Historic F5 Account
    Ah, I left out one critical detail: to use cookie persistence on HTTPS, you have decrypt & re-encrypt the traffic (apply a clientssl and serverssl profile to the virtual server) otherwise the cookie will never be seen (it will be encrypted and unreadable by LTM)

     

     

    /deb