diff --git a/.gitlab-docker-manifest.yml b/.gitlab-docker-manifest.yml index 8b38379..1eddfc3 100644 --- a/.gitlab-docker-manifest.yml +++ b/.gitlab-docker-manifest.yml @@ -1,7 +1,7 @@ x86_64:build-manifest: stage: build-manifest script: - - docker manifest create ${CI_REGISTRY_IMAGE}:${VERSION} ${CI_REGISTRY_IMAGE}:${VERSION}-x86_64 #${CI_REGISTRY_IMAGE}:${VERSION}-arm64 ${CI_REGISTRY_IMAGE}:${VERSION}armv7l + - docker manifest create ${CI_REGISTRY_IMAGE}:${VERSION} ${CI_REGISTRY_IMAGE}:${VERSION}-x86_64 #${CI_REGISTRY_IMAGE}:${VERSION}-arm64 ${CI_REGISTRY_IMAGE}:${VERSION}-armv7l - docker manifest push --purge ${CI_REGISTRY_IMAGE}:${VERSION} tags: - docker diff --git a/Dockerfile b/Dockerfile index 507365a..521b60a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,7 @@ RUN if [ -n ${HTTP_PROXY} ] ; then sed -i -e s'/https/http/' /etc/apk/repositori RUN apk add --no-cache rspamd +COPY rspamd-dqs/3.x/rbl.conf rspamd-dqs/3.x/rbl_group.conf rspamd-dqs/3.x/rspamd.local.lua /usr/local/dqs/ COPY override.d /etc/rspamd/override.d COPY init /sbin/ diff --git a/init b/init index 52905ad..bb2eb62 100755 --- a/init +++ b/init @@ -28,6 +28,13 @@ if [ -z "$@" ]; then [ -n "${NOTON}" ] && echo "No [${CLAMAV}]?" && exit 1 fi + if [ -n "${SPAMHAUS_DQS_KEY}" ]; then + mv /usr/local/dqs/rbl.conf /usr/local/dqs/rbl_group.conf /etc/rspamd/local.d + mv /usr/local/dqs/rspamd.local.lua /etc/rspamd + + sed -i -e "s/your_DQS_key/${SPAMHAUS_DQS_KEY}/g" /etc/rspamd/local.d/rbl*.conf /etc/rspamd/rspamd.local.lua + fi + mkdir -p /run/rspamd [ -x /usr/bin/rspamd ] && exec /usr/bin/rspamd -u rspamd -g rspamd -c /etc/rspamd/rspamd.conf -f -p /run/rspamd/rspamd.pid & diff --git a/rspamd-dqs/3.x/rbl.conf b/rspamd-dqs/3.x/rbl.conf new file mode 100644 index 0000000..88e19de --- /dev/null +++ b/rspamd-dqs/3.x/rbl.conf @@ -0,0 +1,161 @@ +rbls { + spamhaus { + rbl = "your_DQS_key.zen.dq.spamhaus.net"; + from = false; + } + spamhaus_from { + from = true; + received = false; + rbl = "your_DQS_key.zen.dq.spamhaus.net"; + returncodes { + # Add a generig hit on ZEN. It's safe to tag as spam if the last untrusted relay is in this combined list +# SPAMHAUS_ZEN_SBL = "127.0.0.2"; +# SPAMHAUS_ZEN_CSS = "127.0.0.3"; +# SPAMHAUS_ZEN_XBL = [ "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7" ]; +# SPAMHAUS_ZEN_PBL = [ "127.0.0.10", "127.0.0.11" ]; + SPAMHAUS_ZEN = [ "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.9", "127.0.0.10", "127.0.0.11" ]; + } + } + spamhaus_authbl_received { + # Check if the sender client is listed in AuthBL (AuthBL is *not* part of ZEN) + rbl = "your_DQS_key.authbl.dq.spamhaus.net"; + from = false; + received = true; + ipv6 = true; + returncodes { + SH_AUTHBL_RECEIVED = "127.0.0.20" + } + } + spamhaus_dbl { + # Add checks on the HELO string + rbl = "your_DQS_key.dbl.dq.spamhaus.net"; + helo = true; + rdns = true; + dkim = true; + disable_monitoring = true; + returncodes { + RBL_DBL_SPAM = "127.0.1.2"; + RBL_DBL_PHISH = "127.0.1.4"; + RBL_DBL_MALWARE = "127.0.1.5"; + RBL_DBL_BOTNET = "127.0.1.6"; + RBL_DBL_ABUSED_SPAM = "127.0.1.102"; + RBL_DBL_ABUSED_PHISH = "127.0.1.104"; + RBL_DBL_ABUSED_MALWARE = "127.0.1.105"; + RBL_DBL_ABUSED_BOTNET = "127.0.1.106"; + RBL_DBL_DONT_QUERY_IPS = "127.0.1.255"; + } + } + spamhaus_dbl_fullurls { + ignore_defaults = true; + no_ip = true; + rbl = "your_DQS_key.dbl.dq.spamhaus.net"; + selector = 'urls:get_host' + disable_monitoring = true; + returncodes { + DBLABUSED_SPAM_FULLURLS = "127.0.1.102"; + DBLABUSED_PHISH_FULLURLS = "127.0.1.104"; + DBLABUSED_MALWARE_FULLURLS = "127.0.1.105"; + DBLABUSED_BOTNET_FULLURLS = "127.0.1.106"; + } + } + spamhaus_zrd { + # Add checks on the HELO string also for DQS + rbl = "your_DQS_key.zrd.dq.spamhaus.net"; + helo = true; + rdns = true; + dkim = true; + disable_monitoring = true; + returncodes { + RBL_ZRD_VERY_FRESH_DOMAIN = "127.0.2.[2-4]+"; + RBL_ZRD_FRESH_DOMAIN = ["127.0.2.[5-9]+","127.0.2.1[0-9]+","127.0.2.2[0-4]+"]; + RBL_ZRD_DONT_QUERY_IPS = "127.0.2.255"; + } + } + "SPAMHAUS_ZEN_URIBL" { + rbl = "your_DQS_key.zen.dq.spamhaus.net"; + resolve_ip = true; + checks = ['urls']; + replyto = true; + emails = true; + ipv4 = true; + ipv6 = true; + emails_domainonly = true; + returncodes { + URIBL_SBL = "127.0.0.2"; + URIBL_SBL_CSS = "127.0.0.3"; + URIBL_XBL = ["127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7"]; + URIBL_PBL = ["127.0.0.10", "127.0.0.11"]; + URIBL_DROP = "127.0.0.9"; + } + } + SH_EMAIL_DBL { + ignore_defaults = true; + replyto = true; + emails_domainonly = true; + disable_monitoring = true; + rbl = "your_DQS_key.dbl.dq.spamhaus.net" + returncodes = { + SH_EMAIL_DBL = [ + "127.0.1.2", + "127.0.1.4", + "127.0.1.5", + "127.0.1.6" + ]; + SH_EMAIL_DBL_ABUSED = [ + "127.0.1.102", + "127.0.1.104", + "127.0.1.105", + "127.0.1.106" + ]; + SH_EMAIL_DBL_DONT_QUERY_IPS = [ "127.0.1.255" ]; + } + } + SH_EMAIL_ZRD { + ignore_defaults = true; + replyto = true; + emails_domainonly = true; + disable_monitoring = true; + rbl = "your_DQS_key.zrd.dq.spamhaus.net" + returncodes = { + SH_EMAIL_ZRD_VERY_FRESH_DOMAIN = [ + "127.0.2.[2-4]+" + ]; + SH_EMAIL_ZRD_FRESH_DOMAIN = [ + "127.0.2.[5-9]+", + "127.0.2.1[0-9]+", + "127.0.2.2[0-4]+" + ]; + SH_EMAIL_ZRD_DONT_QUERY_IPS = [ "127.0.2.255" ]; + } + } + "DBL" { + rbl = "your_DQS_key.dbl.dq.spamhaus.net"; + disable_monitoring = true; + } + "ZRD" { + ignore_defaults = true; + rbl = "your_DQS_key.zrd.dq.spamhaus.net"; + no_ip = true; + dkim = true; + emails = true; + emails_domainonly = true; + urls = true; + returncodes = { + ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + ZRD_FRESH_DOMAIN = ["127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24"]; + } + } + spamhaus_sbl_url { + ignore_defaults = true + rbl = "your_DQS_key.sbl.dq.spamhaus.net"; + checks = ['urls']; + disable_monitoring = true; + returncodes { + SPAMHAUS_SBL_URL = "127.0.0.2"; + } + } + +.include(try=true,priority=5) "$LOCAL_CONFDIR/local.d/sh_rbl_hbl.conf" +} + + diff --git a/rspamd-dqs/3.x/rbl_group.conf b/rspamd-dqs/3.x/rbl_group.conf new file mode 100644 index 0000000..149dfda --- /dev/null +++ b/rspamd-dqs/3.x/rbl_group.conf @@ -0,0 +1,208 @@ +symbols = { + "RECEIVED_SPAMHAUS_SBL" { + weight = 6.0; + } + "RECEIVED_SPAMHAUS_CSS" { + weight = 3.0; + } + "RECEIVED_SPAMHAUS_XBL" { + weight = 0; + } + "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"]; + } + .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/sh_rbl_group_hbl.conf" +} diff --git a/rspamd-dqs/3.x/rspamd.local.lua b/rspamd-dqs/3.x/rspamd.local.lua new file mode 100644 index 0000000..b55586d --- /dev/null +++ b/rspamd-dqs/3.x/rspamd.local.lua @@ -0,0 +1,122 @@ +local rspamd_logger = require "rspamd_logger" +local rspamd_re = require "rspamd_regexp" +local rspamd_hash = require "rspamd_cryptobox_hash" +local rspamd_util = require "rspamd_util" + +local check_cw_dns = '._cw.your_DQS_key.hbl.dq.spamhaus.net.' + +local function check_cw_callback ( task, re, lowercase, cryptovalue ) + 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 + if (lowercase == 1) then word = string.lower(word) end + local match = re:match(word) + if match then + local hash = rspamd_hash.create_specific('sha1', word):hex() + rspamd_logger.infox('HASH ' .. hash) + local lookup = hash .. check_cw_dns + local function dns_cb(_,_,results,err) + if (not results) then return false end + if (string.find(tostring(results[1]), '127.0.')) then + rspamd_logger.infox('found ' .. cryptovalue .. ' wallet %s (hashed: %s) in Cryptowallet blocklist', word, hash) + return task:insert_result('RBL_SPAMHAUS_CW_' .. cryptovalue, 1.0, word); + end + end + r:resolve_a({ task = task, name = lookup , callback = dns_cb, forced = true }) + end + end + end +end + +rspamd_config:register_symbol({ + name = "RBL_SPAMHAUS_CW_BTC", + score = 7.0, + description = "BTC found in Spamhaus cryptowallet list", + group = "spamhaus", + type = "callback", + callback = function(task) + -- BTC regex + local re = rspamd_re.create_cached('^(?:bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$') + local lowercase = 0 + local cryptovalue = "BTC" + check_cw_callback (task, re, lowercase, cryptovalue ) + end +}) + +rspamd_config:register_symbol({ + name = "RBL_SPAMHAUS_CW_ETH", + score = 7.0, + description = "ETH found in Spamhaus cryptowallet list", + group = "spamhaus", + type = "callback", + callback = function(task) + -- ETH regex + local re = rspamd_re.create_cached('^0x[a-fA-F0-9]{40}$') + local lowercase = 1 + local cryptovalue = "ETH" + check_cw_callback (task, re, lowercase, cryptovalue ) + end +}) + +rspamd_config:register_symbol({ + name = "RBL_SPAMHAUS_CW_BCH", + score = 7.0, + description = "BCH found in Spamhaus cryptowallet list", + group = "spamhaus", + type = "callback", + callback = function(task) + -- BCH regex + local re = rspamd_re.create_cached('(?