Forum Discussion

S_Meulmeester's avatar
Oct 09, 2023

I need an irule to decline/refuse/ an incomming tcp session from a source to a vip (ip address/port)

I need an irule to decline/refuse/ an incomming tcp session from a source to a vip (ip address/port) if that source has aleady "n" number of connections open. I am using Fast layer 4 LTM configuration

So for every incomming TCP SYN from a /32 source to a vip (destination ip and port)
-> the irule should verify the amount of open connections from that source to the vip it requests a connection for (destination ip and port)
-> if the amount of "open" connections is lower than a configured value > the connections is allowed
-> if the amount of "open" connections is higher than a configured value > the connection is refused

As I am not used ti create Irules I am a bit lost, ps I don't have ASM on the F5

Can someone help please ?

 

 

    • S_Meulmeester's avatar
      S_Meulmeester
      Icon for Cirrus rankCirrus

      Hi,

      That is not the same as what I need!   what you propose is : Connection Rate Limit Mode = rate limiting per second so if i put it to 10 it will allow 10 connections per second = 600 connections per minute

      I want to be able to limit a source ip to connect for example 200 sessions max and not per time interval.

      • Hi S_Meulmeester , 

        Not rate limit , there is another option of connection limit. 

        if you put for ex 10 connection limit , if this source did 11 connection the 11th will be dropped till one of 10  concurrent connections goes out. 

        Don't go for rate limit 

  • Hi S_Meulmeester , 

    Sorry for that mis-understanding , you can't limit per source and VS at the same time , you can use only limiting per Virtual server or rate limiting for ( source address & virtual server ) 

    Could you try this irule : 

    when RULE_INIT {
      array set ::active_clients { }
    }
    
    when CLIENT_ACCEPTED {
      set client_ip [IP::remote_addr]
      if { [info exists ::active_clients($client_ip)] } {
        if {$::active_clients($client_ip) > 5 } {
          reject
          return
        } else {
          incr ::active_clients($client_ip)
        }
      } else {
        set ::active_clients($client_ip) 1
      }
    }
    
    when CLIENT_CLOSED {
      if { [info exists ::active_clients($client_ip)] } {
        incr ::active_clients($client_ip) -1
        if { $::active_clients($client_ip) <= 0 } {
          unset ::active_clients($client_ip)
        }
      }
    }

    use this as a reference : https://github.com/f5devcentral/f5-irule-editor/blob/master/iRuler/Templates/Limit%20Connections%20From%20Client.txt

     

    • S_Meulmeester's avatar
      S_Meulmeester
      Icon for Cirrus rankCirrus

      Hi, it does something but not as expected, I verified it with a TCP dump : 5 first connection get accepted, 6th° gets RST, 7th°gets accepted again, 8th get RST,  9th gets accepted :  at that time I have 7 open connections from the same source .... and so on ... 

      I found this rule 

      when CLIENT_ACCEPTED {
      set x [table incr "ip-block-[IP::client_addr]"]
      if { $x == 1 } {
      required because we cannot set timeout via 'table incr'
      table set "ip-block-[IP::client_addr]" 1 3600 indef
      } elseif { $x >= 50 } {
      reject
      }
      }
      when CLIENT_CLOSED {
      if { [table incr "ip-block-[IP::client_addr]" -1] <= 0 } {
      table delete "ip-block-[IP::client_addr]"
      }
      }

      It gave an error adding it and I had to remove the bolt line  so now I have 

      when CLIENT_ACCEPTED {
      set x [table incr "ip-block-[IP::client_addr]"]
      if { $x == 1 } {
      table set "ip-block-[IP::client_addr]" 1 3600 indef
      } elseif { $x >= 4 } {
      reject
      }
      }
      when CLIENT_CLOSED {
      if { [table incr "ip-block-[IP::client_addr]" -1] <= 0 } {
      table delete "ip-block-[IP::client_addr]"
      }
      }

      This seems to work but to be honest I don't fully understand what it does and what the 3600 indef is about

      Any suggestions ?

  • I plan to use this 


    # Limit each client IP address to 20 concurrent connections
    when CLIENT_ACCEPTED {

    # Check if the subtable has over 20 entries
    if { [table keys -subtable connlimit:[IP::client_addr] -count] >= 20 } {
    reject
    } else {

    # Add the client IP:port to the client IP-specific subtable
    # with a max lifetime of 180 seconds
    table set -subtable connlimit:[IP::client_addr] [TCP::client_port] "" 180
    }
    }

    when CLIENT_CLOSED {
    # When the client connection is closed, remove the table entry
    table delete -subtable connlimit:[IP::client_addr] [TCP::client_port]
    }


    https://community.f5.com/t5/technical-articles/advanced-irules-tables/ta-p/290369
    https://clouddocs.f5.com/api/irules/table.html#:~:text=If%20no%20timeout%20is%20specified,timeout%20will%20not%20be%20changed.