Forum Discussion

PeterB_71603's avatar
PeterB_71603
Icon for Nimbostratus rankNimbostratus
Jun 26, 2017

iRule node directive not working with SSL terminated virtual server

I'm having trouble with an iRule running on a virtual server handling https traffic - specifically with the "node" directive. The situation:

I have a pair of virtual servers, I'll call them Port80 and Port443, serving a web farm. Obviously Port80 receives http traffic and Port443 handles https traffic, configured with SSL termination so its pool is port 80 based (which the Port80 VS also uses). The 2 VSs share the same cookie based persistence profile. This iRule works on the Port80 VS and doesn't on the Port443 VS:

when HTTP_REQUEST {
  if {[string tolower [HTTP::uri]] contains "_monitor" } {
     switch -glob [string tolower [HTTP::uri]] {
        "*prodapp2*" {
           node 192.168.196.23 }
        "*prodapp3*" {
           node 192.168.196.33 }
        "*prodapp4*" {
           node 192.168.196.43 }
     }
  }
}

Obviously this is to allow external "server alive" monitoring of the individual nodes within the web farm. I'm currently doing this in my test environment and this is the only iRule in play. Consider a browser which currently has a persistence cookie for the prodapp3 node:

http://myDomain.com/_monitor/serverTest.aspx - works, response from prodapp3
http://myDomain.com/_monitor/serverTest.aspx?s=prodapp4 - works, response from prodapp4

https://myDomain.com/_monitor/serverTest.aspx - works, response from prodapp3
https://myDomain.com/_monitor/serverTest.aspx?s=prodapp4 - does not work, browser time out, it is as if the F5 dropped the request

The same thing happens if I don't use the serverTest page:

http://myDomain.com/anyPath/anyPage?_monitor=prodapp4 - works, response from prodapp4
https://myDomain.com/anyPath/anyPage?_monitor=prodapp4 - browser time out

I have tried other methods of specifying the node, changing "node 192.168.196.43" to:

node 192.168.196.43 80 - I get a response but from the persisted server, not the server specified in the query string
pool myPool member 192.168.196.43 80 - same (response but from wrong server)

Does anyone have an idea what I'm doing wrong and/or should do to make it work.

  • Have you considered changing the switch to something like this? Seems buggy that http works but not https, but I would think the query is the better aspect to select from.

    switch -glob [string tolower [HTTP::query]] {
      "s=prodapp2" { node 192.168.196.43 }
    }
    
  • Have you considered changing the switch to something like this? Seems buggy that http works but not https, but I would think the query is the better aspect to select from.

    switch -glob [string tolower [HTTP::query]] {
      "s=prodapp2" { node 192.168.196.43 }
    }
    
    • PeterB_71603's avatar
      PeterB_71603
      Icon for Nimbostratus rankNimbostratus

      Maybe ekaleido's answer was the key. I changed the "switch -glob [string tolower [HTTP::uri]]" to "switch -glob [string tolower [HTTP::query]]" and it started working. Note - I had already added port 80 to the "node" command. The full snippet now looks like:

      if {[string tolower [HTTP::uri]] contains "_monitor" } {
       switch -glob [string tolower [HTTP::query]] {
          "*prodapp2*" {
             node 192.168.196.23 80 }
          "*prodapp3*" {
             node 192.168.196.33 80 }
          "*prodapp4*" {
             node 192.168.196.43 80 }
       }
      }
      

      And all is well. I don't understand why it sometimes finds a string located in the query string within HTTP::uri and other times not but that's okay...

      Thanks!

  • Have you considered changing the switch to something like this? Seems buggy that http works but not https, but I would think the query is the better aspect to select from.

    switch -glob [string tolower [HTTP::query]] {
      "s=prodapp2" { node 192.168.196.43 }
    }
    
    • PeterB_71603's avatar
      PeterB_71603
      Icon for Nimbostratus rankNimbostratus

      Maybe ekaleido's answer was the key. I changed the "switch -glob [string tolower [HTTP::uri]]" to "switch -glob [string tolower [HTTP::query]]" and it started working. Note - I had already added port 80 to the "node" command. The full snippet now looks like:

      if {[string tolower [HTTP::uri]] contains "_monitor" } {
       switch -glob [string tolower [HTTP::query]] {
          "*prodapp2*" {
             node 192.168.196.23 80 }
          "*prodapp3*" {
             node 192.168.196.33 80 }
          "*prodapp4*" {
             node 192.168.196.43 80 }
       }
      }
      

      And all is well. I don't understand why it sometimes finds a string located in the query string within HTTP::uri and other times not but that's okay...

      Thanks!

  • Peter,

     

    If you review the iRule node command You'll notice "Note: If is omitted, the client's destination port is used for the serverside connection." Remember, the node command bypasses all load balancing, you're no longer using a pool or pool member, your going direct to the node. As such, since you didn't specify a port, the F5 uses the client's original destination port, in this case it'd be 443.

     

     

    So, are you expecting to send the traffic to the servers on port 443? Perhaps you should use the command "node 80".