Rspamd
To add Guardian Mail
Updated: 2022-12-13
These instructions are for rspamd 3.x – if you aren’t running the latest version, you should be! You wouldn’t use an out-of-date Anti-Virus engine, so don’t run an out-of-date Anti-Spam engine.
You need to edit the following files (or create them if they don’t already exist).
/etc/rspamd/local.d/rbl.conf
rbls { abusix_dnsbls_lasthop { symbol = "RBL_AMI_LASTHOP"; rbl = "<APIKEY>.combined.mail.abusix.zone"; checks = [ "from" ]; unknown = false; returncodes { RBL_AMI_POLICY = [ "127.0.0.11", "127.0.0.12" ]; RBL_AMI_BLACK = [ "127.0.0.2", "127.0.0.3", "127.0.0.200" ]; RBL_AMI_EXPLOIT = [ "127.0.0.4" ]; } } abusix_dnsbls_authbl { symbol = "RBL_AMI_AUTHBL"; rbl = "<APIKEY>.authbl.mail.abusix.zone"; checks = [ "from" ]; exclude_users = false; } abusix_dnsbls_anyhop { symbol = "RBL_AMI_RCVD"; rbl = "<APIKEY>.combined.mail.abusix.zone"; checks = [ "received" ]; unknown = false; returncodes { RBL_AMI_BLACK_RCVD = [ "127.0.0.2", "127.0.0.3", "127.0.0.200" ]; RBL_AMI_EXPLOIT_RCVD = "127.0.0.4"; } } abusix_dnsbls_noip { symbol = "RBL_AMI_NOIP"; rbl = "<APIKEY>.noip.mail.abusix.zone"; checks = [ "from", "received" ]; } abusix_dnsbls_dblack { symbol = "RBL_AMI_DBLACK"; rbl = "<APIKEY>.dblack.mail.abusix.zone"; checks = [ "content_urls", "dkim" ]; selector = "urls:get_host"; } abusix_dnsbls_nod { symbol = "RBL_AMI_NOD"; rbl = "<APIKEY>.nod.mail.abusix.zone"; checks = [ "content_urls", "dkim", "urls" ]; } abusix_dnsbls_emailbl { symbol = "RBL_AMI_EMAILBL"; rbl = "<APIKEY>.emailbl.mail-beta.abusix.zone"; selector = "from('mime').lower;from('smtp').lower"; checks = ['emails', 'replyto']; hash = "sha1"; } abusix_dnsbls_attachments { symbol = "RBL_AMI_ATTACH"; rbl = "<APIKEY>.attachhash.mail-beta.abusix.zone"; selector = "attachments('hex', 'sha1')"; } abusix_dnswls_lasthop { symbol = "RWL_AMI_LASTHOP"; rbl = "<APIKEY>.white.mail.abusix.zone"; checks = [ "from" ]; is_whitelist = true; } }
Replace <APIKEY> in all places with “Your API key” from your account in app.abusix.com.
/etc/rspamd/local.d/groups.conf
group "abusix" { description = "Guardian Mail" symbols = { "RBL_AMI_BLACK" { score = 6.5; description = "Delivered by a host in the Guardian Mail Block list"; } "RBL_AMI_EXPLOIT" { score = 6.5; description = "Delivered by a host in the Guardian Mail Exploit list"; } "RBL_AMI_POLICY" { score = 2.0; description = "Delivered by a host in the Guardian Mail Policy list"; } "RBL_AMI_AUTHBL" { score = 15.0; description = "Delivered by a host in the Guardian Mail Authentication block list"; } "RBL_AMI_BLACK_RCVD" { score = 3.0; description = "Received via a host in the Guardian Mail Black list"; } "RBL_AMI_EXPLOIT_RCVD" { score = 3.0; description = "Received via a host in the Guardian Mail Exploit list"; } "RBL_AMI_BLACK_HTTP" { score = 4.5; description = "Message was injected via HTTP from a host in the Guardian Mail Block list"; } "RBL_AMI_NOIP" { score = 4.5; description = "Delivered or Received via a host in the Guardian Mail Newly Observed IPs list"; } "RWL_AMI_LASTHOP" { score = -1.0; description = "Delivered by a host in the Guardian Mail White list"; } "RBL_AMI_DBLACK" { score = 6.5; description = "Message contains a domain listed in the Guardian Mail Block list"; } "RBL_AMI_NOD" { score = 2.0; description = "Message contains a domain listed in the Guardian Mail Newly Observed Domains list"; } "RBL_AMI_EMAILBL" { score = 4.5; description = "Message contains an email address listed in the Guardian Mail Email block list"; } "RBL_AMI_BTC" { score = 6.5; description = "Message contains a Bitcoin wallet address listed in the Guardian Mail BTC Wallet block list"; } "RBL_AMI_SHORTURL" { score = 6.5; description = "Message contains a Short URL listed in the Guardian Mail Short URL block list"; } "RBL_AMI_DISKURL" { score = 6.5; description = "Message contains a Disk URL listed in the Guardian Mail Disk URL block list"; } "RBL_AMI_ATTACH" { score = 4.5; description = "Message contains an attachment listed in the Guardian Mail Attachment block list"; } } }
/etc/rspamd/rspamd.local.lua
IMPORTANT:
If you use rsync, change the check_*_dns
values to reflect the namespace in your local rbldnsd that should be queried.
You can comment out the relevant check_*_dns
setting to disable the lookup.
local rregexp = require "rspamd_regexp" local rlogger = require "rspamd_logger" local rhash = require "rspamd_cryptobox_hash" local rutil = require "lua_util" local rip = require "rspamd_ip" -- IMPORTANT: change <APIKEY> with the key from your account in app.abusix.com. local ABUSIX_API_KEY = '<APIKEY>'; -- Comment any of the following lines out to disable the lookups -- NOTE: if you run rbldnsd yourself and rsync the data then you might need to modify these. local check_shorturls_dns = '.' .. ABUSIX_API_KEY .. '.shorthash.mail.abusix.zone.' local check_diskurls_dns = '.' .. ABUSIX_API_KEY .. '.diskhash.mail.abusix.zone.' local check_web_submission_dns = '.' .. ABUSIX_API_KEY .. '.combined.mail.abusix.zone.' local check_btc_dns = '.' .. ABUSIX_API_KEY .. '.btc-wallets.mail-beta.abusix.zone.' local re_short_path = rregexp.create_cached('/^(?!(?:[a-z]+|[A-Z]+|[0-9]+)$)[a-zA-Z0-9]{3,11}$/') local check_shorturls_cb = function (task) -- Disable checks if no DNS namespace is set-up if not (check_shorturls_dns) then return false end local function find_short_urls (url) local path = url:get_path(); if (re_short_path:match(path)) then return true end end local shorturls = rutil.extract_specific_urls({ task = task, limit = 5, prefix = 'shorturls', filter = find_short_urls }); if (not shorturls) then return false end local r = task:get_resolver() for _, url in pairs(shorturls) do -- Normalize local surl = url:get_host():lower() .. '/' .. url:get_path() local surl_hash = rhash.create_specific('sha1', surl):hex() local lookup = surl_hash .. check_shorturls_dns local function dns_cb(_,_,results,err) if (not results) then return false end if (tostring(results[1]) == '127.0.3.1') then rlogger.errx('found URL %s (%s) in Short URL blacklist', surl, surl_hash) return task:insert_result('RBL_AMI_SHORTURL', 1.0, surl); end end r:resolve_a({ task = task, name = lookup , callback = dns_cb }) end end local check_shorturls = rspamd_config:register_symbol({ name = "RBL_AMI_SHORTURL", type = "callback", callback = check_shorturls_cb }); local re_disk_urls = rregexp.create_cached('/^(?:drive\\.google\\.com$|yadi\\.sk$|disk\\.yandex\\.)/') local check_diskurls_cb = function (task) -- Disable checks if no DNS namespace is set-up if not (check_diskurls_dns) then return false end local function find_disk_urls (url) local host = url:get_host():lower(); if (re_disk_urls:match(host)) then return true end end local diskurls = rutil.extract_specific_urls({ task = task, limit = 5, prefix = 'diskurls', filter = find_disk_urls }); if (not diskurls) then return false end local r = task:get_resolver() for _, url in pairs(diskurls) do -- Normalize local durl = url:get_host():lower() .. '/' .. url:get_path() local durl_hash = rhash.create_specific('sha1', durl):hex() local lookup = durl_hash .. check_diskurls_dns local function dns_cb(_,_,results,err) if (not results) then return false end if (tostring(results[1]) == '127.0.3.2') then rlogger.errx('found URL %s (%s) in Disk URL blacklist', durl, durl_hash) return task:insert_result('RBL_AMI_DISKURL', 1.0, durl); end end r:resolve_a({ task = task, name = lookup , callback = dns_cb }) end end local check_diskurls = rspamd_config:register_symbol({ name = "RBL_AMI_DISKURL", type = "callback", callback = check_diskurls_cb }); local re_web_submission_ips = rregexp.create_cached('/for (.+)$/') local check_web_submission_ips_cb = function (task) -- Disable checks if no DNS namespace is set-up if not (check_web_submission_dns) then return false end local ips if (task:has_header('x-php-script')) then local h = task:get_header('x-php-script') local m = re_web_submission_ips:search(h, false, true) if (m and m[1] and m[1][2]) then ips = m[1][2] end end if (task:has_header('http-posting-client')) then if (ips) then ips = ips .. ' ' .. task:get_header('http-posting-client') else ips = task:get_header('http-posting-client') end end if not (ips) then return false end local dedup = {} for ip in string.gmatch(ips, '([^, ]+)') do dedup[ip] = true; end local c = task:get_from_ip() local cip if (c) then cip = c:to_string() end local r = task:get_resolver() for k, v in pairs(dedup) do -- Exclude IPs that match the From IP if (k ~= cip) then local ip4 = rip.from_string(k) if not (ip4) then goto continue end local lookup = table.concat(ip4:inversed_str_octets(), '.') .. check_web_submission_dns local function dns_cb(_,_,results,err) rlogger.errx('lookup=%s, results=%s, err=%s', lookup, results, err) if (not results) then return false end for _, result in ipairs(results) do if (tostring(result) == '127.0.0.4') then return task:insert_result('RBL_AMI_BLACK_HTTP', 1.0, k); end end end r:resolve_a({ task = task, name = lookup , callback = dns_cb }) ::continue:: end end end local check_diskurls = rspamd_config:register_symbol({ name = "RBL_AMI_BLACK_HTTP", type = "callback", callback = check_web_submission_ips_cb }); local btc_wallet_re = rregexp.create_cached('/(?:^|\\s)((?:[13]|bc1)[A-HJ-NP-Za-km-z1-9]{27,34})(?:\\s|$)/') local check_btc_cb = function (task) -- Disable checks if no DNS namespace is set-up if not (check_btc_dns) then return false end local parts = task:get_text_parts() if not parts then return false end local r = task:get_resolver() for _, part in ipairs(parts) do local words = part:get_words('raw') for _, word in ipairs(words) do local match = btc_wallet_re:match(word) if match then local btc_hash = rhash.create_specific('sha1', word):hex() local lookup = btc_hash .. check_btc_dns local function dns_cb(_,_,results,err) if (not results) then return false end if (tostring(results[1]) == '127.0.4.1') then rlogger.errx('found BTC wallet %s (%s) in BTC Wallet blacklist', word, btc_hash) return task:insert_result('RBL_AMI_BTC', 1.0, word); end end r:resolve_a({ task = task, name = lookup , callback = dns_cb, forced = true }) end end end end local check_btc = rspamd_config:register_symbol({ name = "RBL_AMI_BTC", type = "callback", callback = check_btc_cb });
Replace <APIKEY> in all places with “Your API key” from your account in app.abusix.com.
Once you have created these files, restart rspamd.