Integrate the reputation service in your mail filter
Classic DNSBL at dnsbl.bsnsoft-hostings.de. HTTP API available as an alternative transport.
Classification
The service answers with one of five classifications, encoded in the DNS return code:
| Score | Class | Symbol | DNS return | Recommended weight |
|---|---|---|---|---|
| 9 | TOP | BSN_REP_TOP | 127.0.0.0 | −2.0 (bonus) |
| 7–8 | HIGH | BSN_REP_HIGH | 127.0.0.[1-2] | −0.5 (small bonus) |
| 4–6 | MEDIUM | BSN_REP_MEDIUM | 127.0.0.[3-5] | +1.0 |
| 2–3 | LOW | BSN_REP_LOW | 127.0.0.[6-7] | +4.0 |
| 0–1 | BAD | BSN_REP_BAD | 127.0.0.[8-9] | +6.0 |
With an RSpamD reject threshold of 12, our maximum contribution (+6.0) stays below half – our signal alone never rejects a message; only in combination with another indicator (DMARC fail, Bayes, IP RBL, …).
RSpamD · Lua plugin (recommended)
Sender-domain lookup via our DNSBL. Small Lua file, loaded once, runs for every message. This is the cleanest integration for sender-domain reputation.
Step 1 – save as /etc/rspamd/local.d/bsn_reputation.lua:
local rspamd_logger = require "rspamd_logger"
local N = "bsn_reputation"
local RBL = "dnsbl.bsnsoft-hostings.de"
local function reputation_cb(task)
local from = task:get_from("smtp")
if not from or not from[1] then from = task:get_from("mime") end
if not from or not from[1] then return false end
local domain = (from[1]["domain"] or ""):lower()
if domain == "" then return false end
local resolver = task:get_resolver()
if not resolver then return false end
resolver:resolve_a({
task = task,
name = domain .. "." .. RBL,
callback = function(_, _, results, err)
if err or not results or #results == 0 then return end
local last = tonumber(tostring(results[1]):match("%.(%d+)$"))
if not last then return end
local sym
if last == 0 then sym = "BSN_REP_TOP"
elseif last <= 2 then sym = "BSN_REP_HIGH"
elseif last <= 5 then sym = "BSN_REP_MEDIUM"
elseif last <= 7 then sym = "BSN_REP_LOW"
else sym = "BSN_REP_BAD"
end
task:insert_result(sym, 1.0, domain)
end,
})
return false
end
local id = rspamd_config:register_symbol({
name = "BSN_REPUTATION_CHECK", type = "callback", callback = reputation_cb,
})
for _, sub in ipairs({"BSN_REP_TOP","BSN_REP_HIGH","BSN_REP_MEDIUM","BSN_REP_LOW","BSN_REP_BAD"}) do
rspamd_config:register_symbol({ name = sub, type = "virtual", parent = id, group = N })
end
rspamd_logger.infox(rspamd_config, "%s: loaded (zone=%s)", N, RBL)
Step 2 – activate it by adding this line to /etc/rspamd/rspamd.local.lua:
dofile("/etc/rspamd/local.d/bsn_reputation.lua")
Step 3 – set weights in /etc/rspamd/local.d/scores.conf:
BSN_REP_TOP = -2.0;
BSN_REP_HIGH = -0.5;
BSN_REP_MEDIUM = 1.0;
BSN_REP_LOW = 4.0;
BSN_REP_BAD = 6.0;
Step 4 – systemctl restart rspamd. Verify with:
printf "From: t@heise.de\nTo: r@x.de\nSubject: t\n\nbody\n" | \
rspamc -F "t@heise.de" - | grep BSN_REP
RSpamD · rbl module (optional, for body-URLs)
The Lua plugin above covers sender-domain reputation. If you additionally
want to match domains that appear as URLs inside the body text, add the native
rbl module on top. Be careful not to set weights that double-count
between sender-based (Lua) and URL-based (rbl) hits.
File /etc/rspamd/local.d/rbl.conf:
rbls {
bsnsoft_reputation_urls {
symbol = "BSN_URL_REPUTATION";
rbl = "dnsbl.bsnsoft-hostings.de";
checks = ["urls", "content_urls"];
emails_domainonly = true;
unknown = false;
returncodes {
BSN_URL_TOP = "127.0.0.0";
BSN_URL_HIGH = "127.0.0.[1-2]";
BSN_URL_MEDIUM = "127.0.0.[3-5]";
BSN_URL_LOW = "127.0.0.[6-7]";
BSN_URL_BAD = "127.0.0.[8-9]";
}
}
}
Separate symbol names (BSN_URL_*) prevent double-scoring with the Lua sender-check
(BSN_REP_*). Typical weights: use smaller numbers for URL hits, since most legit mails
contain URLs to mid-reputation domains (shorteners, trackers).
Weights in /etc/rspamd/local.d/scores.conf:
symbols {
"BSN_REP_TOP" { score = -2.0; description = "Top reputation"; }
"BSN_REP_HIGH" { score = -0.5; description = "Strong reputation"; }
"BSN_REP_MEDIUM" { score = 1.0; description = "Neutral / unclear reputation"; }
"BSN_REP_LOW" { score = 4.0; description = "Weak reputation"; }
"BSN_REP_BAD" { score = 6.0; description = "Throwaway / spam infrastructure"; }
}
Reload after changes: systemctl reload rspamd.
Postfix · postfwd policy
If RSpamD is not in use, a policy daemon such as postfwd can query the DNSBL:
id=BSN_REP_REJECT ; client_address!~=^127\. ; sender_domain_in_dnsbl==dnsbl.bsnsoft-hostings.de ; action=REJECT Poor sender reputation
HTTP API
Single lookup:
curl https://dnsbl.bsnsoft-hostings.de/api/score/example.com
Response format:
{
"rawInput": "example.com",
"normalizedDomain": "example.com",
"score": 8,
"classification": "HIGH",
"status": "INDEXED"
}
Status values:
| Status | Meaning |
|---|---|
INDEXED | Score available in score / classification |
INVALID_DOMAIN | Input is not a valid domain |
Set generous client timeouts (at least 90 seconds).
Questions or enterprise usage?
Contact: info@bsnsoft.de · bsnsoft.de