Forum Discussion

Misty_Spillers's avatar
Misty_Spillers
Icon for Nimbostratus rankNimbostratus
Mar 04, 2016

Please help me rewrite an iRule from Ver 9 to version 11.6 (How to detect excessive connections)

I used to use this rule (which I grabbed from here) on version 9 to detect and alert on IP addresses making excessive connection to VIPs. I was wondering if anyone could help me optimize it for version 11.6. I would like the "whitelist" to be a data group if possible.

 

Or if you have any other suggestions how to accomplish this without ASM (working on getting it) please let me know.

 

Thank you very much.

 

Misty

 

Code
when RULE_INIT {
        array set ::active_clients { }
        array set white_client {
            x.x.x.x
            x.x.x.x
            }
    }

    when CLIENT_ACCEPTED {
            set client_ip [IP::remote_addr]
            if { [info exists ::active_clients($client_ip)] && ![info exist ::white_client($client_ip)] } {
            if {$::active_clients($client_ip) > 50 } {
            incr ::active_clients($client_ip)
            log "Alert! $::active_clients($client_ip) connections to mysite.com from $client_ip"
            return
            } else {
            incr ::active_clients($client_ip)
           }
    } else {
    set ::active_clients($client_ip) 1
    }
    }
    when CLIENT_CLOSED {
    set client_ip [IP::remote_addr]
    if { [info exists ::active_clients($client_ip)] && ![info exist ::white_client($client_ip)] } {
    incr ::active_clients($client_ip) -1
    if { $::active_clients($client_ip) <= 0 } {
    unset ::active_clients($client_ip)
    }
    }
    }

3 Replies

  • I used to use this rule (which I grabbed from here) on version 9 to detect and alert on IP addresses making excessive connection to VIPs. I was wondering if anyone could help me optimize it for version 11.6.

    This example should only be used on v9. For v10 or higher, use the session table to track the client connections. See the first example in the table wiki page for one way to do this.

    table command - https://clouddocs.f5.com/api/irules/table.html

    I would like the "whitelist" to be a data group if possible.

    you may check client ip against ip data group using class match command. when matching, exit from irule (i.e. "return" command).

    class command - https://clouddocs.f5.com/api/irules/class.html

  • Hi Misty,

    a CMP-friendly version (e.g. using the [table] and [class] command) of your provided logic would look like this...

    Datagroup:

     

    ltm data-group internal ALLOWED_IP_DATAGRROUP {
        records {
            10.0.0.0/8 { }
            172.12.0.0/12 { }
            192.168.0.0/16 { }
        }
        type ip
    }
    

     

    iRule Code:

     

    when RULE_INIT { 
        set static::client_timeout 300      ;seconds
    } 
    when CLIENT_ACCEPTED { 
        if { [class match [IP::client_addr] equals ALLOWED_IP_DATAGRROUP] } then {
            set is_filtered 0
        } else {
            set is_filtered 1
            if { [set result [table incr "conn_[IP::client_addr]"]] > 50 } then {
                log local0.debug "Alert: $result connections to mysite.com from [IP::client_addr]"
                 reject
                return
            } elseif { $result == 1 } then {
                table timeout "conn_[IP::client_addr]" $static::client_timeout
            }
            log local0.debug "Info: $result connections to mysite.com from [IP::client_addr]"
        }
    } 
    when CLIENT_CLOSED {
        if { $is_filtered } then {
            table incr "conn_[IP::client_addr]" -1 
        }
    }
    

     

    Cheers, Kai

  • Hi Misty,

    to show your clients a friendly error page you could try the iRule below...

     

    when RULE_INIT { 
        set static::client_timeout 300                      ; Seconds
        set static::conn_limit_site "http://somesite.de/"   ; URL
    } 
    when CLIENT_ACCEPTED { 
        if { [class match [IP::client_addr] equals ALLOWED_IP_DATAGRROUP] } then {
            set is_filtered 0
            set is_blocked 0
        } else {
            set is_filtered 1
            if { [set result [table incr "conn_[IP::client_addr]"]] > 50 } then {
                log local0.debug "Alert: $result connections to mysite.com from [IP::client_addr]"
                set is_blocked 1
                return
            } elseif { $result == 1 } then {
                table timeout "conn_[IP::client_addr]" $static::client_timeout
            }
            log local0.debug "Info: $result connections to mysite.com from [IP::client_addr]"
            set is_blocked 0
        }
    }
    when HTTP_REQUEST {
        if { $is_blocked } then {
            HTTP::redirect "$static::conn_limit_site?conn=$result"
            TCP::close
        }
    }
    when CLIENT_CLOSED {
        if { $is_filtered } then {
            table incr "conn_[IP::client_addr]" -1 
        }
    }
    

     

    Update: Added a TCP::close after HTTP::redirect

    Cheers, Kai