From 9a284150b2f744acaf4f134ecf78d00494fbf997 Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:51:23 +0200 Subject: [PATCH] Rspamd: replace `reject_unknown_client_hostname` with Rspamd `HFILTER_HOSTNAME_UNKNOWN` and make it configurable (#3248) --- docs/content/config/environment.md | 15 ++++++++ docs/content/config/security/rspamd.md | 6 ++-- mailserver.env | 11 ++++++ target/postfix/main.cf | 2 +- target/rspamd/local.d/hfilter_group.conf | 11 ++++++ target/rspamd/local.d/options.inc | 1 + .../startup/setup.d/security/rspamd.sh | 36 ++++++++++++++++++- target/scripts/startup/variables-stack.sh | 2 ++ .../parallel/set1/spam_virus/rspamd.bats | 19 ++++++++-- 9 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 target/rspamd/local.d/hfilter_group.conf diff --git a/docs/content/config/environment.md b/docs/content/config/environment.md index e8168062..e221d13c 100644 --- a/docs/content/config/environment.md +++ b/docs/content/config/environment.md @@ -363,6 +363,21 @@ When enabled, - **0** => Disabled - 1 => Enabled +##### RSPAMD_HFILTER + +Can be used to enable or disable the [Hfilter group module][rspamd-docs-hfilter-group-module]. This is used by DMS to adjust the `HFILTER_HOSTNAME_UNKNOWN` symbol, increasing it's default weight to act similar to Postfix's `reject_unknown_client_hostname`, without the need to outright reject a message. + +- 0 => Disabled +- **1** => Enabled + +[rspamd-docs-hfilter-group-module]: https://www.rspamd.com/doc/modules/hfilter.html + +##### RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE + +Can be used to control the score when the [`HFILTER_HOSTNAME_UNKNOWN` symbol](#rspamd_hfilter) applies. A higher score is more punishing. Setting it to 15 (the default score for rejecting an e-mail) is equivalent to rejecting the email when the check fails. + +Default: 6 (which corresponds to the `add_header` action) + #### Reports ##### PFLOGSUMM_TRIGGER diff --git a/docs/content/config/security/rspamd.md b/docs/content/config/security/rspamd.md index 5f70fe73..1f40c623 100644 --- a/docs/content/config/security/rspamd.md +++ b/docs/content/config/security/rspamd.md @@ -25,8 +25,10 @@ The following environment variables are related to Rspamd: 1. [`ENABLE_RSPAMD`](../environment.md#enable_rspamd) 2. [`ENABLE_RSPAMD_REDIS`](../environment.md#enable_rspamd_redis) 3. [`RSPAMD_GREYLISTING`](../environment.md#rspamd_greylisting) -4. [`RSPAMD_LEARN`](../environment.md#rspamd_learn) -5. [`MOVE_SPAM_TO_JUNK`](../environment.md#move_spam_to_junk) +4. [`RSPAMD_HFILTER`](../environment.md#rspamd_hfilter) +5. [`RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE`](../environment.md#rspamd_hfilter_hostname_unknown_score) +6. [`RSPAMD_LEARN`](../environment.md#rspamd_learn) +7. [`MOVE_SPAM_TO_JUNK`](../environment.md#move_spam_to_junk) With these variables, you can enable Rspamd itself and you can enable / disable certain features related to Rspamd. diff --git a/mailserver.env b/mailserver.env index de8a7653..81356af5 100644 --- a/mailserver.env +++ b/mailserver.env @@ -150,6 +150,17 @@ RSPAMD_LEARN=0 # 1 => enabled RSPAMD_GREYLISTING=0 +# Can be used to enable or diable the Hfilter group module. +# +# - 0 => Disabled +# - **1** => Enabled +RSPAMD_HFILTER=1 + +# Can be used to control the score when the HFILTER_HOSTNAME_UNKNOWN symbol applies. A higher score is more punishing. Setting it to 15 is equivalent to rejecting the email when the check fails. +# +# Default: 6 +RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE=6 + # Amavis content filter (used for ClamAV & SpamAssassin) # 0 => Disabled # 1 => Enabled diff --git a/target/postfix/main.cf b/target/postfix/main.cf index 9d47348f..881c3796 100644 --- a/target/postfix/main.cf +++ b/target/postfix/main.cf @@ -54,7 +54,7 @@ smtpd_sender_restrictions = $dms_smtpd_sender_restrictions disable_vrfy_command = yes # Custom defined parameters for DMS: -dms_smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unknown_sender_domain, reject_unknown_client_hostname +dms_smtpd_sender_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unknown_sender_domain # Submission ports 587 and 465 support for SPOOF_PROTECTION=1 mua_sender_restrictions = reject_authenticated_sender_login_mismatch, $dms_smtpd_sender_restrictions diff --git a/target/rspamd/local.d/hfilter_group.conf b/target/rspamd/local.d/hfilter_group.conf new file mode 100644 index 00000000..7bf73b3e --- /dev/null +++ b/target/rspamd/local.d/hfilter_group.conf @@ -0,0 +1,11 @@ +symbols = { + "HFILTER_HOSTNAME_UNKNOWN" { + # We add 6 because we need a score of exactly 6 for the `add_header` + # action to trigger; that's the least we want to happen. + # + # This is meant as a replacement for `reject_unknown_client_hostname` + # (see https://www.postfix.org/postconf.5.html#reject_unknown_client_hostname) + # which Postfix can employ to directly reject emails. + score = 6; # __TAG__HFILTER_HOSTNAME_UNKNOWN + } +} diff --git a/target/rspamd/local.d/options.inc b/target/rspamd/local.d/options.inc index 6561c2ec..f57d4339 100644 --- a/target/rspamd/local.d/options.inc +++ b/target/rspamd/local.d/options.inc @@ -1 +1,2 @@ pidfile = false; +soft_reject_on_timeout = true; diff --git a/target/scripts/startup/setup.d/security/rspamd.sh b/target/scripts/startup/setup.d/security/rspamd.sh index ba292346..d7feb802 100644 --- a/target/scripts/startup/setup.d/security/rspamd.sh +++ b/target/scripts/startup/setup.d/security/rspamd.sh @@ -15,6 +15,7 @@ function _setup_rspamd __rspamd__setup_default_modules __rspamd__setup_learning __rspamd__setup_greylisting + __rspamd__setup_hfilter_group __rspamd__handle_user_modules_adjustments # must run last _log 'trace' 'Rspamd setup finished' @@ -138,6 +139,9 @@ function __rspamd__setup_default_modules { __rspamd__log 'debug' 'Disabling default modules' + # This array contains all the modules we disable by default. They + # can be re-enabled later (in `__rspamd__handle_user_modules_adjustments`) + # with `rspamd-modules.conf`. local DISABLE_MODULES=( clickhouse elastic @@ -202,7 +206,8 @@ EOF fi } -# Sets up greylisting based on the environment variable RSPAMD_GREYLISTING. +# Sets up greylisting with the greylisting module (see +# https://rspamd.com/doc/modules/greylisting.html). function __rspamd__setup_greylisting { if [[ ${RSPAMD_GREYLISTING} -eq 1 ]] @@ -214,6 +219,35 @@ function __rspamd__setup_greylisting fi } +# This function handles setup of the Hfilter module (see +# https://www.rspamd.com/doc/modules/hfilter.html). This module is mainly +# used for hostname checks, and whether or not a reverse-DNS check +# succeeds. +function __rspamd__setup_hfilter_group +{ + local MODULE_FILE='/etc/rspamd/local.d/hfilter_group.conf' + if [[ ${RSPAMD_HFILTER} -eq 1 ]] + then + __rspamd__log 'debug' 'Hfilter (group) module is enabled' + # Check if we received a number first + if [[ ! ${RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE} =~ ^[0-9][1-9]*$ ]] + then + __rspamd__log 'warn' "'RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE' is not a number (${RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE}) but was expected to be!" + elif [[ ${RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE} -ne 6 ]] + then + __rspamd__log 'trace' "Adjusting score for 'HFILTER_HOSTNAME_UNKNOWN' in Hfilter group module to ${RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE}" + sed -i -E \ + "s|(.*score =).*(# __TAG__HFILTER_HOSTNAME_UNKNOWN)|\1 ${RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE}; \2|g" \ + "${MODULE_FILE}" + else + __rspamd__log 'trace' "Not adjusting score for 'HFILTER_HOSTNAME_UNKNOWN' in Hfilter group module" + fi + else + __rspamd__log 'debug' 'Disabling Hfilter (group) module' + rm -f "${MODULE_FILE}" + fi +} + # Parses `RSPAMD_CUSTOM_COMMANDS_FILE` and executed the directives given by the file. # To get a detailed explanation of the commands and how the file works, visit # https://docker-mailserver.github.io/docker-mailserver/edge/config/security/rspamd/#with-the-help-of-a-custom-file diff --git a/target/scripts/startup/variables-stack.sh b/target/scripts/startup/variables-stack.sh index 5bf5a340..8919a547 100644 --- a/target/scripts/startup/variables-stack.sh +++ b/target/scripts/startup/variables-stack.sh @@ -56,6 +56,8 @@ function __environment_variables_general_setup VARS[POSTGREY_TEXT]="${POSTGREY_TEXT:=Delayed by Postgrey}" VARS[POSTSCREEN_ACTION]="${POSTSCREEN_ACTION:=enforce}" VARS[RSPAMD_GREYLISTING]="${RSPAMD_GREYLISTING:=0}" + VARS[RSPAMD_HFILTER]="${RSPAMD_HFILTER:=1}" + VARS[RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE]="${RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE:=6}" VARS[RSPAMD_LEARN]="${RSPAMD_LEARN:=0}" VARS[SA_KILL]=${SA_KILL:="10.0"} VARS[SA_SPAM_SUBJECT]=${SA_SPAM_SUBJECT:="***SPAM*** "} diff --git a/test/tests/parallel/set1/spam_virus/rspamd.bats b/test/tests/parallel/set1/spam_virus/rspamd.bats index b0d0f88b..ea57e81f 100644 --- a/test/tests/parallel/set1/spam_virus/rspamd.bats +++ b/test/tests/parallel/set1/spam_virus/rspamd.bats @@ -10,6 +10,8 @@ function setup_file() { # Comment for maintainers about `PERMIT_DOCKER=host`: # https://github.com/docker-mailserver/docker-mailserver/pull/2815/files#r991087509 local CUSTOM_SETUP_ARGUMENTS=( + --env ENABLE_AMAVIS=0 + --env ENABLE_SPAMASSASSIN=0 --env ENABLE_CLAMAV=1 --env ENABLE_RSPAMD=1 --env ENABLE_OPENDKIM=0 @@ -19,6 +21,8 @@ function setup_file() { --env MOVE_SPAM_TO_JUNK=1 --env RSPAMD_LEARN=1 --env RSPAMD_GREYLISTING=1 + --env RSPAMD_HFILTER=1 + --env RSPAMD_HFILTER_HOSTNAME_UNKNOWN_SCORE=7 ) mv "${TEST_TMP_CONFIG}"/rspamd/* "${TEST_TMP_CONFIG}/" @@ -170,7 +174,7 @@ function teardown_file() { _default_teardown ; } assert_success } -@test 'Check MOVE_SPAM_TO_JUNK works for Rspamd' { +@test 'MOVE_SPAM_TO_JUNK works for Rspamd' { _run_in_container_bash '[[ -f /usr/lib/dovecot/sieve-global/after/spam_to_junk.sieve ]]' assert_success _run_in_container_bash '[[ -f /usr/lib/dovecot/sieve-global/after/spam_to_junk.svbin ]]' @@ -186,7 +190,7 @@ function teardown_file() { _default_teardown ; } _count_files_in_directory_in_container /var/mail/localhost.localdomain/user1/.Junk/new/ 1 } -@test 'Check RSPAMD_LEARN works' { +@test 'RSPAMD_LEARN works' { for FILE in learn-{ham,spam}.{sieve,svbin} do _run_in_container_bash "[[ -f /usr/lib/dovecot/sieve-pipe/${FILE} ]]" @@ -245,10 +249,19 @@ function teardown_file() { _default_teardown ; } done } -@test 'Check greylisting is enabled' { +@test 'greylisting is enabled' { _run_in_container grep 'enabled = true;' /etc/rspamd/local.d/greylist.conf assert_success _run_in_container rspamadm configdump greylist assert_success assert_output --partial 'enabled = true;' } + +@test 'hfilter group module is configured correctly' { + _run_in_container_bash '[[ -f /etc/rspamd/local.d/hfilter_group.conf ]]' + assert_success + + _run_in_container grep '__TAG__HFILTER_HOSTNAME_UNKNOWN' /etc/rspamd/local.d/hfilter_group.conf + assert_success + assert_output --partial 'score = 7;' +}