# HG changeset patch # User Matthew Wild # Date 1479246912 0 # Node ID 5fe483b73fd237c6e51a660e7ace0f1da29c7a20 # Parent 2fb11d34087edf600f13b1391e3ee44d8b9ce79b mod_firewall: Rate limiting: Document 'entries' and add option to allow overflowing when full diff -r 2fb11d34087e -r 5fe483b73fd2 mod_firewall/README.markdown --- a/mod_firewall/README.markdown Tue Nov 15 21:02:46 2016 +0000 +++ b/mod_firewall/README.markdown Tue Nov 15 21:55:12 2016 +0000 @@ -302,6 +302,18 @@ For more information on expressions, see the section later in this document. +Each value of 'EXPRESSION' has to be tracked individually in a table, which uses a small amount of memory. To prevent +memory exhaustion, the number of tracked values is limited to 1000 by default. You can override this by setting the +maximum number of table entries when you define the rate: + + %RATE normal: 2 (burst 3) (entries 4096) + +Old values are automatically removed from the tracking table. However if the tracking table becomes full, new entries +will be rejected - it will behave as if the rate limit was reached, even for values that have not been seen before. Since +this opens up a potential denial of service (innocent users may be affected if malicious users can fill up the tracking +table within the limit period). You can choose to instead "fail open", and allow the rate limit to be temporarily bypassed +when the table is full. To choose this behaviour, add `(allow overflow)` to the RATE definition. + ### Session marking It is possible to 'mark' sessions (see the MARK_ORIGIN action below). To match stanzas from marked sessions, use the diff -r 2fb11d34087e -r 5fe483b73fd2 mod_firewall/definitions.lib.lua --- a/mod_firewall/definitions.lib.lua Tue Nov 15 21:02:46 2016 +0000 +++ b/mod_firewall/definitions.lib.lua Tue Nov 15 21:55:12 2016 +0000 @@ -31,14 +31,14 @@ local rate = assert(tonumber(line:match("([%d.]+)")), "Unable to parse rate"); local burst = tonumber(line:match("%(%s*burst%s+([%d.]+)%s*%)")) or 1; local max_throttles = tonumber(line:match("%(%s*entries%s+([%d]+)%s*%)")) or multirate_cache_size; - + local deny_when_full = not line:match("%(allow overflow%)"); return { single = function () return new_throttle(rate*burst, burst); end; multi = function () - local cache = require "util.cache".new(max_throttles, evict_only_unthrottled); + local cache = require "util.cache".new(max_throttles, deny_when_full and evict_only_unthrottled or nil); return { poll_on = function (_, key, amount) assert(key, "no key");