Forum Discussion

Ryan_34424's avatar
Ryan_34424
Icon for Altostratus rankAltostratus
Jan 18, 2018

LTM :: iRule to Limit Source Addresses

So... here's a weird one. And I understand it's not optimal...

...but say there is a crisis and management sends down the proclamation: "Only allow X sources at a time access to the server pool until the admins can fix XYZ on the systems involved". So we rush to figure out a way to do so... and come up with the below.

Other than blasting the table full of addresses (such as a resource exhaustion DDoS against the F5), are there any other caveats that I might not be thinking about here?

when CLIENT_ACCEPTED {
    set hsl [HSL::open -proto UDP -pool syslog-servers.pool] 
}

when HTTP_REQUEST {
    set source_ip [IP::client_addr]
    set ip_limit 2000

     Delete all IPs
     table delete -subtable conns -all

    if { [table lookup -notouch -subtable conns $source_ip] != 1 } {
         Source IP doesn't exist in table, add to table
        table add -subtable conns $source_ip 1 900
    } else {
         Source IP is in the table, actively involved, renew the timer
        table lookup -subtable conns $source_ip
    }

    if { [table keys -subtable conns -count] <= $ip_limit } {
         The current IP count is less than alloted, allow pool access
        pool $pool_name
         above variable acquired in prior logic
    } else {
         The IP count has been reached. Do not provide pool access.
        HSL::send $hsl ":: Source IP limit ($ip_limit) hit for pool, redirecting to maintenance page."
        call maintenance_page.irule::display_page
    }
}
  • Hi Ryan,

    the problem with your iRule is, that it would DoS your entire application once

    [table keys -subtable conns -count]
    has reached its configured limit. Even the
    [IP::client_addr]
    which has been allowed before will become blocked.

    You may take a look to the iRule below how I would solve the puzzle. My iRule would allow the already known

    [IP::client_addr]
    until their
    [table -subtable]
    entry expires and then allow another
    [IP::client_addr]
    to access the application until its entry expires...

    when RULE_INIT {
        set static::ip_limit 2000
        set static::ip_timeout 900
    }
    when CLIENT_ACCEPTED {
        set hsl [HSL::open -proto UDP -pool syslog-servers.pool] 
    }
    when HTTP_REQUEST {
         Delete all IPs
         table delete -subtable conns -all
        if { [table lookup -subtable conns [IP::client_addr]] ne "" } then {
             The client is currently known in the table. 
             Already refreshed the clients table entry.
             Allow the request...
        } elseif { [table keys -subtable conns -count] < $static::ip_limit } then {
             The client is not known in the table. 
             The connection limit has not been reached. 
             Create a new entry for the client.
            table set -subtable conns [IP::client_addr] 1 $static::ip_timeout indef
             Allow the request...
        } else {
             The client is not known in the table. 
             The connection limit has been reached. 
             Log the request...
            HSL::send $hsl ":: Source IP limit ($ip_limit) hit for pool, redirecting to maintenance page."
             Display maintenance page...
            call maintenance_page.irule::display_page
        }
    }
    

    Note: I've removed the pool logic, since it shouldn't considered as security control. The premptive

    [HTTP::respond]
    of your meintenance macro should be more than sufficent...

    Cheers, Kai