Forum Discussion

Martin_Kaiser_1's avatar
Martin_Kaiser_1
Icon for Nimbostratus rankNimbostratus
Nov 14, 2006

connection limit across services

Hi guys,

 

 

I need to find a solution for the following problem:

 

 

I have a pair of v9 BigIPs which are loadbalancing a couple of Nortel VPN gateways. Clients connect to a VS running on port 500 over the internet. This is only the initial connection. Each client opens two of those connections to the chosen VPN gateway (don't ask me why, I'm not into this VPN stuff very deeply).

 

When those connections are established, the client establishes a new connection to a different VS running on port 10000, through which the "real" data will flow. The both connections on port 500 are teared down shortly after the connection on port 10000 is established. Of course, the connections on port 500 and the one on port 10000 have to use the same gateway, which is no problem with the option "persist across services".

 

The problem is a different one: Each gateway assigns IP-addresses to its clients. Let's assume that each gateway has a pool of 200 addresses to assign. The problem now is, when I configure a connection limit of 200 on each node for port 10000, it will have no influence on the initial connections to port 500. When I configure the same connection limit for port 500, it won't work either, because those connections are teared down long before the connection to port 10000 is, i.e. the loadbalancer might pick a gateway which does not have any free ressources and the client will be rejected when it tries to connect to port 10000.

 

 

Does anybody have a hint or a solution for me? I thought about an iRule which is bound to the VS at port 500 and somehow checks if the appropriate node has its connection limit on port 10000 exceeded. How is that configured?

 

 

Any help is appreciated! Thanks in advance!

 

 

Greetings from Germany,

 

Martin

 

 

PS: it is not possible to simply use "least connections" as loadbalancing algorithm, because the VPN gateways are not equal in processing power and connection limit.

6 Replies

  • Perhaps the easiest way would be to establish an active connection count via an iRule on the virtual hosting the data path:

    
    when RULE_INIT {
      array set ::active_clients { }
    }
    when CLIENT_ACCEPTED {
      if { [info exists ::active_clients([IP::client_addr])]  } {
        incr ::active_clients([IP::client_addr])
      } else {
        set ::active_clients([IP::client_addr]) 1
      }
    }
    when CLIENT_CLOSED {
      if { [info exists ::active_clients([IP::client_addr])] } {
        incr ::active_clients([IP::client_addr]) -1
        if { $::active_clients([IP::client_addr]) <= 0 } {
          unset ::active_clients([IP::client_addr])
        }
      }
    }

    Then applying a limit via an iRule on the initial virtual:

    
    when CLIENT_ACCEPTED {
      if { [info exists ::active_clients([IP::client_addr])]  } {
        if {$::active_clients([IP::client_addr]) > 200 } {
          reject
          log local0. "Rejecting [IP::client_addr], 200 Active connections"
          return
        }
      }
    }

    Happy testing! (Rules loaded fine with the Editor on v9.1.2, not that that ensures a working solution!)
  • Thank you!

    I wasn't even aware that there is the possibility of defining some sort of global variables that can be accessed from separate rules. That opens new horizons 🙂

    However I have a few questions concerning your suggestion:

    1. shouldn't IP::client_addr be sustituted by IP::server_addr (except for the log command of course)?

    2. Can I extend the rule so that it will not simply reject the client, but redo the loadbalancing decision and take only those hosts into consideration, which have not exceeded their limit?

    By the way, expressions like this remind me of why I dislike TCL...

     if { [info exists ::active_clients([IP::client_addr])] } {

    so many brackets...

    I simply do not understand how F5 could prefer TCL over Python or Perl...

    Anyway, thank you very much for pointing my into the right direction!

    Greetings,

    Martin
  • You're right, it should be server. I don't think the variable will be populated however, until the serverside events. You could use the virtual address, which in this context would be IP::local_addr.

     

     

    You could easily extend this to limit connections by host/client/port/protocol/username/etc. Whatever you define as interesting on the clientside can be incremented/decremented as a connection count.

     

     

    Unless there is a reason for your virtual servers to be separate, you could simplify your rules by collapsing your two virtuals into a wildcard virtual so you could handle both ports in a single iRule.
  • Posted By citizen_elah on 11/14/2006 8:47 AM

     

    You're right, it should be server. I don't think the variable will be populated however, until the serverside events. You could use the virtual address, which in this context would be IP::local_addr.

     

     

     

    I already thought about that and will try to replace the event CLIENT_ACCEPTED with LB_SELECTED in order to get the subsequent IP::server_addr filled with something I can work with.

     

     

    Combining both virtuals to one single wildcard VS is also an interesting option. I hope I can give it a try tomorrow.

     

     

    Once again, thank you and have a nice evening (or whatever time it is right now where you are...)

     

     

    Martin
  • hi again,

     

     

    there was another thing which came into my mind before I was able to test the rule (which I wasn't able to do so far...):

     

    Will the events CLIENT_ACCEPTED and CLIENT_CLOSED ever get triggered when the VS runs as UDP service???
  • Yes: CLIENT_ACCEPTED and CLIENT_CLOSED are triggered for TCP and UDP. I believe they coincide with connection table entries being added/removed (b conn show).

     

     

    Aaron