From: Vsevolod Stakhov Date: Tue, 6 Aug 2024 12:45:27 +0000 (+0100) Subject: [Rework] Resolve rdns in a separate function X-Git-Tag: 3.10.0~65^2^2~1 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=e227bedc4f24b1ab5cf7feae0d2acb076ddcb312;p=rspamd.git [Rework] Resolve rdns in a separate function Historically, it was done in `once_received` module, however, that check must be done early, even before settings (as they could rely on hostname). Hence, it was discussed to move this code to a separate rule. --- diff --git a/conf/modules.d/once_received.conf b/conf/modules.d/once_received.conf index ab0749295..6fcc35bb6 100644 --- a/conf/modules.d/once_received.conf +++ b/conf/modules.d/once_received.conf @@ -14,8 +14,7 @@ once_received { good_host = "mail"; - bad_host = "static"; - bad_host = "dynamic"; + bad_host = ["static", "dynamic"]; symbol_strict = "ONCE_RECEIVED_STRICT"; symbol = "ONCE_RECEIVED"; symbol_mx = "DIRECT_TO_MX"; diff --git a/conf/scores.d/headers_group.conf b/conf/scores.d/headers_group.conf index 1c70ca588..972c6872a 100644 --- a/conf/scores.d/headers_group.conf +++ b/conf/scores.d/headers_group.conf @@ -50,14 +50,6 @@ symbols = { weight = 0.1; description = "One received header in a message"; } - "RDNS_NONE" { - weight = 2.0; - description = "Cannot resolve reverse DNS for sender's IP"; - } - "RDNS_DNSFAIL" { - weight = 0.0; - description = "PTR verification DNS error"; - } "ONCE_RECEIVED_STRICT" { weight = 4.0; description = "One received header with 'bad' patterns inside"; diff --git a/conf/scores.d/hfilter_group.conf b/conf/scores.d/hfilter_group.conf index 09fcfcd8d..21cd11a60 100644 --- a/conf/scores.d/hfilter_group.conf +++ b/conf/scores.d/hfilter_group.conf @@ -130,4 +130,12 @@ symbols = { weight = 2.5; description = "One line URL and text in body"; } + "RDNS_NONE" { + weight = 2.0; + description = "Cannot resolve reverse DNS for sender's IP"; + } + "RDNS_DNSFAIL" { + weight = 0.0; + description = "PTR verification DNS error"; + } } diff --git a/rules/misc.lua b/rules/misc.lua index faf4a8fb8..cbe90e561 100644 --- a/rules/misc.lua +++ b/rules/misc.lua @@ -862,3 +862,58 @@ rspamd_config.COMPLETELY_EMPTY = { group = 'blankspam', score = 15 } + +-- Check for the hostname if it was not set +local rnds_check_id = rspamd_config:register_symbol { + name = 'RDNS_CHECK', + callback = function(task) + if not task:get_hostname() then + -- Try to resolve + local task_ip = task:get_ip() + if task_ip and task_ip:is_valid() then + local rspamd_logger = require "rspamd_logger" + local function rdns_dns_cb(_, to_resolve, results, err) + if err and (err ~= 'requested record is not found' and err ~= 'no records with this name') then + rspamd_logger.errx(task, 'error looking up %s: %s', to_resolve, err) + task:insert_result('RDNS_DNSFAIL', 1.0) + end + + if not results then + task:insert_result('RDNS_NONE', 1.0) + else + rspamd_logger.infox(task, 'source hostname has not been passed to Rspamd from MTA, ' .. + 'but we could resolve source IP address PTR %s as "%s"', + to_resolve, results[1]) + task:set_hostname(results[1]) + end + end + task:get_resolver():resolve_ptr({ task = task, + name = task_ip:to_string(), + callback = rdns_dns_cb, + forced = true + }) + end + end + end, + type = 'prefilter', + priority = lua_util.symbols_priorities.top, + description = 'Check if hostname has been resolved by MTA', +} + +rspamd_config:register_symbol { + type = 'virtual', + name = 'RDNS_DNSFAIL', + score = 0.0, + description = 'DNS failure resolving RDNS', + group = 'hfilter', + parent = rnds_check_id, + +} +rspamd_config:register_symbol { + type = 'virtual', + name = 'RDNS_NONE', + score = 2.0, + description = 'DNS failure resolving RDNS', + group = 'hfilter', + parent = rnds_check_id, +} \ No newline at end of file diff --git a/src/plugins/lua/once_received.lua b/src/plugins/lua/once_received.lua index 2a5552ab9..5c5ff7986 100644 --- a/src/plugins/lua/once_received.lua +++ b/src/plugins/lua/once_received.lua @@ -19,10 +19,7 @@ if confighelp then end -- 0 or 1 received: = spam - local symbol = 'ONCE_RECEIVED' -local symbol_rdns = 'RDNS_NONE' -local symbol_rdns_dnsfail = 'RDNS_DNSFAIL' local symbol_mx = 'DIRECT_TO_MX' -- Symbol for strict checks local symbol_strict = nil @@ -47,54 +44,6 @@ local function check_quantity_received (task) return not h['flags']['artificial'] end, recvh)) - local function recv_dns_cb(_, to_resolve, results, err) - if err and (err ~= 'requested record is not found' and err ~= 'no records with this name') then - rspamd_logger.errx(task, 'error looking up %s: %s', to_resolve, err) - task:insert_result(symbol_rdns_dnsfail, 1.0) - end - - if not results then - if nreceived <= 1 then - task:insert_result(symbol, 1) - -- Avoid strict symbol inserting as the remaining symbols have already - -- quote a significant weight, so a message could be rejected by just - -- this property. - --task:insert_result(symbol_strict, 1) - -- Check for MUAs - local ua = task:get_header('User-Agent') - local xm = task:get_header('X-Mailer') - if (ua or xm) then - task:insert_result(symbol_mx, 1, (ua or xm)) - end - end - task:insert_result(symbol_rdns, 1) - else - rspamd_logger.infox(task, 'source hostname has not been passed to Rspamd from MTA, ' .. - 'but we could resolve source IP address PTR %s as "%s"', - to_resolve, results[1]) - task:set_hostname(results[1]) - - if good_hosts then - for _, gh in ipairs(good_hosts) do - if string.find(results[1], gh) then - return - end - end - end - - if nreceived <= 1 then - task:insert_result(symbol, 1) - for _, h in ipairs(bad_hosts) do - if string.find(results[1], h) then - - task:insert_result(symbol_strict, 1, h) - return - end - end - end - end - end - local task_ip = task:get_ip() if ((not check_authed and task:get_user()) or @@ -110,13 +59,39 @@ local function check_quantity_received (task) local hn = task:get_hostname() -- Here we don't care about received - if (not hn) and task_ip and task_ip:is_valid() then - task:get_resolver():resolve_ptr({ task = task, - name = task_ip:to_string(), - callback = recv_dns_cb, - forced = true - }) + if not hn then + if nreceived <= 1 then + task:insert_result(symbol, 1) + -- Avoid strict symbol inserting as the remaining symbols have already + -- quote a significant weight, so a message could be rejected by just + -- this property. + --task:insert_result(symbol_strict, 1) + -- Check for MUAs + local ua = task:get_header('User-Agent') + local xm = task:get_header('X-Mailer') + if (ua or xm) then + task:insert_result(symbol_mx, 1, (ua or xm)) + end + end return + else + if good_hosts then + for _, gh in ipairs(good_hosts) do + if string.find(hn, gh) then + return + end + end + end + + if nreceived <= 1 then + task:insert_result(symbol, 1) + for _, h in ipairs(bad_hosts) do + if string.find(hn, h) then + task:insert_result(symbol_strict, 1, h) + break + end + end + end end if nreceived <= 1 then @@ -181,10 +156,6 @@ if opts then for n, v in pairs(opts) do if n == 'symbol_strict' then symbol_strict = v - elseif n == 'symbol_rdns' then - symbol_rdns = v - elseif n == 'symbol_rdns_dnsfail' then - symbol_rdns_dnsfail = v elseif n == 'bad_host' then if type(v) == 'string' then bad_hosts[1] = v @@ -206,16 +177,6 @@ if opts then end end - rspamd_config:register_symbol({ - name = symbol_rdns, - type = 'virtual', - parent = id - }) - rspamd_config:register_symbol({ - name = symbol_rdns_dnsfail, - type = 'virtual', - parent = id - }) rspamd_config:register_symbol({ name = symbol_strict, type = 'virtual',