Forum Discussion

Ken_Wong_48678's avatar
Ken_Wong_48678
Historic F5 Account
Aug 01, 2005

use irule to match virtual server name to node name

Hi,

This is Ken. I encounter a problem and need to write some irule to help.

There are two notes servers, client collect the server should use the server's hostname. The server discard any non hostname connection.

But, I need to load balancing the servers. I am trying to use irule to replace the request virtual server name to original server's hostname. I just write the following rule to handle single server. Can anyone give me some suggestions that I can use to load balancing two servers. Thanks!

Regards,

Ken


when CLIENT_ACCEPTED { 
   if { [TCP::remote_port] == 1352 } {
      log local0. "Connect to Notes Server [IP::client_addr]:[TCP::client_port] --> [IP::server_addr]:[TCP::server_port]"
   }
}
when CLIENT_DATA { 
   if { [TCP::payload] contains "WEBCSD00N" } {
      TCP::payload replace 62 9 "WEBCSD01N"
      log local0. "Replace payload [findstr [TCP::payload] "CN=" 9]"
      pool WEBCSD01N_pool
   }
   TCP::release
}
  • Ken_Wong_48678's avatar
    Ken_Wong_48678
    Historic F5 Account
    Hi,

    I combined your suggestion and write the following rule, but some errors occur, pls. help.

    I am trying to replace the hostname in TCP payload and then pass to specify pool.

    Check if the request hostname is WEBCSD0AN, change to WEBCSD01N and use pool WEBCSD01N_pool.

    if request hostname is WEBCSD0BN, change to WEBCSD02N and use pool WEBCSD02N_pool.

    Regards,

    Ken

    
    when CLIENT_ACCEPTED {
      if { [TCP::remote_port] == 1352 } {
        log local0. "Connect to Notes Server [IP::client_addr]:[TCP::client_port] --> [IP::server_addr]:[TCP::server_port]"
        TCP::collect
      }
    }
    when CLIENT_DATA {
      set orig_host_start [string first "CN=" [TCP::payload]]
      TCP::release $orig_host_start
      TCP::collect
      set orig_notes_host [string range [TCP::payload] 3 12]
      if { $orig_notes_host matches "WEBCSD0AN" } {
        TCP::payload replace 3 12 "WEBCSD01N"
        pool WEBCSD01N_pool }
      else {
        TCP::payload replace 3 12 "WEBCSD02N"
        pool WEBCSD02N_pool }
      TCP::release
    }
  • Ken_Wong_48678's avatar
    Ken_Wong_48678
    Historic F5 Account
    The error is

    01070151:3: Rule [test2] error: line 14:

    [parse error: PARSE syntax 390 {syntax error in expression " $orig_notes_host eg "WEBCSD0AN" ": extra tokens at end of expression}]

    [{ $orig_notes_host eg "WEBCSD0AN" }]

    The rule as following, pls. help. Thanks!

    Regards,

    Ken

    
    when CLIENT_ACCEPTED { 
      if { [TCP::remote_port] == 1352 } {
        log local0. "Connect to Notes Server [IP::client_addr]: [TCP::client_port] --> [IP::server_addr]:[TCP::server_port]"
        TCP::collect
      }
    }
    when CLIENT_DATA {
      set orig_host_start [string first "CN=" [TCP::payload]]
      TCP::release $orig_host_start
      TCP::collect
      set orig_notes_host [string range [TCP::payload] 3 12]
      if { $orig_notes_host eg "WEBCSD0AN" } {
        TCP::payload replace 3 12 "WEBCSD01N"
        pool WEBCSD01N_pool
      }
      else { 
        TCP::payload replace 3 12 "WEBCSD02N"
        pool WEBCSD02N_pool }
      TCP::release
    }

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Yes, that's an "EQ" not an "EG". The font for code (especially in bold italics) really does make it look like a lowercase G. I apologize for that.
  • Ken_Wong_48678's avatar
    Ken_Wong_48678
    Historic F5 Account
    Thanks, I have tested my irule but encounter some problems. I hope you guys can give me some advices.

     

     

    I use tcpdump to capture traffic and find out hostname in TCP Data like following pattern

     

    _.L..... ........

     

    ......WE BCSD0AN.

     

     

    But when I use the command "log local0. "Payload is [TCP::payload]"" in irule, I log the following results.

     

     

    Aug 4 12:08:03 tmm tmm[640]: Rule test : Payload is ÒÇ@9ëƓz¶/@[†q‚iìŽHäJ»

     

    Then, I try to use contains to check the whether the hostname in payload.

     

    if { [TCP::payload] contains "WEBCSD0AN" } {

     

    log local0. "WEBCSD0AN exist"

     

    }

     

    else {

     

    log local0. "WEBCSD0AN don't exist"

     

    }

     

     

    I always get the results "WEBCSD0AN don't exist". Therefore, I cannot replace the hostname. Anyone know why? Is there any mistakes?

     

    TIA

     

     

    Regards,

     

    Ken

     

     

     

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Is the host name in the first TCP packet or a following packet? That could explain why you don't see it.

    BTW, for debugging purposes you can use the Tcl command "puts" which will write full unencumbered output to the file /var/log/tmm. Please do not use this for any other purpose as it is very slow, but has the advantage of no buffer length limitation. Thus you can print out the entire TCP::payload. The reason it looks garbled is because it doesn't do anything with regard to the unprintable characters. You could run it through binary scan to get a hexadecimal representation of the payload and then print that out as well.

    
    binary scan [TCP::payload] h* pkt_in_hex
    puts "Rcvd: $pkt_in_hex"
  • Ken_Wong_48678's avatar
    Ken_Wong_48678
    Historic F5 Account
    Hi,

     

     

    Thanks! I use tcpdump to see the hostname appear in two frames which is not the first packet. But the hostname in two frame located in different offset. How can I check the hostname location in rule and replace a new name for it. Is it possible?

     

     

    And, I know there is a redirect method (HTTP::redirect) in rule to do http redirect. Could I redirect on other services? Thanks!

     

     

    Regards,

     

    Ken
  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    Yes, but you will need to enhance your rule to collect more data before releasing. Do you know if the host will always be found? If so, then you could keep collecting until you find the host and then modify it and release.

     

     

    Unfortunately, you need to use the HTTP profile in order to use the HTTP::redirect command. This would require the protocol to loosely conform to RFC2616, in that it would need a METHOD URI VERSION request line, followed by any other optional headers followed by a blank line and any content. I don't think the NotesRPC protocol looks like this at all.