aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/modules.d/ratelimit.conf24
-rw-r--r--doc/markdown/modules/ratelimit.md23
-rw-r--r--src/plugins/lua/ratelimit.lua53
3 files changed, 67 insertions, 33 deletions
diff --git a/conf/modules.d/ratelimit.conf b/conf/modules.d/ratelimit.conf
index c6f243708..317957ac4 100644
--- a/conf/modules.d/ratelimit.conf
+++ b/conf/modules.d/ratelimit.conf
@@ -1,11 +1,21 @@
ratelimit {
.include(try=true,priority=1) "${DBDIR}/dynamic/ratelimit.conf"
- limit = "to:100:0.033333333";
- limit = "to_ip:30:0.025";
- limit = "to_ip_from:20:0.01666666667";
- limit = "bounce_to:10:0.000555556";
- limit = "bounce_to_ip:5:0.000277778";
- limit = "user:20:0.01666666667";
+ rates {
+ # Limit for all mail per recipient (burst 100, rate 2 per minute)
+ to = [100, 0.033333333];
+ # Limit for all mail per one source ip (burst 30, rate 1.5 per minute)
+ to_ip = [30, 0.025];
+ # Limit for all mail per one source ip and from address (burst 20, rate 1 per minute)
+ to_ip_from = [20, 0.01666666667];
+ # Limit for all bounce mail (burst 10, rate 2 per hour)
+ bounce_to = [10, 0.000555556];
+ # Limit for bounce mail per one source ip (burst 5, rate 1 per hour)
+ bounce_to_ip = [5, 0.000277778];
+ # Limit for all mail per authenticated user (burst 20, rate 1 per minute)
+ user = [20, 0.01666666667];
+ }
+ # If symbol is specified, then it is inserted instead of setting result
+ #symbol = "R_RATELIMIT";
whitelisted_rcpts = "postmaster,mailer-daemon";
max_rcpt = 5;
-} \ No newline at end of file
+}
diff --git a/doc/markdown/modules/ratelimit.md b/doc/markdown/modules/ratelimit.md
index 209d9f42f..dc0ac3ae0 100644
--- a/doc/markdown/modules/ratelimit.md
+++ b/doc/markdown/modules/ratelimit.md
@@ -39,26 +39,25 @@ Each bucket has two parameters:
For example, a bucket with capacity `100` and leak `1` can accept up to 100 messages but then
will accept not more than a message per second.
-By default, ratelimit module has the following settings:
+By default, ratelimit module has the following settings which disable all limits:
~~~lua
-- Default settings for limits, 1-st member is burst, second is rate and the third is numeric type
local settings = {
-- Limit for all mail per recipient (burst 100, rate 2 per minute)
- to = {[1] = 100, [2] = 0.033333333, [3] = 1},
+ to = {0, 0.033333333},
-- Limit for all mail per one source ip (burst 30, rate 1.5 per minute)
- to_ip = {[1] = 30, [2] = 0.025, [3] = 2},
+ to_ip = {0, 0.025},
-- Limit for all mail per one source ip and from address (burst 20, rate 1 per minute)
- to_ip_from = {[1] = 20, [2] = 0.01666666667, [3] = 3},
+ to_ip_from = {0, 0.01666666667},
-- Limit for all bounce mail (burst 10, rate 2 per hour)
- bounce_to = {[1] = 10, [2] = 0.000555556, [3] = 4},
+ bounce_to = {0, 0.000555556},
-- Limit for bounce mail per one source ip (burst 5, rate 1 per hour)
- bounce_to_ip = {[1] = 5 , [2] = 0.000277778, [3] = 5},
+ bounce_to_ip = {0, 0.000277778},
-- Limit for all mail per user (authuser) (burst 20, rate 1 per minute)
- user = {[1] = 20, [2] = 0.01666666667, [3] = 6}
-
+ user = {0, 0.01666666667}
}
~~~
@@ -73,9 +72,9 @@ the value of this option is 'postmaster, mailer-daemon'
- `whitelisted_ip` - a map of ip addresses or networks whitelisted
- `max_rcpts` - do not apply ratelimit if it contains more than this value of recipients (5 by default). This
option allows to avoid too many work for setting buckets if there are a lot of recipients in a message).
-- `limit` - allows to set limit for a specific category. This option should be in the following form:
+- `rates` - a table of allowed rates in form:
- type:burst:leak
+ type = [burst,leak];
Where `type` is one of:
@@ -86,4 +85,6 @@ Where `type` is one of:
- `bounce_to_ip`
`burst` is a capacity of a bucket and `leak` is a rate in messages per second.
-Both these attributes are floating point values. \ No newline at end of file
+Both these attributes are floating point values.
+
+- `symbol` - if this option is specified, then `ratelimit` plugin just adds the corresponding symbol instead of setting pre-result, the value is scaled as $$ 2 * tanh(\frac{bucket}{threshold * 2}) $$, where `tanh` is the hyperbolic tanhent function
diff --git a/src/plugins/lua/ratelimit.lua b/src/plugins/lua/ratelimit.lua
index cb7394e2f..2c80c0139 100644
--- a/src/plugins/lua/ratelimit.lua
+++ b/src/plugins/lua/ratelimit.lua
@@ -31,20 +31,19 @@ local default_port = 6379
-- Default settings for limits, 1-st member is burst, second is rate and the third is numeric type
local settings = {
-- Limit for all mail per recipient (burst 100, rate 2 per minute)
- to = {[1] = 100, [2] = 0.033333333, [3] = 1},
+ to = {0, 0.033333333},
-- Limit for all mail per one source ip (burst 30, rate 1.5 per minute)
- to_ip = {[1] = 30, [2] = 0.025, [3] = 2},
+ to_ip = {0, 0.025},
-- Limit for all mail per one source ip and from address (burst 20, rate 1 per minute)
- to_ip_from = {[1] = 20, [2] = 0.01666666667, [3] = 3},
+ to_ip_from = {0, 0.01666666667},
-- Limit for all bounce mail (burst 10, rate 2 per hour)
- bounce_to = {[1] = 10, [2] = 0.000555556, [3] = 4},
+ bounce_to = {0, 0.000555556},
-- Limit for bounce mail per one source ip (burst 5, rate 1 per hour)
- bounce_to_ip = {[1] = 5 , [2] = 0.000277778, [3] = 5},
+ bounce_to_ip = {0, 0.000277778},
-- Limit for all mail per user (authuser) (burst 20, rate 1 per minute)
- user = {[1] = 20, [2] = 0.01666666667, [3] = 6}
-
+ user = {0, 0.01666666667}
}
-- Senders that are considered as bounce
local bounce_senders = {'postmaster', 'mailer-daemon', '', 'null', 'fetchmail-daemon', 'mdaemon'}
@@ -259,24 +258,32 @@ local function rate_test_set(task, func)
end
-- Get user (authuser)
local auser = task:get_user()
- if auser then
+ if auser and settings['user'] > 0 then
table.insert(args, {settings['user'], make_rate_key (auser, '<auth>', nil)})
end
local is_bounce = check_bounce(from_user)
- if rcpts then
+ if rcpts and not auser then
_.each(function(r)
if is_bounce then
- table.insert(args, {settings['bounce_to'], make_rate_key ('<>', r['addr'], nil)})
- if ip then
- table.insert(args, {settings['bounce_to_ip'], make_rate_key ('<>', r['addr'], ip)})
+ if settings['bounce_to'][1] > 0 then
+ table.insert(args, { settings['bounce_to'], make_rate_key('<>', r['addr'], nil) })
+ end
+ if ip and settings['bounce_to_ip'][1] > 0 then
+ table.insert(args, { settings['bounce_to_ip'], make_rate_key('<>', r['addr'], ip) })
end
end
- table.insert(args, {settings['to'], make_rate_key (nil, r['addr'], nil)})
+ if settings['to'][1] > 0 then
+ table.insert(args, { settings['to'], make_rate_key(nil, r['addr'], nil) })
+ end
if ip then
- table.insert(args, {settings['to_ip'], make_rate_key (nil, r['addr'], ip)})
- table.insert(args, {settings['to_ip_from'], make_rate_key (from_addr, r['addr'], ip)})
+ if settings['to_ip'][1] > 0 then
+ table.insert(args, { settings['to_ip'], make_rate_key(nil, r['addr'], ip) })
+ end
+ if settings['to_ip_from'][1] > 0 then
+ table.insert(args, { settings['to_ip_from'], make_rate_key(from_addr, r['addr'], ip) })
+ end
end
end, rcpts)
end
@@ -362,6 +369,22 @@ if opts then
parse_limit(rates)
end
+ if opts['rates'] and type(opts['rates']) == 'table' then
+ -- new way of setting limits
+ _.each(function(t, lim)
+ if type(lim) == 'table' and settings[t] then
+ settings[t] = lim
+ else
+ rspamd_logger.errx(rspamd_config, 'bad rate: %s: %s', t, lim)
+ end
+ end, opts['rates'])
+ end
+
+ local enabled_limits = _.totable(_.map(function(t, lim)
+ return t
+ end, _.filter(function(t, lim) return lim[1] > 0 end, settings)))
+ rspamd_logger.infox(rspamd_config, 'enabled rate buckets: %s', enabled_limits)
+
if opts['whitelisted_rcpts'] and type(opts['whitelisted_rcpts']) == 'string' then
whitelisted_rcpts = split(opts['whitelisted_rcpts'], ',')
elseif type(opts['whitelisted_rcpts']) == 'table' then