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;
}
}
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";
}
}
}
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
});