[Rspamd] Dynamic ratelimit fixed, removed async redis request; Ready to implement per-user ratelimits via UI (tbd)

This commit is contained in:
andryyy
2017-08-30 21:42:39 +02:00
parent 66ae588445
commit b1213c51d7
8 changed files with 565 additions and 396 deletions

View File

@@ -1,66 +1,25 @@
local custom_keywords = {
['customrl'] = {},
}
function custom_keywords.customrl.get_value(task)
local rspamd_logger = require "rspamd_logger"
local rspamd_redis = require "rspamd_redis"
local rspamd_regexp = require "rspamd_regexp"
local re = rspamd_regexp.create('/^\\s*$/i')
local envfrom = task:get_from(1)
local env_from_addr = envfrom[1].addr:lower() -- get smtp from addr in lower case
local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case
local function rlo(object) -- get ratelimited object
local rlobj = string.format('%s', object)
local rl_ret, rl_obj = rspamd_redis.make_request_sync({host="172.22.1.249:6379", cmd='HGET', args={'RL_OBJECT', rlobj}, timeout=2.0})
if rl_ret and rl_obj then
return rl_obj
else
return false
end
end
rl_addr = rlo(env_from_addr)
rl_domain = rlo(env_from_domain)
if type(rl_addr) == 'string' and not re:match(rl_addr) then
rspamd_logger.infox(rspamd_config, "returning ratelimit object for %s", env_from_addr)
return rl_addr
elseif type(rl_domain) == 'string' and not re:match(rl_domain) then
rspamd_logger.infox(rspamd_config, "returning ratelimit object for %s", env_from_domain)
return rl_domain
if task:has_symbol('DYN_RL') then
rspamd_logger.infox(rspamd_config, "task has a dynamic ratelimit symbol, processing...")
return "check"
else
rspamd_logger.infox(rspamd_config, "task has no dynamic ratelimit symbol, skipping...")
return
end
end
function custom_keywords.customrl.get_limit(task)
local rspamd_logger = require "rspamd_logger"
local rspamd_redis = require "rspamd_redis"
local rspamd_regexp = require "rspamd_regexp"
local re = rspamd_regexp.create('/^\\s*$/i')
local envfrom = task:get_from(1)
local env_from_addr = envfrom[1].addr:lower() -- get smtp from addr in lower case
local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case
local function rlv(object) -- get ratelimited object
local rlobj = string.format('%s', object)
local rl_ret, rl_value = rspamd_redis.make_request_sync({host="172.22.1.249:6379", cmd='HGET', args={'RL_VALUE', rlobj}, timeout=2.0})
if rl_ret and rl_value then
return rl_value
else
return false
end
end
rl_addr = rlv(env_from_addr)
rl_domain = rlv(env_from_domain)
if type(rl_addr) == 'string' and not re:match(rl_addr) then
rspamd_logger.infox(rspamd_config, "returning ratelimit %s for %s", rl_addr, env_from_addr)
return rl_addr
elseif type(rl_domain) == 'string' and not re:match(rl_domain) then
rspamd_logger.infox(rspamd_config, "returning ratelimit %s for %s", rl_domain, env_from_domain)
return rl_domain
local dyn_rl_symbol = task:get_symbol("DYN_RL")
if dyn_rl_symbol then
local rl_value = dyn_rl_symbol[1].options[1]
rspamd_logger.infox(rspamd_config, "dynamic ratelimit symbol has option %s, returning...", rl_value)
return rl_value
end
end
return custom_keywords
-- returning custom keywords
return custom_keywords

View File

@@ -50,4 +50,61 @@ rspamd_config:register_symbol({
priority = 11
})
rspamd_config:register_symbol({
name = 'DYN_RL_CHECK',
type = 'prefilter',
callback = function(task)
local util = require("rspamd_util")
local redis_params = rspamd_parse_redis_server('dyn_rl')
local rspamd_logger = require "rspamd_logger"
local envfrom = task:get_from(1)
local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case
local env_from_addr = envfrom[1].addr:lower() -- get smtp from addr in lower case
local function redis_cb_user(err, data)
if err or type(data) ~= 'string' then
rspamd_logger.infox(rspamd_config, "dynamic ratelimit request for user %s returned invalid or empty data (\"%s\") or error (\"%s\") - trying dynamic ratelimit for domain...", env_from_addr, data, err)
local function redis_key_cb_domain(err, data)
if err or type(data) ~= 'string' then
rspamd_logger.infox(rspamd_config, "dynamic ratelimit request for domain %s returned invalid or empty data (\"%s\") or error (\"%s\")", env_from_domain, data, err)
else
rspamd_logger.infox(rspamd_config, "found dynamic ratelimit in redis for domain %s with value %s", env_from_domain, data)
task:insert_result('DYN_RL', 0.0, data)
end
end
local redis_ret_domain = rspamd_redis_make_request(task,
redis_params, -- connect params
env_from_domain, -- hash key
false, -- is write
redis_key_cb_domain, --callback
'HGET', -- command
{'RL_VALUE', env_from_domain} -- arguments
)
if not redis_ret_domain then
rspamd_logger.infox(rspamd_config, "cannot make request to load ratelimit for domain")
end
else
rspamd_logger.infox(rspamd_config, "found dynamic ratelimit in redis for user %s with value %s", env_from_addr, data)
task:insert_result('DYN_RL', 0.0, data)
end
end
local redis_ret_user = rspamd_redis_make_request(task,
redis_params, -- connect params
env_from_addr, -- hash key
false, -- is write
redis_cb_user, --callback
'HGET', -- command
{'RL_VALUE', env_from_addr} -- arguments
)
if not redis_ret_user then
rspamd_logger.infox(rspamd_config, "cannot make request to load ratelimit for user")
end
return true
end,
priority = 20
})