Forum Discussion
mattias_56723
Nov 29, 2010Nimbostratus
Mitigating Slow HTTP Post DDoS Attacks With iRules
I have tried to implement the "slow http post ddos.." iRule, but I got some errors. http://devcentral.f5.com/Tutorials/...Rules.aspx
when HTTP_REQUEST {
if { [HTTP::method] equal...
Joshua_Rasnier
Jul 17, 2014Nimbostratus
Sorry for bringing up an old topic. But thought would be useful to add my own edited copy of the above irule.
The addition is rejecting any verb except for those specified. Helpful when a server on the back end is accepting any verb.
Based on 'Mitigating Slow HTTP Post DDoS Attacks With iRules' from George Watkins
Requires LTM v10.0+ for the after command
when RULE_INIT {
This iRule enforces a minimum length of time ($static::timeout) for a client to send POST request data.
The initial values are 2Kb / 2 sec = 1 Kb/s for the first 2Kb. These values should be tailored for the client base.
Default amount of request payload to collect (in bytes).
This is the maximum amount of content we will collect.
Clients will still be able to send unlimited payload sizes.
set static::collect_length 2048
Default timeout, for POST requests, to send $collect_length bytes (in milliseconds)
set static::timeout 2000
HTML response to send for blocked requests
set static::block_html {Your POST request is not being received quickly enough. Please retry.}
Log debug messages to /var/log/ltm? 1=yes, 0=no.
set static::post_debug 1
List of http methods supported by webserver
set sec_http_methods [list "GET" "PUT" "HEAD"]
}
when HTTP_REQUEST {
if { [matchclass [HTTP::method] equals $::sec_http_methods] } {
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: POST to [HTTP::host][HTTP::uri]" }
Create a local variable copy of the collection amount
set collect_length $static::collect_length
Create a local variable copy of the static timeout
set timeout $static::timeout
Check for a non-existent Content-Length header
if {[HTTP::header Content-Length] eq ""}{
Use default collect length for POSTs without a Content-Length header
set collect_length $static::collect_length
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: No Content-Length value" }
} elseif {[HTTP::header Content-Length] <= 0}{
Don't try to collect a payload if there isn't one
unset collect_length
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: Content-Length: 0." }
} elseif {[HTTP::header Content-Length] > $static::collect_length}{
Use the default collect length
set collect_length $static::collect_length
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: Content-Length: [HTTP::header Content-Length], collecting $collect_length" }
} else {
Collect the actual payload length
set collect_length [HTTP::header Content-Length]
Calculate a custom timeout based on the same ratio we use for the default collect length and default timeout
set timeout [expr {[HTTP::header Content-Length] * $static::timeout / $static::collect_length }]
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: Content-Length: [HTTP::header Content-Length], collecting $collect_length bytes with timeout $timeout ms" }
}
If the POST Content-Length isn't 0, collect (a portion of) the payload
if {[info exists collect_length]}{
If the entire request hasn't been received within X seconds, send a 408, and close the connection
set id [after $timeout {
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: $timeout ms reached. Closing connection" }
HTTP::respond 408 content $static::block_html Connection Close
TCP::close
}]
Trigger collection of the request payload
HTTP::collect $collect_length
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: Collecting $collect_length" }
}
} else {
reject
}
}
when HTTP_REQUEST_DATA {
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: Collected [HTTP::payload length] bytes." }
Check if the 'after' ID exists
if {[info exists id]} {
If all the POST data has been received, cancel the connection closure
if { $static::post_debug } { log local0. "[IP::client_addr]:[TCP::client_port]: Canceling \$id: $id" }
after cancel $id
}
}
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects