First Shot

Signed-off-by: Patrick Niebeling <patrick.niebeling@adacor.com>
This commit is contained in:
Patrick Niebeling
2024-11-06 17:13:46 +01:00
parent 64e203ed61
commit de7350baab
76 changed files with 3667 additions and 0 deletions

View File

@ -0,0 +1,3 @@
reject = 15;
add_header = 8;
greylist = 7;

View File

@ -0,0 +1,11 @@
clamav {
# Scan whole message
scan_mime_parts = false;
#scan_text_mime = true;
#scan_image_mime = true;
symbol = "CLAM_VIRUS";
type = "clamav";
log_clean = true;
servers = "clamd:3310";
max_size = 20971520;
}

View File

@ -0,0 +1,32 @@
# If false, messages with empty envelope from are not signed
allow_envfrom_empty = true;
# If true, envelope/header domain mismatch is ignored
allow_hdrfrom_mismatch = true;
# If true, multiple from headers are allowed (but only first is used)
allow_hdrfrom_multiple = false;
# If true, username does not need to contain matching domain
allow_username_mismatch = false;
# If false, messages from authenticated users are not selected for signing
sign_authenticated = false;
# Default path to key, can include '$domain' and '$selector' variables
path = "/data/dkim/keys/$domain.dkim";
# Default selector to use
selector = "dkim";
# If false, messages from local networks are not selected for signing
sign_local = false;
# Symbol to add when message is signed
symbol = "ARC_SIGNED";
# Whether to fallback to global config
try_fallback = true;
# Domain to use for DKIM signing: can be "header" or "envelope"
use_domain = "recipient";
# Whether to normalise domains to eSLD
use_esld = false;
# Whether to get keys from Redis
use_redis = true;
# Hash for DKIM keys in Redis
key_prefix = "DKIM_PRIV_KEYS";
# Selector map
selector_prefix = "DKIM_SELECTORS";
sign_inbound = true;
use_domain_sign_inbound = "recipient";

View File

@ -0,0 +1,6 @@
provider_type = "rspamd";
provider_info {
ip4 = "asn.rspamd.com";
ip6 = "asn6.rspamd.com";
}
symbol = "ASN";

View File

@ -0,0 +1,110 @@
MX_IMPLICIT {
expression = "MX_GOOD & MX_MISSING";
score = -0.01;
}
VIRUS_FOUND {
expression = "CLAM_VIRUS & !MAILCOW_WHITE";
score = 2000.0;
}
# Bad policy from free mail providers
FREEMAIL_POLICY_FAILURE {
expression = "FREEMAIL_FROM & !DMARC_POLICY_ALLOW & !MAILLIST& !WHITELISTED_FWD_HOST & -g+:policies";
score = 16.0;
}
# Applies to freemail with undisclosed recipients
FREEMAIL_TO_UNDISC_RCPT {
expression = "FREEMAIL_FROM & ( MISSING_TO | R_UNDISC_RCPT | TO_EQ_FROM )";
score = 5.0;
}
# Bad policy from non-whitelisted senders
# Remove SOGO_CONTACT symbol for fwd hosts and senders with broken policy
SOGO_CONTACT_EXCLUDE {
expression = "(-WHITELISTED_FWD_HOST | -g+:policies) & ^SOGO_CONTACT & !DMARC_POLICY_ALLOW";
}
# Remove MAILCOW_WHITE symbol for senders with broken policy recieved not from fwd hosts
MAILCOW_WHITE_EXCLUDE {
expression = "^MAILCOW_WHITE & (-DMARC_POLICY_REJECT | -DMARC_POLICY_QUARANTINE | -R_SPF_PERMFAIL) & !WHITELISTED_FWD_HOST";
}
# Spoofed header from and broken policy (excluding sieve host, rspamd host, whitelisted senders, authenticated senders and forward hosts)
SPOOFED_UNAUTH {
expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & !RSPAMD_HOST & !SIEVE_HOST & MAILCOW_DOMAIN_HEADER_FROM & !WHITELISTED_FWD_HOST & -g+:policies";
score = 50.0;
}
# Only apply to inbound unauthed and not whitelisted
OLEFY_MACRO {
expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & OLETOOLS";
score = 20.0;
policy = "remove_weight";
}
# Applies to a content filter map
BAD_WORD_BAD_TLD {
expression = "FISHY_TLD & ( BAD_WORDS | BAD_WORDS_DE )";
score = 10.0;
}
# Forged with bad policies and not fwd host, keep bad policy symbols
FORGED_W_BAD_POLICY {
expression = "( -g+:policies | -R_SPF_NA) & ( ~FROM_NEQ_ENVFROM | ~FORGED_SENDER ) & !WHITELISTED_FWD_HOST & !DMARC_POLICY_ALLOW";
score = 3.0;
}
# Keep negative (good) scores for rbl, policies and hfilter, disable neural group
WL_FWD_HOST {
expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)";
}
# Exclude X-Spam like flags from scoring from fwd and sieve hosts
UPSTREAM_CHECKS_EXCLUDE_FWD_HOST {
expression = "(-SIEVE_HOST | -WHITELISTED_FWD_HOST) & (^UNITEDINTERNET_SPAM | ^SPAM_FLAG | ^KLMS_SPAM | ^AOL_SPAM | ^MICROSOFT_SPAM)";
}
# Remove fuzzy group from bounces
BOUNCE_FUZZY {
expression = "-BOUNCE & ^g+:fuzzy";
}
# Remove bayes ham if fuzzy denied
FUZZY_HAM_MISMATCH {
expression = "( -FUZZY_DENIED | -MAILCOW_FUZZY_DENIED | -LOCAL_FUZZY_DENIED ) & ( ^BAYES_HAM | ^NEURAL_HAM_LONG | ^NEURAL_HAM_SHORT )";
}
# Remove bayes spam if local fuzzy white
FUZZY_SPAM_MISMATCH {
expression = "( -LOCAL_FUZZY_WHITE ) & ( ^BAYES_SPAM | ^NEURAL_SPAM_LONG | ^NEURAL_SPAM_SHORT )";
}
WL_FWD_HOST {
expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)";
}
ENCRYPTED_CHAT {
expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP";
}
CLAMD_SPAM_FOUND {
expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE";
description = "Probably Spam, Securite Spam Flag set through ClamAV";
score = 5;
}
CLAMD_BAD_PDF {
expression = "CLAM_SECI_PDF & !MAILCOW_WHITE";
description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV";
score = 8;
}
CLAMD_BAD_JPG {
expression = "CLAM_SECI_JPG & !MAILCOW_WHITE";
description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV";
score = 8;
}
CLAMD_ASCII_MALWARE {
expression = "CLAM_SECI_ASCII & !MAILCOW_WHITE";
description = "ASCII malware found, Securite ASCII malware Flag set through ClamAV";
score = 8;
}
CLAMD_HTML_MALWARE {
expression = "CLAM_SECI_HTML & !MAILCOW_WHITE";
description = "HTML malware found, Securite HTML malware Flag set through ClamAV";
score = 8;
}
CLAMD_JS_MALWARE {
expression = "CLAM_SECI_JS & !MAILCOW_WHITE";
description = "JS malware found, Securite JS malware Flag set through ClamAV";
score = 8;
}

View File

@ -0,0 +1,35 @@
# If false, messages with empty envelope from are not signed
allow_envfrom_empty = true;
# If true, envelope/header domain mismatch is ignored
allow_hdrfrom_mismatch = true;
# If true, multiple from headers are allowed (but only first is used)
allow_hdrfrom_multiple = true;
# If true, username does not need to contain matching domain
allow_username_mismatch = true;
# If false, messages from authenticated users are not selected for signing
sign_authenticated = true;
# Default path to key, can include '$domain' and '$selector' variables
path = "/data/dkim/keys/$domain.dkim";
# Default selector to use
selector = "dkim";
# If false, messages from local networks are not selected for signing
sign_local = true;
# Symbol to add when message is signed
symbol = "DKIM_SIGNED";
# Whether to fallback to global config
try_fallback = true;
# Domain to use for DKIM signing: can be "header" or "envelope"
use_domain = "envelope";
# Whether to normalise domains to eSLD
use_esld = false;
# Whether to get keys from Redis
use_redis = true;
# Hash for DKIM keys in Redis
key_prefix = "DKIM_PRIV_KEYS";
# Selector map
selector_prefix = "DKIM_SELECTORS";
# Sieve is in sign_networks only
# forwards are arc signed, rejects are dkim signed
sign_networks = "/etc/rspamd/custom/dovecot_trusted.map";
use_domain_sign_networks = "header";
sign_headers = "from:sender:reply-to:subject:date:message-id:to:cc:mime-version:content-type:content-transfer-encoding:content-language:resent-to:resent-cc:resent-from:resent-sender:resent-message-id:in-reply-to:references:list-id:list-help:list-owner:list-unsubscribe:list-subscribe:list-post:list-unsubscribe-post:disposition-notification-to:disposition-notification-options:original-recipient:openpgp:autocrypt";

View File

@ -0,0 +1,12 @@
oletools {
# default olefy settings
servers = "olefy:10055";
# needs to be set explicitly for Rspamd < 1.9.5
scan_mime_parts = true;
# mime-part regex matching in content-type or filename
# block all macros
extended = true;
max_size = 3145728;
timeout = 20.0;
retransmits = 1;
}

View File

@ -0,0 +1,12 @@
rules {
WHITELIST_FORWARDING_HOST_NO_REJECT {
action = "add header";
expression = "WHITELISTED_FWD_HOST";
require_action = ["reject"];
}
WHITELIST_FORWARDING_HOST_NO_GREYLIST {
action = "no action";
expression = "WHITELISTED_FWD_HOST";
require_action = ["greylist", "soft reject"];
}
}

View File

@ -0,0 +1,54 @@
rule "local" {
# Fuzzy storage server list
servers = "localhost:11445";
# Default symbol for unknown flags
symbol = "LOCAL_FUZZY_UNKNOWN";
# Additional mime types to store/check
mime_types = ["application/*"];
# Hash weight threshold for all maps
max_score = 100.0;
# Whether we can learn this storage
read_only = no;
# Ignore unknown flags
skip_unknown = yes;
# Hash generation algorithm
algorithm = "mumhash";
# Map flags to symbols
fuzzy_map = {
LOCAL_FUZZY_DENIED {
max_score = 10.0;
flag = 11;
}
LOCAL_FUZZY_WHITE {
max_score = 5.0;
flag = 13;
}
}
}
rule "mailcow" {
# Fuzzy storage server list
servers = "fuzzy.mailcow.email:11445";
# Default symbol for unknown flags
symbol = "MAILCOW_FUZZY_UNKNOWN";
# Additional mime types to store/check
mime_types = ["application/*"];
# Hash weight threshold for all maps
max_score = 100.0;
# Whether we can learn this storage
read_only = yes;
# Ignore unknown flags
skip_unknown = yes;
# Hash generation algorithm
algorithm = "mumhash";
# Encrypt connection
encryption_key = "oa7xjgdr9u7w3hq1xbttas6brgau8qc17yi7ur5huaeq6paq8h4y";
# Map flags to symbols
fuzzy_map = {
MAILCOW_FUZZY_DENIED {
max_score = 10.0;
flag = 11;
}
}
}

View File

@ -0,0 +1,17 @@
symbols = {
"LOCAL_FUZZY_UNKNOWN" {
weight = 0.1;
}
"LOCAL_FUZZY_DENIED" {
weight = 15.0;
}
"MAILCOW_FUZZY_UNKNOWN" {
weight = 0.1;
}
"MAILCOW_FUZZY_DENIED" {
weight = 7.0;
}
"LOCAL_FUZZY_WHITE" {
weight = -10.0;
}
}

View File

@ -0,0 +1,4 @@
whitelisted_ip = "http://nginx:8081/forwardinghosts.php";
ipv4_mask = 24;
ipv6_mask = 64;
message = "Greylisted, please try again later";

View File

@ -0,0 +1,59 @@
symbols {
"MAILCOW_AUTH" {
description = "mailcow authenticated";
score = -20.0;
}
"CTYPE_MIXED_BOGUS" {
score = 0.0;
}
"BAD_REP_POLICIES" {
score = 2.0;
}
"BAD_HEADER" {
score = 10.0;
}
"BULK_HEADER" {
score = 4.0;
}
"ENCRYPTED_CHAT" {
score = -20.0;
}
"SOGO_CONTACT" {
score = -99.0;
}
}
group "MX" {
"MX_INVALID" {
score = 0.5;
description = "No connectable MX";
one_shot = true;
}
"MX_MISSING" {
score = 2.0;
description = "No MX record";
one_shot = true;
}
"MX_GOOD" {
score = -0.01;
description = "MX was ok";
one_shot = true;
}
}
group "reputation" {
symbols = {
"IP_REPUTATION_HAM" {
weight = 1.0;
}
"IP_REPUTATION_SPAM" {
weight = 4.0;
}
"SENDER_REP_HAM" {
weight = 1.0;
}
"SENDER_REP_SPAM" {
weight = 2.0;
}
}
}

View File

@ -0,0 +1,7 @@
symbols = {
"R_MIXED_CHARSET" {
weight = 1.0;
description = "Mixed characters in a message";
one_shot = true;
}
}

View File

@ -0,0 +1,5 @@
symbols = {
"HFILTER_HOSTNAME_UNKNOWN" {
score = 8.5;
}
}

View File

@ -0,0 +1 @@
nrows = 1000;

View File

@ -0,0 +1,72 @@
rules {
QUARANTINE {
backend = "http";
url = "http://nginx:9081/pipe.php";
selector = "reject_no_global_bl";
formatter = "default";
meta_headers = true;
}
RLINFO {
backend = "http";
url = "http://nginx:9081/pipe_rl.php";
selector = "ratelimited";
formatter = "json";
}
PUSHOVERMAIL {
backend = "http";
url = "http://nginx:9081/pushover.php";
selector = "mailcow_rcpt";
formatter = "json";
meta_headers = true;
}
}
custom_select {
mailcow_rcpt = <<EOD
return function(task)
local action = task:get_metric_action('default')
if task:has_symbol('NO_LOG_STAT') or (action == 'soft reject' or action == 'reject' or action == 'add header' or action == 'rewrite subject') then
return false
else
if task:get_symbol("RCPT_MAILCOW_DOMAIN") then
return true
end
return false
end
end
EOD;
ratelimited = <<EOD
return function(task)
local ratelimited = task:get_symbol("RATELIMITED")
if ratelimited then
return true
end
return false
end
EOD;
reject_no_global_bl = <<EOD
return function(task)
if not task:has_symbol('GLOBAL_SMTP_FROM_BL')
and not task:has_symbol('GLOBAL_MIME_FROM_BL')
and not task:has_symbol('LOCAL_BL_ASN')
and not task:has_symbol('GLOBAL_RCPT_BL')
and not task:has_symbol('BAD_SUBJECT_00')
and not task:has_symbol('MAILCOW_BLACK') then
local action = task:get_metric_action('default')
if action == 'reject' or action == 'add header' or action == 'rewrite subject' then
return true
end
end
return false
end
EOD;
}
custom_format {
msgid = <<EOD
return function(task)
return task:get_message_id()
end
EOD;
}

View File

@ -0,0 +1,43 @@
use = ["spam-header", "x-spamd-result", "x-rspamd-queue-id", "authentication-results", "fuzzy-hashes"];
skip_local = false;
skip_authenticated = true;
routines {
spam-header {
header = "X-Spam-Flag";
value = "YES";
remove = 1;
}
fuzzy-hashes {
header = "X-Rspamd-Fuzzy";
}
authentication-results {
header = "Authentication-Results";
add_smtp_user = false;
remove = 1;
spf_symbols {
pass = "R_SPF_ALLOW";
fail = "R_SPF_FAIL";
softfail = "R_SPF_SOFTFAIL";
neutral = "R_SPF_NEUTRAL";
temperror = "R_SPF_DNSFAIL";
none = "R_SPF_NA";
permerror = "R_SPF_PERMFAIL";
}
dkim_symbols {
pass = "R_DKIM_ALLOW";
fail = "R_DKIM_REJECT";
temperror = "R_DKIM_TEMPFAIL";
none = "R_DKIM_NA";
permerror = "R_DKIM_PERMFAIL";
}
dmarc_symbols {
pass = "DMARC_POLICY_ALLOW";
permerror = "DMARC_BAD_POLICY";
temperror = "DMARC_DNSFAIL";
none = "DMARC_NA";
reject = "DMARC_POLICY_REJECT";
softfail = "DMARC_POLICY_SOFTFAIL";
quarantine = "DMARC_POLICY_QUARANTINE";
}
}
}

View File

@ -0,0 +1,47 @@
# Extensions that are treated as 'bad'
# Number is score multiply factor
bad_extensions = {
scr = 20,
lnk = 20,
exe = 20,
msi = 1,
msp = 1,
msu = 1,
jar = 2,
com = 20,
bat = 4,
cmd = 4,
ps1 = 4,
ace = 4,
arj = 4,
cab = 20,
vbs = 20,
hta = 4,
shs = 4,
wsc = 4,
wsf = 4,
iso = 8,
img = 8
};
# Extensions that are particularly penalized for archives
bad_archive_extensions = {
pptx = 0.5,
docx = 0.5,
xlsx = 0.5,
pdf = 1.0,
jar = 3,
js = 0.5,
vbs = 20,
exe = 20
};
# Used to detect another archive in archive
archive_extensions = {
zip = 1,
arj = 1,
rar = 1,
ace = 1,
7z = 1,
cab = 1
};

View File

@ -0,0 +1,7 @@
symbols = {
"MIME_DOUBLE_BAD_EXTENSION" {
weight = 0; # This rule has dynamic weight up to 4.0
description = "Bad extension cloaking";
one_shot = true;
}
}

View File

@ -0,0 +1,181 @@
RCPT_MAILCOW_DOMAIN {
type = "rcpt";
filter = "email:domain";
map = "redis://DOMAIN_MAP";
symbols_set = ["RCPT_MAILCOW_DOMAIN"];
}
WHITELISTED_FWD_HOST {
type = "ip";
map = "redis://WHITELISTED_FWD_HOST";
symbols_set = ["WHITELISTED_FWD_HOST"];
}
BULK_HEADER {
type = "content";
map = "${LOCAL_CONFDIR}/custom/bulk_header.map";
filter = "headers"
regexp = true;
symbols_set = ["BULK_HEADER"];
}
CHAT_VERSION_HEADER {
type = "header";
header = "Chat-Version";
map = "${LOCAL_CONFDIR}/custom/chat_versions.map";
regexp = true;
symbols_set = ["CHAT_VERSION_HEADER"];
}
BAD_HEADER {
type = "content";
map = "${LOCAL_CONFDIR}/custom/bad_header.map";
filter = "headers"
regexp = true;
symbols_set = ["BAD_HEADER"];
}
LOCAL_BL_ASN {
require_symbols = "!MAILCOW_WHITE";
type = "asn";
map = "${LOCAL_CONFDIR}/custom/bad_asn.map";
score = 5;
description = "Sender's ASN is on the local blacklist";
symbols_set = ["LOCAL_BL_ASN"];
}
GLOBAL_SMTP_FROM_WL {
type = "from";
map = "${LOCAL_CONFDIR}/custom/global_smtp_from_whitelist.map";
regexp = true;
score = -2050;
}
GLOBAL_SMTP_FROM_BL {
type = "from";
map = "${LOCAL_CONFDIR}/custom/global_smtp_from_blacklist.map";
regexp = true;
score = 2050;
}
GLOBAL_MIME_FROM_WL {
type = "header";
header = "from";
filter = "email:addr";
map = "${LOCAL_CONFDIR}/custom/global_mime_from_whitelist.map";
regexp = true;
score = -2050;
}
GLOBAL_MIME_FROM_BL {
type = "header";
header = "from";
filter = "email:addr";
map = "${LOCAL_CONFDIR}/custom/global_mime_from_blacklist.map";
regexp = true;
score = 2050;
}
GLOBAL_RCPT_WL {
type = "rcpt";
map = "${LOCAL_CONFDIR}/custom/global_rcpt_whitelist.map";
regexp = true;
prefilter = true;
action = "accept";
}
GLOBAL_RCPT_BL {
type = "rcpt";
map = "${LOCAL_CONFDIR}/custom/global_rcpt_blacklist.map";
regexp = true;
prefilter = true;
action = "reject";
}
SIEVE_HOST {
type = "ip";
map = "${LOCAL_CONFDIR}/custom/dovecot_trusted.map";
symbols_set = ["SIEVE_HOST"];
}
RSPAMD_HOST {
type = "ip";
map = "${LOCAL_CONFDIR}/custom/rspamd_trusted.map";
symbols_set = ["RSPAMD_HOST"];
}
MAILCOW_DOMAIN_HEADER_FROM {
type = "header";
header = "from";
filter = "email:domain";
map = "redis://DOMAIN_MAP";
}
IP_WHITELIST {
type = "ip";
map = "${LOCAL_CONFDIR}/custom/ip_wl.map";
symbols_set = ["IP_WHITELIST"];
score = -2050;
}
FISHY_TLD {
type = "from";
filter = "email:domain";
map = "${LOCAL_CONFDIR}/custom/fishy_tlds.map";
regexp = true;
score = 0.1;
}
BAD_WORDS {
type = "content";
filter = "text";
map = "${LOCAL_CONFDIR}/custom/bad_words.map";
regexp = true;
score = 0.1;
}
BAD_WORDS_DE {
type = "content";
filter = "text";
map = "${LOCAL_CONFDIR}/custom/bad_words_de.map";
regexp = true;
score = 0.1;
}
BAD_LANG {
type = 'selector';
selector = 'languages';
map = "${LOCAL_CONFDIR}/custom/bad_languages.map";
symbols_set = ["LANG_FILTER"];
regexp = true;
score = 5.0;
}
BAZAAR_ABUSE_CH {
type = "selector";
selector = "attachments(hex,md5)";
map = "https://bazaar.abuse.ch/export/txt/md5/recent/";
score = 10.0;
}
URLHAUS_ABUSE_CH {
type = "selector";
selector = "urls";
map = "https://urlhaus.abuse.ch/downloads/text_online/";
score = 10.0;
}
SMTP_LIMITED_ACCESS {
type = "user";
map = "redis://SMTP_LIMITED_ACCESS";
symbols_set = ["SMTP_LIMITED_ACCESS"];
}
BAD_SUBJECT_00 {
type = "header";
header = "subject";
regexp = true;
map = "http://fuzzy.mailcow.email/bad-subject-regex.txt";
score = 6.0;
symbols_set = ["BAD_SUBJECT_00"];
}

View File

@ -0,0 +1,7 @@
timeout = 8.0;
symbol_bad_mx = "MX_INVALID";
symbol_no_mx = "MX_MISSING";
symbol_good_mx = "MX_GOOD";
expire = 86400;
key_prefix = "rmx";
enabled = true;

View File

@ -0,0 +1,9 @@
dns {
enable_dnssec = true;
}
map_watch_interval = 30s;
disable_monitoring = true;
# In case a task times out (like DNS lookup), soft reject the message
# instead of silently accepting the message without further processing.
soft_reject_on_timeout = true;
local_addrs = /etc/rspamd/custom/mailcow_networks.map;

View File

@ -0,0 +1 @@
phishtank_enabled = false;

View File

@ -0,0 +1,26 @@
symbols = {
"ARC_REJECT" {
score = 0.1;
}
"R_SPF_FAIL" {
score = 8.0;
}
"R_SPF_PERMFAIL" {
score = 8.0;
}
"R_SPF_SOFTFAIL" {
score = 0.1;
}
"R_DKIM_REJECT" {
score = 8.0;
}
"DMARC_POLICY_REJECT" {
weight = 16.0;
}
"DMARC_POLICY_QUARANTINE" {
weight = 8.0;
}
"DMARC_POLICY_SOFTFAIL" {
weight = 0.1;
}
}

View File

@ -0,0 +1,9 @@
# Uncomment below to apply the ratelimits globally. Use Ratelimits inside mailcow UI to overwrite them for a specific domain/mailbox.
# rates {
# # Format: "1 / 1h" or "20 / 1m" etc.
# to = "100 / 1s";
# to_ip = "100 / 1s";
# to_ip_from = "100 / 1s";
# bounce_to = "100 / 1h";
# bounce_to_ip = "7 / 1m";
# }

View File

@ -0,0 +1,26 @@
rbls {
interserver_ip {
symbol = "RBL_INTERSERVER_IP";
rbl = "rbl.interserver.net";
from = true;
ipv6 = false;
returncodes {
RBL_INTERSERVER_BAD_IP = "127.0.0.2";
}
}
interserver_uri {
symbol = "RBL_INTERSERVER_URI";
rbl = "rbluri.interserver.net";
ignore_defaults = true;
no_ip = true;
dkim = true;
emails = true;
urls = true;
returncodes = {
RBL_INTERSERVER_BAD_URI = "127.0.0.2";
}
}
.include(try=true,override=true,priority=5) "$LOCAL_CONFDIR/custom/dqs-rbl.conf"
}

View File

@ -0,0 +1,277 @@
symbols = {
"RBL_UCEPROTECT_LEVEL1" {
score = 3.5;
}
"RBL_UCEPROTECT_LEVEL2" {
score = 1.5;
}
"RECEIVED_SPAMHAUS_XBL" {
weight = 0.0;
description = "Received address is listed in ZEN XBL";
}
"RBL_INTERSERVER_BAD_URI" {
score = 4.0;
description = "Listed on Interserver RBL";
}
"RBL_INTERSERVER_BAD_IP" {
score = 4.0;
description = "Listed on Interserver RBL";
}
"SPAMHAUS_ZEN" {
weight = 7.0;
}
"SH_AUTHBL_RECEIVED" {
weight = 4.0;
}
"RBL_DBL_SPAM" {
weight = 7.0;
}
"RBL_DBL_PHISH" {
weight = 7.0;
}
"RBL_DBL_MALWARE" {
weight = 7.0;
}
"RBL_DBL_BOTNET" {
weight = 7.0;
}
"RBL_DBL_ABUSED_SPAM" {
weight = 3.0;
}
"RBL_DBL_ABUSED_PHISH" {
weight = 3.0;
}
"RBL_DBL_ABUSED_MALWARE" {
weight = 3.0;
}
"RBL_DBL_ABUSED_BOTNET" {
weight = 3.0;
}
"RBL_ZRD_VERY_FRESH_DOMAIN" {
weight = 7.0;
}
"RBL_ZRD_FRESH_DOMAIN" {
weight = 4.0;
}
"ZRD_VERY_FRESH_DOMAIN" {
weight = 7.0;
}
"ZRD_FRESH_DOMAIN" {
weight = 4.0;
}
"SH_EMAIL_DBL" {
weight = 7.0;
}
"SH_EMAIL_DBL_ABUSED" {
weight = 7.0;
}
"SH_EMAIL_ZRD_VERY_FRESH_DOMAIN" {
weight = 7.0;
}
"SH_EMAIL_ZRD_FRESH_DOMAIN" {
weight = 4.0;
}
"RBL_DBL_DONT_QUERY_IPS" {
weight = 0.0;
}
"RBL_ZRD_DONT_QUERY_IPS" {
weight = 0.0;
}
"SH_EMAIL_ZRD_DONT_QUERY_IPS" {
weight = 0.0;
}
"SH_EMAIL_DBL_DONT_QUERY_IPS" {
weight = 0.0;
}
"DBL" {
weight = 0.0;
description = "DBL unknown result";
groups = ["spamhaus"];
}
"DBL_SPAM" {
weight = 7;
description = "DBL uribl spam";
groups = ["spamhaus"];
}
"DBL_PHISH" {
weight = 7;
description = "DBL uribl phishing";
groups = ["spamhaus"];
}
"DBL_MALWARE" {
weight = 7;
description = "DBL uribl malware";
groups = ["spamhaus"];
}
"DBL_BOTNET" {
weight = 7;
description = "DBL uribl botnet C&C domain";
groups = ["spamhaus"];
}
"DBLABUSED_SPAM_FULLURLS" {
weight = 5.5;
description = "DBL uribl abused legit spam";
groups = ["spamhaus"];
}
"DBLABUSED_PHISH_FULLURLS" {
weight = 5.5;
description = "DBL uribl abused legit phish";
groups = ["spamhaus"];
}
"DBLABUSED_MALWARE_FULLURLS" {
weight = 5.5;
description = "DBL uribl abused legit malware";
groups = ["spamhaus"];
}
"DBLABUSED_BOTNET_FULLURLS" {
weight = 5.5;
description = "DBL uribl abused legit botnet";
groups = ["spamhaus"];
}
"DBL_ABUSE" {
weight = 5.5;
description = "DBL uribl abused legit spam";
groups = ["spamhaus"];
}
"DBL_ABUSE_REDIR" {
weight = 1.5;
description = "DBL uribl abused spammed redirector domain";
groups = ["spamhaus"];
}
"DBL_ABUSE_PHISH" {
weight = 5.5;
description = "DBL uribl abused legit phish";
groups = ["spamhaus"];
}
"DBL_ABUSE_MALWARE" {
weight = 5.5;
description = "DBL uribl abused legit malware";
groups = ["spamhaus"];
}
"DBL_ABUSE_BOTNET" {
weight = 5.5;
description = "DBL uribl abused legit botnet C&C";
groups = ["spamhaus"];
}
"DBL_PROHIBIT" {
weight = 0.0;
description = "DBL uribl IP queries prohibited!";
groups = ["spamhaus"];
}
"DBL_BLOCKED_OPENRESOLVER" {
weight = 0.0;
description = "You are querying Spamhaus from an open resolver, please see https://www.spamhaus.org/returnc/pub/";
groups = ["spamhaus"];
}
"DBL_BLOCKED" {
weight = 0.0;
description = "You are exceeding the query limit, please see https://www.spamhaus.org/returnc/vol/";
groups = ["spamhaus"];
}
"SPAMHAUS_ZEN_URIBL" {
weight = 0.0;
description = "Spamhaus ZEN URIBL: Filtered result";
groups = ["spamhaus"];
}
"URIBL_SBL" {
weight = 6.5;
description = "A domain in the message body resolves to an IP listed in Spamhaus SBL";
one_shot = true;
groups = ["spamhaus"];
}
"URIBL_SBL_CSS" {
weight = 6.5;
description = "A domain in the message body resolves to an IP listed in Spamhaus SBL CSS";
one_shot = true;
groups = ["spamhaus"];
}
"URIBL_PBL" {
weight = 0.01;
description = "A domain in the message body resolves to an IP listed in Spamhaus PBL";
one_shot = true;
groups = ["spamhaus"];
}
"URIBL_DROP" {
weight = 6.5;
description = "A domain in the message body resolves to an IP listed in Spamhaus DROP";
one_shot = true;
groups = ["spamhaus"];
}
"URIBL_XBL" {
weight = 5.0;
description = "A domain in the message body resolves to an IP listed in Spamhaus XBL";
one_shot = true;
groups = ["spamhaus"];
}
"SPAMHAUS_SBL_URL" {
weight = 6.5;
description = "A numeric URL in the message body is listed in Spamhaus SBL";
one_shot = true;
groups = ["spamhaus"];
}
"SH_HBL_EMAIL" {
weight = 7;
description = "Email listed in HBL";
groups = ["spamhaus"];
}
"SH_HBL_FILE_MALICIOUS" {
weight = 7;
description = "An attachment hash is listed in Spamhaus HBL as malicious";
groups = ["spamhaus"];
}
"SH_HBL_FILE_SUSPICIOUS" {
weight = 5;
description = "An attachment hash is listed in Spamhaus HBL as suspicious";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_CW_BTC" {
score = 7;
description = "Bitcoin found in Spamhaus cryptowallet list";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_CW_ETH" {
score = 7;
description = "Ethereum found in Spamhaus cryptowallet list";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_CW_BCH" {
score = 7;
description = "Bitcoinhash found in Spamhaus cryptowallet list";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_CW_XMR" {
score = 7;
description = "Monero found in Spamhaus cryptowallet list";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_CW_LTC" {
score = 7;
description = "Litecoin found in Spamhaus cryptowallet list";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_CW_XRP" {
score = 7;
description = "Ripple found in Spamhaus cryptowallet list";
groups = ["spamhaus"];
}
"RBL_SPAMHAUS_HBL_URL" {
score = 7;
description = "URL found in spamhaus HBL blocklist";
groups = ["spamhaus"];
}
}

View File

@ -0,0 +1,2 @@
servers = "redis:6379";
timeout = 10;

View File

@ -0,0 +1,9 @@
rules {
ip_reputation = {
selector "ip" {
}
backend "redis" {
}
symbol = "IP_REPUTATION";
}
}

View File

@ -0,0 +1 @@
ruleset = "/etc/rspamd/custom/sa-rules";

View File

@ -0,0 +1,26 @@
classifier "bayes" {
# name = "custom"; # 'name' parameter must be set if multiple classifiers are defined
learn_condition = 'return require("lua_bayes_learn").can_learn';
new_schema = true;
tokenizer {
name = "osb";
}
backend = "redis";
min_tokens = 11;
min_learns = 5;
expire = 7776000;
statfile {
symbol = "BAYES_HAM";
spam = false;
}
statfile {
symbol = "BAYES_SPAM";
spam = true;
}
autolearn {
spam_threshold = 12.0;
ham_threshold = -4.5;
check_balance = true;
min_balance = 0.9;
}
}

View File

@ -0,0 +1,10 @@
symbols = {
"BAYES_SPAM" {
weight = 4.5;
description = "Message probably spam, probability: ";
}
"BAYES_HAM" {
weight = -5.5;
description = "Message probably ham, probability: ";
}
}