Warning: Array to string conversion in /home/wwwroot/myf5/wp-content/plugins/wpjam-basic/public/wpjam-utils.php on line 496
# 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
}
when HTTP_REQUEST {
# Only check POST requests. If the application supports other request methods with payloads, add them in a switch statement here.
if { [HTTP::method] equals "POST"} {
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 {}{
# 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" }
}
}
}
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 {} {
# 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
}
}
Array
文章评论