Forum Discussion

Eddie_H_26456's avatar
Eddie_H_26456
Icon for Nimbostratus rankNimbostratus
Jul 22, 2013

Interpret a string as an IP address

The background is I have two virtual servers, one fort port 80 traffic and the other for port 443 traffic. Both are using different pools with the same nodes, but different ports. Here is my iRule:

 

 

---------------------------------------------

 

when HTTP_REQUEST {

 

set setCookie 0

 

 

if { [HTTP::cookie exists "cPersist"] } {

 

set nodeIP "[b64decode [HTTP::cookie value cPersist]]"

 

pool [LB::server pool] member $nodeIP

 

} else {

 

set setCookie 1

 

}

 

}

 

 

when HTTP_RESPONSE {

 

if { $setCookie equals "1" } {

 

HTTP::cookie insert name "cPersist" value [b64encode [IP::remote_addr]]

 

HTTP::cookie expires "cPersist" 3600

 

}

 

}

 

---------------------------------------------

 

 

The goal is simple, I'm trying to create an iRule that will persist based off the node IP address which initially served the request. To avoid the node IP address being available publically, I'm doing a simple base64 encode/decode on the value to obfuscute it.

 

 

The issue, I don't think the "pool" command is properly telling the F5 what should be set. I'm seeing my connection bounce between two servers. When removing the base64 encoding/decoding, however, everything seems to work just fine. The theory is when the string has been base64 decoded, it may be an IP address, but TCL is interpretting it as a string.

 

 

So, my question then, is simply this, how do you instruct the F5 to interpret a string as an IP address?

 

 

If I'm missing anything else blatently in my iRule, please let me know.

 

 

Thanks.

 

 

-Eddie

 

 

7 Replies

  • Try this:

    
    set do_pool "pool [LB::server pool] member [b64decode [HTTP::cookie value cPersist]]"
    eval $do_pool
    

    Also, just curious but why not use the built-in Cookie persistence - which also obfuscates the IP?

  • The build-in cookie persistence includes the port number in its obfuscation. Since we are serving unencrypted and "decrypted" traffic on different pool member ports, we are unable to ensure persistence during HTTP to HTTPS transitions.

     

     

    I'll test out your suggestion as soon as I get a chance.

     

     

    In other news, thanks to you, I think I finally understand what the "eval" command does ;)
  • Hi Eddie,

     

     

    Are you unable to use Source Address Persistence? With Source Address Persistence you can persist to the same node across different Pools and Virtual Servers.

     

     

    This persistence type should also satisfy your desire to hide the Server's IP Addresses.

     

  • Hi Michael,

     

     

    That would work, but the customer requires for persistence to last a week, and has a terribly busy site. We initially did this with UIE, and the solution worked, but in the first 24 hours, the LB had over 300,000 persistence records, and we crashed TMM looking at it. So we have to find a way to do this that is entirely "stateless" on the load balancer.

     

     

    Thanks for the suggestion, however.

     

     

    -Eddie

     

  • Even with Cookie Persistance you are still running a large number of Client and Server Side connections and will run into the same problem through the configuration of your TCP Profiles with a Persistence Requirement of that size. If your TCP Profiles are configured for anything less that your applciation timeout the F5 LTM will send a TCP Reset in both directions and any reconnections (regardless of if they are persisted to the same server will be new connections...if this is not a problem and the applciation is truly stateless...then no persistence should be required at all).

     

     

    See SOL9812: Overview of BIG-IP TCP RST behavior for more information on the TCP Resets.

     

     

    Specifically under Profiles (Reset on Timeout is active by default):

     

     

    Protocol profile idle timeouts (if the Reset On Timeout setting is enabled)

     

     

    The BIG-IP system tracks connection flows by adding an entry to the connection table. When the connection flow becomes idle, the BIG-IP system starts a timer and closes the connection with a TCP RST packet when the connection reaches the idle session timeout. The TCP RST packet is sent on the client and server side of the connection, and the source IP address of the reset is the relevant virtual server IP address.
  • Given the information I provided, you make a great point, Michael. This particular issue, however is going to be avoided. Let me explain.

     

     

    The application's timeout is far less than one week, it coincides just fine with our TCP Profile's timeout. The weeklong persistence is to test upgraded code on a new web server. Effectively, my customer wants to insert a new server into the mix and send 10% of traffic to that server (using ratio's). To fully test the new website, he wants clients directed to the new server to "stay" on the new code/website for a week. Throughout that week, they can make as many connection and application login/logouts as they want, so long as they are on the new server for the whole week to fully test the new site.

     

     

     

    All that said, I managed to test Kevin's solution, and it did indeed work! Thanks Kevin. I also found another solution that worked as well, even though I didn't fully understand it ;).

     

     

     

    Kevin's Solution:

     

     

    if { [HTTP::cookie exists "cPersist"] } {

     

    set do_pool "pool [LB::server pool] member [b64decode [HTTP::cookie value cPersist]]"

     

    eval $do_pool

     

    } else {

     

    set setCookie 1

     

    }

     

    }

     

     

     

    Another solution:

     

     

    if { [HTTP::cookie exists "cPersist"] } {

     

    set nodeIP "[string tolower [b64decode [HTTP::cookie value cPersist]]]"

     

    pool [LB::server pool] member $nodeIP

     

    } else {

     

    set setCookie 1

     

    }

     

    }

     

     

    For some reason, when I did a "string tolower" on the decoded value, the Pool command took it correctly as an IP address. String toupper worked as well. But if I did neither, for some reason it was unable to intepret the decoded value as an IP address, even if it looked exactly like an IP address. Very strange, don't know what was going on. Even logged all three and couldn't see a difference in my logs:

     

     

    Jul 23 11:47:56 local/tmm info tmm[5323]: Playing with nodeIP -- nodeIP: 192.168.212.31 upper: 192.168.212.31 lower: 192.168.212.31

     

     

    Don't know. Eitherway, it looks like doing some sort of string manipulation to the b64decod value allowed the interpretter to properly interpret the result as an IP address. If anyone has any guesses as to why, I'd love to hear them ;)

     

     

     

     

    Thanks everyone for your help.

     

  • Hi Eddie,

     

     

    Thank you for the additional explanation. It makes more sense to me now on what you are trying to accomplish.

     

     

    I still see a problem though, the cookies that you are creating and injecting are Session Based on the browser, so unless they are going to use the same browser for 7 days straight there is still a very good chance that they could bounce back and forth between your new and old servers.

     

     

    Another idea (and it still has caveats to it) would be to create a Table (iRule Table Command) that would store the Client's IP Address with a lifetime of 7 days. When the client connects, if their IP Address is in the table then route them to the new server. So unless their IP Address changes you have them tied to the new server.

     

     

    Where this could be problematic is if you have a large number of clients behind a NAT hide or something.

     

     

    It's just a thought. In the end I would recommend that you do whatever works best for you. :-)