diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index e6dc6f70..9b299847 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -13,7 +13,9 @@ mail_location = maildir:~/ mail_plugins = quota acl zlib antispam auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@ ssl_protocols = !SSLv3 !SSLv2 -ssl_cipher_list = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA +ssl_prefer_server_ciphers = yes +ssl_cipher_list = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA +ssl_options = no_compression # Automatically regenerates every week ssl_dh_parameters_length = 2048 log_timestamp = "%Y-%m-%d %H:%M:%S " diff --git a/data/conf/dovecot/sieve_after b/data/conf/dovecot/sieve_after index ae6aa5fe..0b43dbcf 100644 --- a/data/conf/dovecot/sieve_after +++ b/data/conf/dovecot/sieve_after @@ -7,6 +7,18 @@ require "envelope"; if header :contains "X-Spam-Flag" "YES" { fileinto "Junk"; } -if envelope :detail :matches "to" "*" { - fileinto :create "INBOX/${1}"; + +if allof ( + envelope :detail :matches "to" "*", + header :contains "X-Moo-Tag" "YES", + mailboxexists "INBOX/${s}" + ) { + fileinto "INBOX/${s}"; +} +elsif allof ( + envelope :detail :matches "to" "*", + header :contains "X-Moo-Tag" "YES" + ) { + set :lower "s" "${1}"; + fileinto :create "INBOX/${s}"; } diff --git a/data/conf/nginx/site.conf b/data/conf/nginx/site.conf index ffc3f607..d754eae1 100644 --- a/data/conf/nginx/site.conf +++ b/data/conf/nginx/site.conf @@ -5,9 +5,9 @@ server { ssl_certificate_key /etc/ssl/mail/key.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; - ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; + ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA'; + add_header Strict-Transport-Security "max-age=15768000; includeSubDomains"; ssl_ecdh_curve secp384r1; - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; index index.php index.html; server_name _ autodiscover.* autoconfig.*; error_log /var/log/nginx/error.log; diff --git a/data/conf/postfix/main.cf b/data/conf/postfix/main.cf index 6912d6b4..4f365677 100644 --- a/data/conf/postfix/main.cf +++ b/data/conf/postfix/main.cf @@ -69,12 +69,16 @@ smtpd_tls_dh1024_param_file = /etc/ssl/mail/dhparams.pem smtpd_tls_eecdh_grade = strong smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL smtpd_tls_loglevel = 1 -smtpd_tls_mandatory_ciphers = high -smtpd_tls_mandatory_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL +smtp_tls_mandatory_protocols = !SSLv2, !SSLv3 +smtp_tls_protocols = !SSLv2, !SSLv3 +lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3 +lmtp_tls_protocols = !SSLv2, !SSLv3 smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3 smtpd_tls_protocols = !SSLv2, !SSLv3 +smtpd_tls_mandatory_ciphers = high smtpd_tls_security_level = may -tls_high_cipherlist = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA +tls_ssl_options = NO_COMPRESSION +tls_high_cipherlist = EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA virtual_alias_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_spamalias_maps.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_alias_domain_catchall_maps.cf virtual_gid_maps = static:5000 virtual_mailbox_base = /var/vmail/ diff --git a/data/conf/rspamd/dynmaps/authoritative.php b/data/conf/rspamd/dynmaps/authoritative.php new file mode 100644 index 00000000..b2c101f7 --- /dev/null +++ b/data/conf/rspamd/dynmaps/authoritative.php @@ -0,0 +1,22 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +$pdo = new PDO($dsn, $database_user, $database_pass, $opt); +$stmt = $pdo->query("SELECT `domain` FROM `domain`"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +while ($row = array_shift($rows)) { + echo strtolower(trim($row['domain'])) . PHP_EOL; +} +$stmt = $pdo->query("SELECT `alias_domain` FROM `alias_domain`"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +while ($row = array_shift($rows)) { + echo strtolower(trim($row['alias_domain'])) . PHP_EOL; +} +?> \ No newline at end of file diff --git a/data/conf/rspamd/dynmaps/tags.php b/data/conf/rspamd/dynmaps/tags.php new file mode 100644 index 00000000..cc6435fe --- /dev/null +++ b/data/conf/rspamd/dynmaps/tags.php @@ -0,0 +1,17 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +$pdo = new PDO($dsn, $database_user, $database_pass, $opt); +$stmt = $pdo->query("SELECT `username` FROM `mailbox` WHERE `wants_tagged_subject` = '1'"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +while ($row = array_shift($rows)) { + echo strtolower(trim($row['username'])) . PHP_EOL; +} +?> \ No newline at end of file diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 292b7d08..7e254d3b 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -10,3 +10,52 @@ rspamd_config.MAILCOW_AUTH = { rspamd_config.MAILCOW_MOO = function (task) return true end + +local modify_subject_map = rspamd_config:add_map({ + url = 'http://nginx:8081/tags.php', + type = 'map', + description = 'Map of users to use subject tags for' +}) + +local auth_domain_map = rspamd_config:add_map({ + url = 'http://nginx:8081/authoritative.php', + type = 'map', + description = 'Map of domains we are authoritative for' +}) + +rspamd_config.ADD_DELIMITER_TAG = { + callback = function(task) + local util = require("rspamd_util") + local rspamd_logger = require "rspamd_logger" + local user_tagged = task:get_recipients(1)[1]['user'] + local domain = task:get_recipients(1)[1]['domain'] + local user, tag = user_tagged:match("([^+]+)+(.*)") + local authdomain = auth_domain_map:get_key(domain) + + if tag and authdomain then + rspamd_logger.infox("Domain %s is part of mailcow, start reading tag settings", domain) + local user_untagged = user .. '@' .. domain + rspamd_logger.infox("Querying tag settings for user %1", user_untagged) + if modify_subject_map:get_key(user_untagged) then + rspamd_logger.infox("User wants subject modified for tagged mail") + local sbj = task:get_header('Subject') + if tag then + rspamd_logger.infox("Found tag %1, will modify subject header", tag) + new_sbj = '=?UTF-8?B?' .. tostring(util.encode_base64('[' .. tag .. '] ' .. sbj)) .. '?=' + task:set_rmilter_reply({ + remove_headers = {['Subject'] = 1}, + add_headers = {['Subject'] = new_sbj} + }) + end + else + rspamd_logger.infox("Add X-Moo-Tag header") + task:set_rmilter_reply({ + add_headers = {['X-Moo-Tag'] = 'YES'} + }) + end + else + rspamd_logger.infox("Skip delimiter handling for untagged message or authenticated user") + end + return false + end +} diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php index b2976bec..d2adca8e 100644 --- a/data/web/inc/footer.inc.php +++ b/data/web/inc/footer.inc.php @@ -1,5 +1,5 @@ - - +
diff --git a/docker-compose.yml b/docker-compose.yml index 3888762c..a31b4244 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -70,6 +70,7 @@ services: php-fpm-mailcow: image: andryyy/mailcow-dockerized:phpfpm + command: "php-fpm -d date.timezone=${TZ}" depends_on: - pdns-mailcow volumes: @@ -84,7 +85,6 @@ services: - DBUSER=${DBUSER} - DBPASS=${DBPASS} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - - TZ=${TZ} restart: always networks: mailcow-network: