2023-02-26 10:42:14 +00:00
#!/bin/bash
2023-05-25 23:01:41 +00:00
function _setup_security_stack( ) {
2023-02-26 10:42:14 +00:00
_log 'debug' 'Setting up Security Stack'
2023-02-27 19:21:45 +00:00
__setup__security__postgrey
__setup__security__postscreen
2023-02-26 10:42:14 +00:00
# recreate auto-generated file
local DMS_AMAVIS_FILE = /etc/amavis/conf.d/61-dms_auto_generated
echo "# WARNING: this file is auto-generated." >" ${ DMS_AMAVIS_FILE } "
echo "use strict;" >>" ${ DMS_AMAVIS_FILE } "
2023-02-27 19:21:45 +00:00
__setup__security__spamassassin
__setup__security__clamav
echo '1; # ensure a defined return' >>" ${ DMS_AMAVIS_FILE } "
chmod 444 " ${ DMS_AMAVIS_FILE } "
__setup__security__fail2ban
__setup__security__amavis
}
2023-05-25 23:01:41 +00:00
function __setup__security__postgrey( ) {
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_POSTGREY } -eq 1 ] ] ; then
2023-02-27 19:21:45 +00:00
_log 'debug' 'Enabling and configuring Postgrey'
sedfile -i -E \
's|(^smtpd_recipient_restrictions =.*)|\1, check_policy_service inet:127.0.0.1:10023|' \
/etc/postfix/main.cf
sed -i -e \
" s|\"--inet=127.0.0.1:10023\"|\"--inet=127.0.0.1:10023 --delay= ${ POSTGREY_DELAY } --max-age= ${ POSTGREY_MAX_AGE } --auto-whitelist-clients= ${ POSTGREY_AUTO_WHITELIST_CLIENTS } \"| " \
/etc/default/postgrey
2023-05-24 07:06:59 +00:00
if ! grep -i 'POSTGREY_TEXT' /etc/default/postgrey; then
2023-02-27 19:21:45 +00:00
printf 'POSTGREY_TEXT=\"%s\"\n\n' " ${ POSTGREY_TEXT } " >>/etc/default/postgrey
fi
2023-05-24 07:06:59 +00:00
if [ [ -f /tmp/docker-mailserver/whitelist_clients.local ] ] ; then
2023-02-27 19:21:45 +00:00
cp -f /tmp/docker-mailserver/whitelist_clients.local /etc/postgrey/whitelist_clients.local
fi
2023-05-24 07:06:59 +00:00
if [ [ -f /tmp/docker-mailserver/whitelist_recipients ] ] ; then
2023-02-27 19:21:45 +00:00
cp -f /tmp/docker-mailserver/whitelist_recipients /etc/postgrey/whitelist_recipients
fi
else
2023-04-23 10:16:53 +00:00
_log 'debug' 'Postgrey is disabled'
2023-02-27 19:21:45 +00:00
fi
}
2023-05-25 23:01:41 +00:00
function __setup__security__postscreen( ) {
2023-02-27 19:21:45 +00:00
_log 'debug' 'Configuring Postscreen'
sed -i \
-e " s|postscreen_dnsbl_action = enforce|postscreen_dnsbl_action = ${ POSTSCREEN_ACTION } | " \
-e " s|postscreen_greet_action = enforce|postscreen_greet_action = ${ POSTSCREEN_ACTION } | " \
-e " s|postscreen_bare_newline_action = enforce|postscreen_bare_newline_action = ${ POSTSCREEN_ACTION } | " /etc/postfix/main.cf
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_DNSBL } -eq 0 ] ] ; then
2023-02-27 19:21:45 +00:00
_log 'debug' 'Disabling Postscreen DNSBLs'
postconf 'postscreen_dnsbl_action = ignore'
postconf 'postscreen_dnsbl_sites = '
else
_log 'debug' 'Postscreen DNSBLs are enabled'
fi
}
2023-05-25 23:01:41 +00:00
function __setup__security__spamassassin( ) {
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_SPAMASSASSIN } -eq 1 ] ] ; then
2023-02-26 10:42:14 +00:00
_log 'debug' 'Enabling and configuring SpamAssassin'
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_tag_level_deflt (.*);|\$sa_tag_level_deflt = ' " ${ SA_TAG } " ';|g' /etc/amavis/conf.d/20-debian_defaults
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_tag2_level_deflt (.*);|\$sa_tag2_level_deflt = ' " ${ SA_TAG2 } " ';|g' /etc/amavis/conf.d/20-debian_defaults
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_kill_level_deflt (.*);|\$sa_kill_level_deflt = ' " ${ SA_KILL } " ';|g' /etc/amavis/conf.d/20-debian_defaults
2023-02-27 19:21:45 +00:00
# fix cron.daily for spamassassin
sed -i \
's|invoke-rc.d spamassassin reload|/etc/init\.d/spamassassin reload|g' \
/etc/cron.daily/spamassassin
2023-05-24 07:06:59 +00:00
if [ [ ${ SA_SPAM_SUBJECT } = = 'undef' ] ] ; then
2023-02-26 10:42:14 +00:00
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_spam_subject_tag (.*);|\$sa_spam_subject_tag = undef;|g' /etc/amavis/conf.d/20-debian_defaults
else
# shellcheck disable=SC2016
sed -i -r 's|^\$sa_spam_subject_tag (.*);|\$sa_spam_subject_tag = ' " ' ${ SA_SPAM_SUBJECT } ' " ';|g' /etc/amavis/conf.d/20-debian_defaults
fi
# activate short circuits when SA BAYES is certain it has spam or ham.
2023-05-24 07:06:59 +00:00
if [ [ ${ SA_SHORTCIRCUIT_BAYES_SPAM } -eq 1 ] ] ; then
2023-02-26 10:42:14 +00:00
# automatically activate the Shortcircuit Plugin
sed -i -r 's|^# loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|g' /etc/spamassassin/v320.pre
sed -i -r 's|^# shortcircuit BAYES_99|shortcircuit BAYES_99|g' /etc/spamassassin/local.cf
fi
2023-05-24 07:06:59 +00:00
if [ [ ${ SA_SHORTCIRCUIT_BAYES_HAM } -eq 1 ] ] ; then
2023-02-26 10:42:14 +00:00
# automatically activate the Shortcircuit Plugin
sed -i -r 's|^# loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|loadplugin Mail::SpamAssassin::Plugin::Shortcircuit|g' /etc/spamassassin/v320.pre
sed -i -r 's|^# shortcircuit BAYES_00|shortcircuit BAYES_00|g' /etc/spamassassin/local.cf
fi
2023-05-24 07:06:59 +00:00
if [ [ -e /tmp/docker-mailserver/spamassassin-rules.cf ] ] ; then
2023-02-26 10:42:14 +00:00
cp /tmp/docker-mailserver/spamassassin-rules.cf /etc/spamassassin/
fi
2023-05-24 07:06:59 +00:00
if [ [ ${ SPAMASSASSIN_SPAM_TO_INBOX } -eq 1 ] ] ; then
2023-02-26 10:42:14 +00:00
_log 'trace' 'Configuring Spamassassin/Amavis to send SPAM to inbox'
2023-05-23 17:32:09 +00:00
_log 'debug' 'SPAM_TO_INBOX=1 is set. SA_KILL will be ignored.'
2023-02-26 10:42:14 +00:00
sed -i " s|\$final_spam_destiny.*=.* $|\$final_spam_destiny = D_PASS;|g " /etc/amavis/conf.d/49-docker-mailserver
sed -i " s|\$final_bad_header_destiny.*=.* $|\$final_bad_header_destiny = D_PASS;|g " /etc/amavis/conf.d/49-docker-mailserver
else
_log 'trace' 'Configuring Spamassassin/Amavis to bounce SPAM'
sed -i " s|\$final_spam_destiny.*=.* $|\$final_spam_destiny = D_BOUNCE;|g " /etc/amavis/conf.d/49-docker-mailserver
sed -i " s|\$final_bad_header_destiny.*=.* $|\$final_bad_header_destiny = D_BOUNCE;|g " /etc/amavis/conf.d/49-docker-mailserver
fi
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_SPAMASSASSIN_KAM } -eq 1 ] ] ; then
2023-02-26 10:42:14 +00:00
_log 'trace' 'Configuring Spamassassin KAM'
local SPAMASSASSIN_KAM_CRON_FILE = /etc/cron.daily/spamassassin_kam
sa-update --import /etc/spamassassin/kam/kam.sa-channels.mcgrail.com.key
cat >" ${ SPAMASSASSIN_KAM_CRON_FILE } " <<"EOF"
#!/bin/bash
RESULT = $( sa-update --gpgkey 24C063D8 --channel kam.sa-channels.mcgrail.com 2>& 1)
EXIT_CODE = ${ ? }
# see https://spamassassin.apache.org/full/3.1.x/doc/sa-update.html#exit_codes
2023-05-24 07:06:59 +00:00
if [ [ ${ EXIT_CODE } -ge 4 ] ] ; then
2023-02-26 10:42:14 +00:00
echo -e " Updating SpamAssassin KAM failed:\n ${ RESULT } \n " >& 2
exit 1
fi
exit 0
EOF
chmod +x " ${ SPAMASSASSIN_KAM_CRON_FILE } "
fi
2023-02-27 19:21:45 +00:00
else
_log 'debug' 'SpamAssassin is disabled'
echo "@bypass_spam_checks_maps = (1);" >>" ${ DMS_AMAVIS_FILE } "
rm -f /etc/cron.daily/spamassassin
2023-02-26 10:42:14 +00:00
fi
2023-02-27 19:21:45 +00:00
}
2023-02-26 10:42:14 +00:00
2023-05-25 23:01:41 +00:00
function __setup__security__clamav( ) {
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_CLAMAV } -eq 1 ] ] ; then
2023-02-27 19:21:45 +00:00
_log 'debug' 'Enabling and configuring ClamAV'
2023-03-04 09:57:42 +00:00
local FILE
2023-05-26 12:00:40 +00:00
for FILE in /var/log/mail/{ clamav,freshclam} .log; do
2023-03-04 09:57:42 +00:00
touch " ${ FILE } "
chown clamav:adm " ${ FILE } "
chmod 640 " ${ FILE } "
done
2023-05-24 07:06:59 +00:00
if [ [ ${ CLAMAV_MESSAGE_SIZE_LIMIT } != '25M' ] ] ; then
2023-02-27 19:21:45 +00:00
_log 'trace' " Setting ClamAV message scan size limit to ' ${ CLAMAV_MESSAGE_SIZE_LIMIT } ' "
2023-05-12 14:04:41 +00:00
2023-05-15 13:46:13 +00:00
# do a short sanity check: ClamAV does not support setting a maximum size greater than 4000M (at all)
2023-05-24 07:06:59 +00:00
if [ [ $( numfmt --from= si " ${ CLAMAV_MESSAGE_SIZE_LIMIT } " ) -gt $( numfmt --from= si 4000M) ] ] ; then
2023-05-15 13:46:13 +00:00
_log 'warn' "You set 'CLAMAV_MESSAGE_SIZE_LIMIT' to a value larger than 4 Gigabyte, but the maximum value is 4000M for this value - you should correct your configuration"
fi
# For more details, see
# https://github.com/docker-mailserver/docker-mailserver/pull/3341
2023-05-24 07:06:59 +00:00
if [ [ $( numfmt --from= si " ${ CLAMAV_MESSAGE_SIZE_LIMIT } " ) -ge $( numfmt --from= iec 2G) ] ] ; then
2023-05-15 17:11:36 +00:00
_log 'warn' "You set 'CLAMAV_MESSAGE_SIZE_LIMIT' to a value larger than 2 Gibibyte but ClamAV does not scan files larger or equal to 2 Gibibyte"
2023-05-12 14:04:41 +00:00
fi
sedfile -i -E \
" s|^(MaxFileSize).*|\1 ${ CLAMAV_MESSAGE_SIZE_LIMIT } | " \
/etc/clamav/clamd.conf
sedfile -i -E \
" s|^(MaxScanSize).*|\1 ${ CLAMAV_MESSAGE_SIZE_LIMIT } | " \
2023-02-27 19:21:45 +00:00
/etc/clamav/clamd.conf
fi
else
_log 'debug' 'Disabling ClamAV'
2023-02-26 10:42:14 +00:00
echo '@bypass_virus_checks_maps = (1);' >>" ${ DMS_AMAVIS_FILE } "
2023-02-27 19:21:45 +00:00
rm -f /etc/logrotate.d/clamav-* /etc/cron.d/clamav-freshclam
2023-02-26 10:42:14 +00:00
fi
2023-02-27 19:21:45 +00:00
}
2023-02-26 10:42:14 +00:00
2023-05-25 23:01:41 +00:00
function __setup__security__fail2ban( ) {
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_FAIL2BAN } -eq 1 ] ] ; then
2023-02-27 19:21:45 +00:00
_log 'debug' 'Enabling and configuring Fail2Ban'
2023-02-26 10:42:14 +00:00
2023-05-24 07:06:59 +00:00
if [ [ -e /tmp/docker-mailserver/fail2ban-fail2ban.cf ] ] ; then
2023-02-26 10:42:14 +00:00
cp /tmp/docker-mailserver/fail2ban-fail2ban.cf /etc/fail2ban/fail2ban.local
fi
2023-05-24 07:06:59 +00:00
if [ [ -e /tmp/docker-mailserver/fail2ban-jail.cf ] ] ; then
2023-02-26 10:42:14 +00:00
cp /tmp/docker-mailserver/fail2ban-jail.cf /etc/fail2ban/jail.d/user-jail.local
fi
2023-02-27 19:21:45 +00:00
2023-05-24 07:06:59 +00:00
if [ [ ${ FAIL2BAN_BLOCKTYPE } != 'reject' ] ] ; then
2023-02-27 19:21:45 +00:00
echo -e '[Init]\nblocktype = drop' >/etc/fail2ban/action.d/nftables-common.local
fi
echo '[Definition]' >/etc/fail2ban/filter.d/custom.conf
2023-02-26 10:42:14 +00:00
else
2023-02-27 19:21:45 +00:00
_log 'debug' 'Fail2Ban is disabled'
2023-02-26 10:42:14 +00:00
rm -f /etc/logrotate.d/fail2ban
fi
2023-02-27 19:21:45 +00:00
}
2023-02-26 10:42:14 +00:00
2023-05-25 23:01:41 +00:00
function __setup__security__amavis( ) {
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_AMAVIS } -eq 1 ] ] ; then
2023-02-27 19:21:45 +00:00
_log 'debug' 'Configuring Amavis'
2023-05-24 07:06:59 +00:00
if [ [ -f /tmp/docker-mailserver/amavis.cf ] ] ; then
2023-02-26 10:42:14 +00:00
cp /tmp/docker-mailserver/amavis.cf /etc/amavis/conf.d/50-user
fi
sed -i -E \
" s|(log_level).*|\1 = ${ AMAVIS_LOGLEVEL } ;|g " \
/etc/amavis/conf.d/49-docker-mailserver
cat /etc/dms/postfix/master.d/postfix-amavis.cf >>/etc/postfix/master.cf
postconf 'content_filter = smtp-amavis:[127.0.0.1]:10024'
sed -i \
" s|^#\$myhostname = \"mail.example.com\";|\$myhostname = \" ${ HOSTNAME } \";| " \
/etc/amavis/conf.d/05-node_id
else
2023-02-27 19:21:45 +00:00
_log 'debug' 'Disabling Amavis'
_log 'trace' 'Disabling Amavis cron job'
2023-02-26 10:42:14 +00:00
mv /etc/cron.d/amavisd-new /etc/cron.d/amavisd-new.disabled
chmod 0 /etc/cron.d/amavisd-new.disabled
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_CLAMAV } -eq 1 ] ] && [ [ ${ ENABLE_RSPAMD } -eq 0 ] ] ; then
2023-02-26 10:42:14 +00:00
_log 'warn' 'ClamAV will not work when Amavis & rspamd are disabled. Enable either Amavis or rspamd to fix it.'
fi
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_SPAMASSASSIN } -eq 1 ] ] ; then
2023-02-26 10:42:14 +00:00
_log 'warn' 'Spamassassin will not work when Amavis is disabled. Enable Amavis to fix it.'
fi
fi
}
2023-03-18 15:32:48 +00:00
# We can use Sieve to move spam emails to the "Junk" folder.
2023-05-25 23:01:41 +00:00
function _setup_spam_to_junk( ) {
2023-05-24 07:06:59 +00:00
if [ [ ${ MOVE_SPAM_TO_JUNK } -eq 1 ] ] ; then
2023-03-18 15:32:48 +00:00
_log 'debug' 'Spam emails will be moved to the Junk folder'
2023-06-20 11:37:31 +00:00
mkdir -p /usr/lib/dovecot/sieve-global/after/
2023-03-18 15:32:48 +00:00
cat >/usr/lib/dovecot/sieve-global/after/spam_to_junk.sieve << EOF
require [ "fileinto" ,"mailbox" ] ;
if anyof ( header :contains "X-Spam-Flag" "YES" ,
header :contains "X-Spam" "Yes" ) {
fileinto "Junk" ;
}
EOF
sievec /usr/lib/dovecot/sieve-global/after/spam_to_junk.sieve
chown dovecot:root /usr/lib/dovecot/sieve-global/after/spam_to_junk.{ sieve,svbin}
2023-05-24 07:06:59 +00:00
if [ [ ${ ENABLE_SPAMASSASSIN } -eq 1 ] ] && [ [ ${ SPAMASSASSIN_SPAM_TO_INBOX } -eq 0 ] ] ; then
2023-03-18 15:32:48 +00:00
_log 'warning' "'SPAMASSASSIN_SPAM_TO_INBOX=0' but it is required to be 1 for 'MOVE_SPAM_TO_JUNK=1' to work"
fi
else
_log 'debug' 'Spam emails will not be moved to the Junk folder'
fi
}
2023-08-20 22:32:26 +00:00
function _setup_spam_mark_as_read( ) {
if [ [ ${ MARK_SPAM_AS_READ } -eq 1 ] ] ; then
_log 'debug' 'Spam emails will be marked as read'
mkdir -p /usr/lib/dovecot/sieve-global/after/
# Header support: `X-Spam-Flag` (SpamAssassin), `X-Spam` (Rspamd)
cat >/usr/lib/dovecot/sieve-global/after/spam_mark_as_read.sieve << EOF
require [ "mailbox" ,"imap4flags" ] ;
if anyof ( header :contains "X-Spam-Flag" "YES" ,
header :contains "X-Spam" "Yes" ) {
setflag "\\\\Seen" ;
}
EOF
sievec /usr/lib/dovecot/sieve-global/after/spam_mark_as_read.sieve
chown dovecot:root /usr/lib/dovecot/sieve-global/after/spam_mark_as_read.{ sieve,svbin}
if [ [ ${ ENABLE_SPAMASSASSIN } -eq 1 ] ] && [ [ ${ SPAMASSASSIN_SPAM_TO_INBOX } -eq 0 ] ] ; then
_log 'warning' "'SPAMASSASSIN_SPAM_TO_INBOX=0' but it is required to be 1 for 'MARK_SPAM_AS_READ=1' to work"
fi
else
_log 'debug' 'Spam emails will not be marked as read'
fi
}