In einem voran gegangenen Artikel habe ich generell über Logging von Rspamd in Verbindung mit rsyslog geschrieben. In diesem Artikel zeige ich exemplarisch, wie man in den sogenannten „user settings“ Policies erstellen kann und eigene Symbole in die Log-Ausgabe integriert. Ferner verwende ich ein eigenes Log-Template in Rspamd, in dem ich Lua eingebaut habe.
Hier ein Beispiel meiner aktuellen rsyslog-Meldungen für Submission:
Nov 24 13:05:39 mx rspamd[13209]: <5f9508>; proxy; rspamd_task_write_log: qid: <3yjvz711jZzMnk8>, policy_bank: POLICY_SUBMISSION, message-id: <tset.elpmaxe@EA4A6B0354D7-FCF8-0CD4-F94C-9F4795B9>, ip: 2a05:bec0:28:1:134:255:226:248, smtp_from: <tset.elpmaxe@resu>, mime_from: tset.elpmaxe@resu, action: "no action" [-7.70/7.50] [BAYES_HAM(-3.00){100.00%;},MV_CASE(0.50){},MIME_GOOD(-0.20){multipart/signed;text/plain;},ARC_NA(0.00){},ASN(0.00){asn:197071, ipnet:2a05:bec0::/29, country:DE;},FROM_EQ_ENVFROM(0.00){},FROM_HAS_DN(0.00){},HAS_ATTACHMENT(0.00){},MID_RHS_MATCH_FROM(0.00){},PREVIOUSLY_DELIVERED(0.00)moc.liamg@rensseorrhc};},RCPT_COUNT_ONE(0.00){1;},RCVD_COUNT_TWO(0.00){2;},RCVD_NO_TLS_LAST(0.00){},RCVD_VIA_SMTP_AUTH(0.00){},TO_DN_NONE(0.00){},TO_MATCH_ENVRCPT_ALL(0.00){}]), len: 6331, time: 96.005ms real, 12.620ms virtual, dns req: 0, smtp_rcpts: <***@****>, mime_rcpts: <****@****>
Im Log taucht eine Information zu policy_bank auf.
Ausgangspunkt für mich war, dass ich ein verlässliches Merkmal im Log benötige, um in rsyslog Meldungen basierend auf dieser Information unterschiedlich zu behandeln.
User Settings in Rspamd können prinzipiell auf zei verschiedene Arten realisiert werden. Entweder man definiert setting {} innerhalb der Datei rspamd.conf.local oder settings_redis. In meinem Beispiel nutze ich Variante 1 und nutze zusätzlich eine Datei-Map:
settings = "file://$LOCAL_CONFDIR/maps.d/settings.map";
Wie man erkennen kann, liegt eine Datei namens settings.map in einem Unterverzeichnis maps.d. Dieses muss der Administrator selbst erstellen. Der Pfad ist dabei grundsätzlich frei wählbar.
Ohne zu sehr auf die Einzelheiten dieser Datei eingehen zu wollen, zeige ich beispielhaft, wie die Idee von Policy-Banks funktioniert.
settings {
whitelist {
symbols = [ "POLICY_WHITELIST" ];
priority = low;
rcpt = "postmaster";
rcpt = "abuse";
whitelist = yes;
}
SUBMISSION {
symbols = [ "POLICY_SUBMISSION" ];
priority = high;
request_header = {
"MTA-Tag" = "^mail\.example\.test$";
}
apply "default" {
groups_disabled = [
"rbl",
"surbl",
"spf",
"dkim",
"dmarc",
]
symbols_disabled = [
"DCC_BULK"
]
}
}
}
Dieses Beispiel zeigt zwei Policy-Banks. Jede dieser Regeln setzt ein eigenes Symbol beginnend mit „POLICY_“. Diese Symbole wurden selbst definiert und werden nur durch diese User-Settings gesetzt.
Hier die Definition der Symbole in der Datei /etc/rspamd/rspamd.local.lua:
-- rspamd.local.lua
-- Dummy symbols for user settings
rspamd_config.POLICY_WHITELIST = {
callback = function(task)
return false
end,
group = 'policies'
}
rspamd_config.POLICY_SUBMISSION = {
callback = function(task)
return false
end,
group = 'policies'
}
Diese Regeln benötigen noch einen Score. Und hier zeigt sich auch schon ein Vorteil: Admins können auf diese Weise verschiedenen Policy-Banks vorab Punkte schenken.
In der local.d/metrics.conf befindet sich folgende Definition:
group policies {
symbol "POLICY_WHITELIST" {
score 0.0;
description = "Postmaster and abuse whitelisted policy bank";
}
symbol "POLICY_SUBMISSION" {
score = -5.0;
description = "Submission policy bank";
}
}
Im letzten Schritt zeige ich, wie ich das Logging nun angepasst habe. Dazu definiere ich ein eigenes Logging-Template in der Datei local.d/logging.inc:
log_format =<<EOD
$if_qid{qid: <$>,}
$lua{
return function(task)
function string.starts(str, start)
return string.sub(str, 1, string.len(start)) == start
end
local syminf = task:get_symbols_all()
for _, sym in ipairs(syminf) do
if string.starts(sym.name, "POLICY_") then
return 'policy_bank: ' .. sym.name .. ','
end
end
return 'policy_bank: NA,'
end
}
message-id: <$mid>,$if_ip{ ip: $,}$if_user{ user: $,}
$if_smtp_from{smtp_from: <$>, }$if_mime_from{mime_from: $,}
action: "$action" [$scores] [$lua{
return function(task)
function string.starts(str, start)
return string.sub(str, 1, string.len(start)) == start
end
local l = {}
local syminf = task:get_symbols_all()
for _, sym in ipairs(syminf) do
if not string.starts(sym.name, "POLICY_") then
local txt
if sym.options then
local topt = table.concat(sym.options, ', ')
txt = sym.name .. '(' .. string.format('%.2f', sym.score) .. ')' .. '[' .. topt .. ']'
else
txt = sym.name .. '(' .. string.format('%.2f', sym.score) .. ')'
end
table.insert(l, txt)
end
end
return table.concat(l,',')
end
}]),
len: $len, time: $time_real real, $time_virtual virtual, dns req: $dns_req,
$if_smtp_rcpts{smtp_rcpts: <$>}$if_mime_rcpts{, mime_rcpts: <$>}
EOD
Viel Spaß
[ratings]
Rößner-Network-Solutions