From 04116982a5035f040969f38edc8297d33518265e Mon Sep 17 00:00:00 2001 From: Michael Kuron <1748330+mkuron@users.noreply.github.com> Date: Thu, 23 Jan 2025 22:16:54 +0100 Subject: [PATCH 01/13] Remove discontinued Nixspam DNSBL --- data/Dockerfiles/postfix/postfix.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 8ffb76f6a..da0b93769 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -403,7 +403,6 @@ postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 list.dnswl.org=127.0.[0..255].1*-4 list.dnswl.org=127.0.[0..255].2*-6 list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 bl.spamcop.net*2 bl.suomispam.net*2 hostkarma.junkemailfilter.com=127.0.0.2*3 From 45d14254f292c498a23eaca7c9f6e02a9de26834 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 24 Jan 2025 10:06:50 +0100 Subject: [PATCH 02/13] [Postfix] Remove discontinued Nixspam DNSBL from existing dns_blocklists.cf --- data/Dockerfiles/postfix/postfix.sh | 5 ++++- docker-compose.yml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index da0b93769..2960444cb 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -395,7 +395,7 @@ EOF if [ ! -f /opt/postfix/conf/dns_blocklists.cf ]; then cat < /opt/postfix/conf/dns_blocklists.cf -# This file can be edited. +# This file can be edited. # Delete this file and restart postfix container to revert any changes. postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 hostkarma.junkemailfilter.com=127.0.0.1*-2 @@ -418,6 +418,9 @@ EOF fi DNSBL_CONFIG=$(grep -v '^#' /opt/postfix/conf/dns_blocklists.cf | grep '\S') +# Remove discontinued Nixspam DNSBL from existing dns_blocklists.cf +sed -i '/ix\.dnsbl\.manitu\.net\*2/d' /opt/postfix/conf/dns_blocklists.cf + if [ ! -z "$DNSBL_CONFIG" ]; then echo -e "\e[33mChecking if ASN for your IP is listed for Spamhaus Bad ASN List...\e[0m" if [ -n "$SPAMHAUS_DQS_KEY" ]; then diff --git a/docker-compose.yml b/docker-compose.yml index cd85304b4..a11e02d1a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -316,7 +316,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.78 + image: mailcow/postfix:1.79 depends_on: mysql-mailcow: condition: service_started From 60a2270d1e7d0985901378bea83295b3df6bf127 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 28 Jan 2025 14:25:56 +0100 Subject: [PATCH 03/13] clamd: update to 1.4.2 + build from source instead using alpine packages --- data/Dockerfiles/clamd/Dockerfile | 104 ++++++++++++++++++++++++++++-- data/Dockerfiles/clamd/clamd.sh | 1 + docker-compose.yml | 2 +- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index 1850d4bed..4392c84e5 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -1,14 +1,104 @@ -FROM alpine:3.20 +FROM alpine:3.21 AS builder -LABEL maintainer = "The Infrastructure Company GmbH " +WORKDIR /src +ENV CLAMD_VERSION=1.4.2 RUN apk upgrade --no-cache \ && apk add --update --no-cache \ - rsync \ - clamav \ - bind-tools \ - bash \ - tini + g++ \ + gcc \ + gdb \ + make \ + cmake \ + py3-pytest \ + python3 \ + valgrind \ + bzip2-dev \ + check-dev \ + curl-dev \ + json-c-dev \ + libmilter-dev \ + libxml2-dev \ + linux-headers \ + ncurses-dev \ + openssl-dev \ + pcre2-dev \ + zlib-dev \ + cargo \ + rust + +RUN mkdir -p /src \ + && wget -P /src https://www.clamav.net/downloads/production/clamav-${CLAMD_VERSION}.tar.gz \ + && tar xzfv /src/clamav-${CLAMD_VERSION}.tar.gz \ + && cd /src/clamav-${CLAMD_VERSION} \ + && mkdir build \ + && cmake . \ + -D CMAKE_BUILD_TYPE="Release" \ + -D CMAKE_INSTALL_PREFIX="/usr" \ + -D CMAKE_INSTALL_LIBDIR="/usr/lib" \ + -D APP_CONFIG_DIRECTORY="/etc/clamav" \ + -D DATABASE_DIRECTORY="/var/lib/clamav" \ + -D ENABLE_CLAMONACC=OFF \ + -D ENABLE_EXAMPLES=OFF \ + -D ENABLE_MILTER=ON \ + -D ENABLE_MAN_PAGES=OFF \ + -D ENABLE_STATIC_LIB=OFF \ + -D ENABLE_JSON_SHARED=ON \ + && cmake --build . \ + && make DESTDIR="/clamav" -j$(($(nproc) - 1)) install \ + && rm -r "/clamav/usr/lib/pkgconfig/" \ + && sed -e "s|^\(Example\)|\# \1|" \ + -e "s|.*\(LocalSocket\) .*|\1 /tmp/clamd.sock|" \ + -e "s|.*\(TCPSocket\) .*|\1 3310|" \ + -e "s|.*\(TCPAddr\) .*|#\1 0.0.0.0|" \ + -e "s|.*\(User\) .*|\1 clamav|" \ + -e "s|^\#\(LogFile\) .*|\1 /var/log/clamav/clamd.log|" \ + -e "s|^\#\(LogTime\).*|\1 yes|" \ + "/clamav/etc/clamav/clamd.conf.sample" > "/clamav/etc/clamav/clamd.conf" \ + && sed -e "s|^\(Example\)|\# \1|" \ + -e "s|.*\(DatabaseOwner\) .*|\1 clamav|" \ + -e "s|^\#\(UpdateLogFile\) .*|\1 /var/log/clamav/freshclam.log|" \ + -e "s|^\#\(NotifyClamd\).*|\1 /etc/clamav/clamd.conf|" \ + -e "s|^\#\(ScriptedUpdates\).*|\1 yes|" \ + "/clamav/etc/clamav/freshclam.conf.sample" > "/clamav/etc/clamav/freshclam.conf" \ + && sed -e "s|^\(Example\)|\# \1|" \ + -e "s|.*\(MilterSocket\) .*|\1 inet:7357|" \ + -e "s|.*\(User\) .*|\1 clamav|" \ + -e "s|^\#\(LogFile\) .*|\1 /var/log/clamav/milter.log|" \ + -e "s|^\#\(LogTime\).*|\1 yes|" \ + -e "s|.*\(\ClamdSocket\) .*|\1 unix:/tmp/clamd.sock|" \ + "/clamav/etc/clamav/clamav-milter.conf.sample" > "/clamav/etc/clamav/clamav-milter.conf" || exit 1 + + +FROM alpine:3.21 + +LABEL maintainer = "The Infrastructure Company GmbH " + +EXPOSE 3310 +EXPOSE 7357 + +RUN apk upgrade --no-cache \ + && apk add --update --no-cache \ + tzdata \ + rsync \ + bind-tools \ + bash \ + tini \ + json-c \ + libbz2 \ + libcurl \ + libmilter \ + libxml2 \ + ncurses-libs \ + pcre2 \ + zlib \ + libgcc \ + && addgroup -S "clamav" && \ + adduser -D -G "clamav" -h "/var/lib/clamav" -s "/bin/false" -S "clamav" && \ + install -d -m 755 -g "clamav" -o "clamav" "/var/log/clamav" && \ + chown -R clamav:clamav /var/lib/clamav + +COPY --from=builder "/clamav" "/" # init COPY clamd.sh /clamd.sh diff --git a/data/Dockerfiles/clamd/clamd.sh b/data/Dockerfiles/clamd/clamd.sh index 10df8072b..2c6e75dc6 100755 --- a/data/Dockerfiles/clamd/clamd.sh +++ b/data/Dockerfiles/clamd/clamd.sh @@ -91,6 +91,7 @@ done ) & BACKGROUND_TASKS+=($!) +echo "$(clamd -V) is starting... please wait a moment." nice -n10 clamd & BACKGROUND_TASKS+=($!) diff --git a/docker-compose.yml b/docker-compose.yml index cd85304b4..706a02309 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,7 +64,7 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.66 + image: mailcow/clamd:1.70 restart: always depends_on: unbound-mailcow: From 65bc581fab5331fbb35b92f775d2c6a3f31f1bcd Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 28 Jan 2025 14:36:43 +0100 Subject: [PATCH 04/13] clamd: remove exposed ports from buildfile --- data/Dockerfiles/clamd/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index 4392c84e5..12158160d 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -74,9 +74,6 @@ FROM alpine:3.21 LABEL maintainer = "The Infrastructure Company GmbH " -EXPOSE 3310 -EXPOSE 7357 - RUN apk upgrade --no-cache \ && apk add --update --no-cache \ tzdata \ From 1a087bb2c8a1f5866f698629f070e8f895e61ec2 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 28 Jan 2025 14:49:11 +0100 Subject: [PATCH 05/13] clamd: cleanup dockerfile --- data/Dockerfiles/clamd/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index 12158160d..e60e7eef1 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -27,11 +27,9 @@ RUN apk upgrade --no-cache \ cargo \ rust -RUN mkdir -p /src \ - && wget -P /src https://www.clamav.net/downloads/production/clamav-${CLAMD_VERSION}.tar.gz \ +RUN wget -P /src https://www.clamav.net/downloads/production/clamav-${CLAMD_VERSION}.tar.gz \ && tar xzfv /src/clamav-${CLAMD_VERSION}.tar.gz \ && cd /src/clamav-${CLAMD_VERSION} \ - && mkdir build \ && cmake . \ -D CMAKE_BUILD_TYPE="Release" \ -D CMAKE_INSTALL_PREFIX="/usr" \ From 0ad327bbe56a8a14d1de2ed88343b571f343d127 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 29 Jan 2025 09:51:45 +0100 Subject: [PATCH 06/13] [Nginx] Use separate vhosts for additional server names --- data/Dockerfiles/nginx/bootstrap.py | 6 ++++-- data/conf/nginx/templates/nginx.conf.j2 | 25 +++++++++++++++++++++++-- data/web/inc/functions.inc.php | 2 +- docker-compose.yml | 2 +- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/data/Dockerfiles/nginx/bootstrap.py b/data/Dockerfiles/nginx/bootstrap.py index de7824334..f294e7cce 100644 --- a/data/Dockerfiles/nginx/bootstrap.py +++ b/data/Dockerfiles/nginx/bootstrap.py @@ -7,7 +7,7 @@ def includes_conf(env, template_vars): listen_plain = "listen_plain.active" listen_ssl = "listen_ssl.active" - server_name_config = f"server_name {template_vars['MAILCOW_HOSTNAME']} autodiscover.* autoconfig.* {template_vars['ADDITIONAL_SERVER_NAMES']};" + server_name_config = f"server_name {template_vars['MAILCOW_HOSTNAME']} autodiscover.* autoconfig.* {' '.join(template_vars['ADDITIONAL_SERVER_NAMES'])};" listen_plain_config = f"listen {template_vars['HTTP_PORT']};" listen_ssl_config = f"listen {template_vars['HTTPS_PORT']};" if not template_vars['DISABLE_IPv6']: @@ -42,6 +42,8 @@ def nginx_conf(env, template_vars): def prepare_template_vars(): ipv4_network = os.getenv("IPV4_NETWORK", "172.22.1") + additional_server_names = os.getenv("ADDITIONAL_SERVER_NAMES", "") + template_vars = { 'IPV4_NETWORK': ipv4_network, 'TRUSTED_NETWORK': os.getenv("TRUSTED_NETWORK", False), @@ -49,7 +51,7 @@ def prepare_template_vars(): 'SKIP_SOGO': os.getenv("SKIP_SOGO", "n").lower() in ("y", "yes"), 'NGINX_USE_PROXY_PROTOCOL': os.getenv("NGINX_USE_PROXY_PROTOCOL", "n").lower() in ("y", "yes"), 'MAILCOW_HOSTNAME': os.getenv("MAILCOW_HOSTNAME", ""), - 'ADDITIONAL_SERVER_NAMES': os.getenv("ADDITIONAL_SERVER_NAMES", "").replace(',', ' '), + 'ADDITIONAL_SERVER_NAMES': [item.strip() for item in additional_server_names.split(",")], 'HTTP_PORT': os.getenv("HTTP_PORT", "80"), 'HTTPS_PORT': os.getenv("HTTPS_PORT", "443"), 'SOGOHOST': os.getenv("SOGOHOST", ipv4_network + ".248"), diff --git a/data/conf/nginx/templates/nginx.conf.j2 b/data/conf/nginx/templates/nginx.conf.j2 index bcb4612bc..b35aeeea3 100644 --- a/data/conf/nginx/templates/nginx.conf.j2 +++ b/data/conf/nginx/templates/nginx.conf.j2 @@ -41,7 +41,7 @@ http { https https; } - # Default + # Default Server Name server { listen 127.0.0.1:65510; # sogo-auth verify internal listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; @@ -55,11 +55,32 @@ http { ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate_key /etc/ssl/mail/key.pem; - server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.* {{ ADDITIONAL_SERVER_NAMES }}; + server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.*; include /etc/nginx/includes/sites-default.conf; } + # Additional Server Names + {% for SERVER_NAME in ADDITIONAL_SERVER_NAMES %} + server { + listen 127.0.0.1:65510; # sogo-auth verify internal + listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {%endif%} + http2 on; + + ssl_certificate /etc/ssl/mail/cert.pem; + ssl_certificate_key /etc/ssl/mail/key.pem; + + server_name {{ SERVER_NAME }}; + + include /etc/nginx/includes/sites-default.conf; + } + {% endfor %} + # rspamd dynmaps: server { listen 8081; diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 7efbee166..73769d902 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -2277,7 +2277,7 @@ function cors($action, $data = null) { } function getBaseURL() { $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $host = $_SERVER['HTTP_HOST']; + $host = $_SERVER['SERVER_NAME']; $base_url = $protocol . '://' . $host; return $base_url; diff --git a/docker-compose.yml b/docker-compose.yml index a11e02d1a..2b5e85cb9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -372,7 +372,7 @@ services: - php-fpm-mailcow - sogo-mailcow - rspamd-mailcow - image: mailcow/nginx:1.01 + image: mailcow/nginx:1.02 dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: From a2e87e0880e8a882cffd47d50d17cd26e3e8846d Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 30 Jan 2025 11:47:55 +0100 Subject: [PATCH 07/13] [Web] Add validation for server_name against allow list --- data/web/inc/functions.inc.php | 22 +++++++++++++++++++--- docker-compose.yml | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 73769d902..0a9b94fc2 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -2275,9 +2275,25 @@ function cors($action, $data = null) { break; } } -function getBaseURL() { - $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; - $host = $_SERVER['SERVER_NAME']; +function getBaseURL($protocol = null) { + // Get current server name + $host = strtolower($_SERVER['SERVER_NAME']); + + // craft allowed server name list + $mailcow_hostname = strtolower(getenv("MAILCOW_HOSTNAME")); + $additional_server_names = strtolower(getenv("ADDITIONAL_SERVER_NAMES")) ?: ""; + $additional_server_names = preg_replace('/\s+/', '', $additional_server_names); + $allowed_server_names = $additional_server_names !== "" ? explode(',', $additional_server_names) : array(); + array_push($allowed_server_names, $mailcow_hostname); + + // Fallback to MAILCOW HOSTNAME if current server name is not in allowed list + if (!in_array($host, $allowed_server_names)) { + $host = $mailcow_hostname; + } + + if (!isset($protocol)) { + $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; + } $base_url = $protocol . '://' . $host; return $base_url; diff --git a/docker-compose.yml b/docker-compose.yml index 2b5e85cb9..c5fae01a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -174,6 +174,7 @@ services: - DEMO_MODE=${DEMO_MODE:-n} - WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n} - CLUSTERMODE=${CLUSTERMODE:-} + - ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-} restart: always networks: mailcow-network: From 3a81b84cf7af2ed7787446a154710f0c34ffe92c Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 30 Jan 2025 14:49:18 +0100 Subject: [PATCH 08/13] [Nginx] Fix #6275 --- data/conf/nginx/templates/sites-default.conf.j2 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/data/conf/nginx/templates/sites-default.conf.j2 b/data/conf/nginx/templates/sites-default.conf.j2 index 783723bfc..23bce6cea 100644 --- a/data/conf/nginx/templates/sites-default.conf.j2 +++ b/data/conf/nginx/templates/sites-default.conf.j2 @@ -137,13 +137,22 @@ location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml { {% if not SKIP_RSPAMD %} location /rspamd/ { + location /rspamd/auth { + # proxy_pass is not inherited + proxy_pass http://{{ RSPAMDHOST }}:11334/auth; + proxy_intercept_errors on; + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%}; + proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%}; + proxy_redirect off; + error_page 401 /_rspamderror.php; + } + proxy_pass http://{{ RSPAMDHOST }}:11334/; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%}; proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%}; proxy_redirect off; - proxy_intercept_errors on; - error_page 401 /_rspamderror.php; } {% endif %} From aac4c6b5f41abd640436fcb75b9376fedfce5d15 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 31 Jan 2025 12:49:39 +0100 Subject: [PATCH 09/13] postfix: added master.pid removal and startsecs to supervisord (#6284) --- data/Dockerfiles/postfix/postfix.sh | 5 +++++ data/Dockerfiles/postfix/supervisord.conf | 1 + 2 files changed, 6 insertions(+) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 2960444cb..9a4c023f1 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -509,6 +509,11 @@ chgrp -R postdrop /var/spool/postfix/public chgrp -R postdrop /var/spool/postfix/maildrop postfix set-permissions +# Checking if there is a leftover of a crashed postfix container before starting a new one +if [ -e /var/spool/postfix/pid/master.pid ]; then + rm -rf /var/spool/postfix/pid/master.pid +fi + # Check Postfix configuration postconf -c /opt/postfix/conf > /dev/null diff --git a/data/Dockerfiles/postfix/supervisord.conf b/data/Dockerfiles/postfix/supervisord.conf index 134a6c6d1..ba70f8edf 100644 --- a/data/Dockerfiles/postfix/supervisord.conf +++ b/data/Dockerfiles/postfix/supervisord.conf @@ -18,6 +18,7 @@ stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 autorestart=true +startsecs=10 [eventlistener:processes] command=/usr/local/sbin/stop-supervisor.sh From 41ba7d97fa943ea7f6709cbb72eeb135bfc13300 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 1 Feb 2025 17:06:07 +0100 Subject: [PATCH 10/13] update postscreen_access.cidr (#6287) --- data/conf/postfix/postscreen_access.cidr | 33 +++++++++++------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index 741b32298..69be54247 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,6 +1,6 @@ -# Whitelist generated by Postwhite v3.4 on Wed Jan 1 00:18:52 UTC 2025 +# Whitelist generated by Postwhite v3.4 on Sat Feb 1 00:18:03 UTC 2025 # https://github.com/stevejenkins/postwhite/ -# 2014 total rules +# 1984 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit 2a01:111:f403:8000::/50 permit @@ -19,10 +19,6 @@ 8.20.114.31 permit 8.25.194.0/23 permit 8.25.196.0/23 permit -8.39.54.0/23 permit -8.39.54.250/31 permit -8.40.222.0/23 permit -8.40.222.250/31 permit 10.162.0.0/16 permit 12.130.86.238 permit 13.110.208.0/21 permit @@ -98,6 +94,7 @@ 27.123.206.76/30 permit 27.123.206.80/28 permit 31.25.48.222 permit +31.47.251.17 permit 34.195.217.107 permit 34.212.163.75 permit 34.215.104.144 permit @@ -110,6 +107,7 @@ 35.191.0.0/16 permit 35.205.92.9 permit 35.242.169.159 permit +37.188.97.188 permit 37.218.248.47 permit 37.218.249.47 permit 37.218.251.62 permit @@ -448,6 +446,7 @@ 69.171.244.0/23 permit 70.37.151.128/25 permit 70.42.149.35 permit +72.3.185.0/24 permit 72.14.192.0/18 permit 72.21.192.0/19 permit 72.21.217.142 permit @@ -508,6 +507,9 @@ 72.30.239.228/31 permit 72.30.239.244/30 permit 72.30.239.248/31 permit +72.32.154.0/24 permit +72.32.217.0/24 permit +72.32.243.0/24 permit 72.52.72.32/28 permit 74.6.128.0/24 permit 74.6.129.0/24 permit @@ -623,6 +625,7 @@ 89.22.108.0/24 permit 91.211.240.0/22 permit 94.169.2.0/23 permit +94.236.119.0/26 permit 94.245.112.0/27 permit 94.245.112.10/31 permit 95.131.104.0/21 permit @@ -1121,6 +1124,7 @@ 103.28.42.0/24 permit 103.151.192.0/23 permit 103.168.172.128/27 permit +103.237.104.0/22 permit 104.43.243.237 permit 104.44.112.128/25 permit 104.47.0.0/17 permit @@ -1335,6 +1339,8 @@ 130.61.9.72 permit 130.162.39.83 permit 130.211.0.0/22 permit +130.248.172.0/24 permit +130.248.173.0/24 permit 131.253.30.0/24 permit 131.253.121.0/26 permit 132.145.13.209 permit @@ -1476,9 +1482,6 @@ 163.114.135.16 permit 164.152.23.32 permit 164.177.132.168/30 permit -165.173.128.0/24 permit -165.173.180.250/31 permit -165.173.182.250/31 permit 166.78.68.0/22 permit 166.78.68.221 permit 166.78.69.169 permit @@ -1507,12 +1510,6 @@ 168.245.12.252 permit 168.245.46.9 permit 168.245.127.231 permit -169.148.129.0/24 permit -169.148.131.0/24 permit -169.148.142.10 permit -169.148.144.0/25 permit -169.148.144.10 permit -169.148.146.0/23 permit 170.10.128.0/24 permit 170.10.129.0/24 permit 170.10.132.56/29 permit @@ -1553,6 +1550,7 @@ 183.240.219.64/29 permit 185.4.120.0/22 permit 185.12.80.0/22 permit +185.28.196.0/22 permit 185.58.84.93 permit 185.80.93.204 permit 185.80.93.227 permit @@ -1618,6 +1616,7 @@ 192.18.139.154 permit 192.18.145.36 permit 192.18.152.58 permit +192.28.128.0/18 permit 192.29.103.128/25 permit 192.30.252.0/22 permit 192.161.144.0/20 permit @@ -1658,6 +1657,7 @@ 198.244.60.0/22 permit 198.245.80.0/20 permit 198.245.81.0/24 permit +199.15.212.0/22 permit 199.15.213.187 permit 199.15.226.37 permit 199.16.156.0/22 permit @@ -1972,9 +1972,6 @@ 2603:1030:20e:3::23c permit 2603:1030:b:3::152 permit 2603:1030:c02:8::14 permit -2607:13c0:0001:0000:0000:0000:0000:7000/116 permit -2607:13c0:0002:0000:0000:0000:0000:1000/116 permit -2607:13c0:0004:0000:0000:0000:0000:0000/116 permit 2607:f8b0:4000::/36 permit 2620:109:c003:104::/64 permit 2620:109:c003:104::215 permit From e645f931dc04c8b8754927d90275a2e77a03931d Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 3 Feb 2025 12:05:08 +0100 Subject: [PATCH 11/13] [Nginx] Add env var for HTTP to HTTPS redirection --- data/Dockerfiles/nginx/bootstrap.py | 1 + data/conf/nginx/templates/nginx.conf.j2 | 40 +++++++++++++++++++++++++ docker-compose.yml | 1 + generate_config.sh | 3 ++ update.sh | 9 +++++- 5 files changed, 53 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/nginx/bootstrap.py b/data/Dockerfiles/nginx/bootstrap.py index f294e7cce..aa85c8b2b 100644 --- a/data/Dockerfiles/nginx/bootstrap.py +++ b/data/Dockerfiles/nginx/bootstrap.py @@ -58,6 +58,7 @@ def prepare_template_vars(): 'RSPAMDHOST': os.getenv("RSPAMDHOST", "rspamd-mailcow"), 'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"), 'DISABLE_IPv6': os.getenv("DISABLE_IPv6", "n").lower() in ("y", "yes"), + 'HTTP_REDIRECT': os.getenv("HTTP_REDIRECT", "n").lower() in ("y", "yes"), } ssl_dir = '/etc/ssl/mail/' diff --git a/data/conf/nginx/templates/nginx.conf.j2 b/data/conf/nginx/templates/nginx.conf.j2 index b35aeeea3..2bb601c50 100644 --- a/data/conf/nginx/templates/nginx.conf.j2 +++ b/data/conf/nginx/templates/nginx.conf.j2 @@ -41,15 +41,42 @@ http { https https; } + {% if HTTP_REDIRECT %} + # HTTP to HTTPS redirect + server { + root /web; + listen {{ HTTP_PORT }} default_server; + listen [::]:{{ HTTP_PORT }} default_server; + + server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.* {{ ADDITIONAL_SERVER_NAMES | join(' ') }}; + + if ( $request_uri ~* "%0A|%0D" ) { return 403; } + location ^~ /.well-known/acme-challenge/ { + allow all; + default_type "text/plain"; + } + location / { + return 301 https://$host$uri$is_args$args; + } + } + {%endif%} + # Default Server Name server { listen 127.0.0.1:65510; # sogo-auth verify internal + + {% if not HTTP_REDIRECT %} listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; {%endif%} + http2 on; ssl_certificate /etc/ssl/mail/cert.pem; @@ -64,12 +91,19 @@ http { {% for SERVER_NAME in ADDITIONAL_SERVER_NAMES %} server { listen 127.0.0.1:65510; # sogo-auth verify internal + + {% if not HTTP_REDIRECT %} listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; {%endif%} + http2 on; ssl_certificate /etc/ssl/mail/cert.pem; @@ -127,12 +161,18 @@ http { {% for cert in valid_cert_dirs %} server { + {% if not HTTP_REDIRECT %} listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; {%endif%} + http2 on; ssl_certificate {{ cert.cert_path }}cert.pem; diff --git a/docker-compose.yml b/docker-compose.yml index 626c957c0..421610bac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -385,6 +385,7 @@ services: - SKIP_SOGO=${SKIP_SOGO:-n} - SKIP_RSPAMD=${SKIP_RSPAMD:-n} - DISABLE_IPv6=${DISABLE_IPv6:-n} + - HTTP_REDIRECT=${HTTP_REDIRECT:-n} - PHPFPMHOST=${PHPFPMHOST:-} - SOGOHOST=${SOGOHOST:-} - RSPAMDHOST=${RSPAMDHOST:-} diff --git a/generate_config.sh b/generate_config.sh index 8f03e3899..e3faf7bb7 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -267,6 +267,9 @@ HTTP_BIND= HTTPS_PORT=443 HTTPS_BIND= +# Redirect HTTP connections to HTTPS - y/n +HTTP_REDIRECT=n + # ------------------------------ # Other bindings # ------------------------------ diff --git a/update.sh b/update.sh index 4240dad37..c11179c5e 100755 --- a/update.sh +++ b/update.sh @@ -352,6 +352,7 @@ adapt_new_options() { "SPAMHAUS_DQS_KEY" "SKIP_UNBOUND_HEALTHCHECK" "DISABLE_NETFILTER_ISOLATION_RULE" + "HTTP_REDIRECT" ) sed -i --follow-symlinks '$a\' mailcow.conf @@ -637,7 +638,13 @@ adapt_new_options() { echo '# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n' >> mailcow.conf echo '# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost' >> mailcow.conf echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf - fi + fi + elif [[ ${option} == "HTTP_REDIRECT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Redirect HTTP connections to HTTPS - y/n' >> mailcow.conf + echo 'HTTP_REDIRECT=n' >> mailcow.conf + fi elif ! grep -q ${option} mailcow.conf; then echo "Adding new option \"${option}\" to mailcow.conf" echo "${option}=n" >> mailcow.conf From 97890b71f1f328fe3c9a101a6eece7e3bdb954e6 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 3 Feb 2025 12:22:13 +0100 Subject: [PATCH 12/13] [Nginx] Invert SKIP container condition --- data/Dockerfiles/nginx/docker-entrypoint.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/nginx/docker-entrypoint.sh b/data/Dockerfiles/nginx/docker-entrypoint.sh index ea2e048e9..45e327ede 100755 --- a/data/Dockerfiles/nginx/docker-entrypoint.sh +++ b/data/Dockerfiles/nginx/docker-entrypoint.sh @@ -8,13 +8,13 @@ until ping ${PHPFPMHOST} -c1 > /dev/null; do echo "Waiting for PHP..." sleep 1 done -if printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then +if ! printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then until ping ${SOGOHOST} -c1 > /dev/null; do echo "Waiting for SOGo..." sleep 1 done fi -if printf "%s\n" "${SKIP_RSPAMD}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then +if ! printf "%s\n" "${SKIP_RSPAMD}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then until ping ${RSPAMDHOST} -c1 > /dev/null; do echo "Waiting for Rspamd..." sleep 1 From 3544a2246eaa60a1218fac7d55f5feb453ee8dc2 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Tue, 4 Feb 2025 13:30:00 +0100 Subject: [PATCH 13/13] [Nginx] fix ADDITIONAL_SERVER_NAMES array --- data/Dockerfiles/nginx/bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/nginx/bootstrap.py b/data/Dockerfiles/nginx/bootstrap.py index aa85c8b2b..ab95c2a6b 100644 --- a/data/Dockerfiles/nginx/bootstrap.py +++ b/data/Dockerfiles/nginx/bootstrap.py @@ -51,7 +51,7 @@ def prepare_template_vars(): 'SKIP_SOGO': os.getenv("SKIP_SOGO", "n").lower() in ("y", "yes"), 'NGINX_USE_PROXY_PROTOCOL': os.getenv("NGINX_USE_PROXY_PROTOCOL", "n").lower() in ("y", "yes"), 'MAILCOW_HOSTNAME': os.getenv("MAILCOW_HOSTNAME", ""), - 'ADDITIONAL_SERVER_NAMES': [item.strip() for item in additional_server_names.split(",")], + 'ADDITIONAL_SERVER_NAMES': [item.strip() for item in additional_server_names.split(",") if item.strip()], 'HTTP_PORT': os.getenv("HTTP_PORT", "80"), 'HTTPS_PORT': os.getenv("HTTPS_PORT", "443"), 'SOGOHOST': os.getenv("SOGOHOST", ipv4_network + ".248"),