Forum Discussion

Awkrd1_7470's avatar
Awkrd1_7470
Icon for Nimbostratus rankNimbostratus
Jul 22, 2011

Current connections not dropped when using command:discard

Hello,

 

 

I have a simple i-Rule implemented that is not doing what I expect it to do. I would like to discard any current or new connections to the pool (TCP reset) when the pool members <2. What am I missing? Is it possible to send a TCP reset to both client and servers? Do I need to change my event statement?

 

 

when CLIENT_ACCEPTED {

 

 

Check if the VS's default pool has at least 2 active members

 

if { [active_members [LB::server pool]] < 2 } {

 

 

drop/discard the current connections

 

discard

 

}

 

}

 

 

I did turn on logging to verify the new connections are being discarded as I would think they should be, but the existing connections seems to persist and are not disconnected. Any assistance will be appreciated,

 

 

Thank you!
  • Hi Awkrd1,

     

    Have you looked at the reject command?

     

     

    http://devcentral.f5.com/wiki/iRules.reject.ashx

     

     

    I hope this helps

     

    Bhattman

     

  • The CLIENT_ACCEPTED event fires upon completion of the 3-way handshake, so established connections wouldn't actually fire this event and as you've discovered, you won't get the results you want. You may consider other options to deal with the established connections. A custom EAV with action on service down may be one option, although I bet other folks will have other ideas :)

     

     

    -- Matt
  • Thanks Bhattman,

     

     

    I initially configured the rule using the reject command but did not receive the results I needed to terminate the active (present) connections. I have used the reject, drop and discard commands, which drops any new connections but will not terminate the existing active connections.

     

     

    Thanks again!
  • Another suggestion is to use a different event such as SERVER_DATA along with TCP connect. This is really not the ideal way to handle this but it could be used indirectly to detect connections and hopefully drop the connections. This is just a theory of course.

     

     

    Bhattman

     

  • I would have to run some dumps as I'm not sure what exactly happens at the tcp level with a "discard" within that event.. If it just "discards" the packet.. I would think you'd see a lot of tcp retransmissions from the host if you're not sending any tcp parms to the server/host.. just dropping packets..?

     

     

    The discard wiki speaks to it as it does indeed discard the connection..

     

     

    After "discard" is executed, the rule will continue until the end of the current event so "connection discarded ..." will be logged.

     

     

    http://devcentral.f5.com/wiki/iRules.discard.ashx

     

     

    but notice they show it used in the "SERVER_CONNECTED" event..

     

     

    A lot of people miss the "action on service down" feature within a pool configuration. If you're not looking for much manipulation when droping the connection I would say it's a good option for you. Setting it to "reject" will send a TCP reset to the client and server forcing a close..

     

     

    Gui.. Pool--->(advanced)Action On Service Down--->Reject

     

     

    Bigpipe-

     

    b pool test '{

     

    action on svcdown reset

     

    }'
  • I think it's time we ask: what layer 7 protocol are we dealing with here? It may really matter given the use case.

     

     

    This is a really interesting one...my gut is pointing me toward action on service down, combined with another technique or two, as I mentioned above.

     

     

    -- I thought I had cooked up a clever hack with a dummy pool, with a single member forced offline. Set action on service down to reject on that one, then select that pool if you're <2 on your real member pool. But that won't work either, because you still have to address the active flows.

     

     

    -- SERVER_DATA may be an option, but it also means that you'll need to use TCP::collect on every egress segment, and even still I'm not sure how you'd fail those active flows in a consistent way.

     

     

    -- LB::down your pool members to force action on service down to fire on existing flows - I think that this would work, but it introduces a statistical possibility that you'll still get some flapping because LB::down will cause an immediate re-probe of the monitor, and if your pool members are up you may end up with some connections failing as expected, and others working.

     

     

    For this one I think that your best bet is an EAV with TMSH calls (or bigpipe, depending on your version) to check the pool member count, then fail that pool based on the results. With action on service down it'll reject all connections, and you can probably avoid the iRule path completely.

     

     

    It's a philosophical debate as to whether a decision like this should be made on the data plane or the management plane, with valid arguments on both sides. But that'll have to wait for another thread :)

     

     

    --Matt

     

     

     

  • Thank you Matt!

     

     

    Thank you Bhattman!

     

     

    Changing the event is my next option, maybe something like this;

     

     

    when SERVER_CONNECTED {

     

     

    Check if the VS's default pool has at least 2 active members

     

    if { [active_members [LB::server pool]] < 2 } {

     

     

    drop/discard the current connections

     

    discard

     

    }

     

    }

     

     

    I am aware that the action on service down reset will provide the results I am looking for, but my pool is not down with a single node still available.

     

    I'll need to lab using different events and commands and provide an update later.

     

    Thanks again!
  • That's why you'd want to use an EAV here - you can create your own logic that determines when the pool is down. It would be easy to fail a custom monitor with a single available member this way.

     

     

    Remember that SERVER_CONNECTED fires when you establish a connection (handshake) with the server on the back side of the BigIP, so this won't address killing your current connections either.

     

     

    Good luck and let us know what you come up with.

     

     

    -- Matt

     

  • Most certainly NOT an elegant solution, but I think you could try this kludgy idea, which does not involve an irule....

     

     

    For each member of your pool, create a monitor associated with that IP's destination specified. Apply all the monitors to the pool, with an "Availability Requirement" of 2 and set the "Action On Service Down" to either drop or reject....

     

     

    For example... via the CLI...

     

     

    tmsh

     

    ltm

     

    create monitor http http-192.168.0.1-80 destination 192.168.0.1:80 defaults-from http

     

    create monitor http http-192.168.0.2-80 destination 192.168.0.2:80 defaults-from http

     

    create monitor http http-192.168.0.3-80 destination 192.168.0.3:80 defaults-from http

     

    create pool testpool members add {192.168.0.1:80 192.168.0.2:80 192.168.0.3:80} monitor min 2 of { http-192.168.0.1-80 http-192.168.0.2-80 http-192.168.0.3-80} service-down-action reset

     

     

    You may want to replace 'reset' with 'drop' depending on whether or not you actually want to send resets or just kill the connection.