From 6dc0bdbfa377eef1198063bccd41bd86a0858800 Mon Sep 17 00:00:00 2001
From: Tomasz Orzechowski
Date: Tue, 9 Jan 2024 22:03:24 +0100
Subject: [PATCH 001/755] Proper number of threads regex.
---
helper-scripts/backup_and_restore.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/helper-scripts/backup_and_restore.sh b/helper-scripts/backup_and_restore.sh
index ee9f0202d..9a0561059 100755
--- a/helper-scripts/backup_and_restore.sh
+++ b/helper-scripts/backup_and_restore.sh
@@ -54,10 +54,10 @@ COMPOSE_FILE=${SCRIPT_DIR}/../docker-compose.yml
ENV_FILE=${SCRIPT_DIR}/../.env
THREADS=$(echo ${THREADS:-1})
-if ! [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
+if ! [[ "${THREADS}" =~ ^[1-9][0-9]?$ ]] ; then
echo "Thread input is not a number!"
exit 1
-elif [[ "${THREADS}" =~ ^[1-9]+$ ]] ; then
+elif [[ "${THREADS}" =~ ^[1-9][0-9]?$ ]] ; then
echo "Using ${THREADS} Thread(s) for this run."
echo "Notice: You can set the Thread count with the THREADS Variable before you run this script."
fi
From ed493f9c3a63d94ef10b149829fe3a752c3532e3 Mon Sep 17 00:00:00 2001
From: KagurazakaNyaa
Date: Thu, 18 Jan 2024 23:28:03 +0800
Subject: [PATCH 002/755] Allow user skip unbound healthcheck
---
data/Dockerfiles/unbound/healthcheck.sh | 10 ++++++++++
generate_config.sh | 4 ++++
2 files changed, 14 insertions(+)
diff --git a/data/Dockerfiles/unbound/healthcheck.sh b/data/Dockerfiles/unbound/healthcheck.sh
index ea94f63b3..760aa02bb 100644
--- a/data/Dockerfiles/unbound/healthcheck.sh
+++ b/data/Dockerfiles/unbound/healthcheck.sh
@@ -1,5 +1,10 @@
#!/bin/bash
+# Skipping DNS check
+if [[ "${SKIP_DNS_CHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
+ SKIP_DNS_CHECK=y
+fi
+
# Declare log function for logfile inside container
function log_to_file() {
echo "$(date +"%Y-%m-%d %H:%M:%S"): $1" > /var/log/healthcheck.log
@@ -66,6 +71,11 @@ function check_netcat() {
}
+if [[ ${SKIP_DNS_CHECK} == "y" ]]; then
+ log_to_file "Healthcheck: ALL CHECKS WERE SKIPPED! Unbound is healthy!"
+ exit 0
+fi
+
# run checks, if check is not returning 0 (return value if check is ok), healthcheck will exit with 1 (marked in docker as unhealthy)
check_ping
diff --git a/generate_config.sh b/generate_config.sh
index 2986f1689..0c8a9bcfe 100755
--- a/generate_config.sh
+++ b/generate_config.sh
@@ -363,6 +363,10 @@ SKIP_IP_CHECK=n
SKIP_HTTP_VERIFICATION=n
+# Skip DNS check in Unbound container - y/n
+
+SKIP_DNS_CHECK=n
+
# Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n
SKIP_CLAMD=${SKIP_CLAMD}
From b89d71e6e4d42d1082f92914ff453d1272c67088 Mon Sep 17 00:00:00 2001
From: KagurazakaNyaa
Date: Thu, 18 Jan 2024 23:48:59 +0800
Subject: [PATCH 003/755] change variable name
---
data/Dockerfiles/unbound/healthcheck.sh | 8 ++++----
generate_config.sh | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/data/Dockerfiles/unbound/healthcheck.sh b/data/Dockerfiles/unbound/healthcheck.sh
index 760aa02bb..a96eaab41 100644
--- a/data/Dockerfiles/unbound/healthcheck.sh
+++ b/data/Dockerfiles/unbound/healthcheck.sh
@@ -1,8 +1,8 @@
#!/bin/bash
-# Skipping DNS check
-if [[ "${SKIP_DNS_CHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
- SKIP_DNS_CHECK=y
+# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!)
+if [[ "${SKIP_UNBOUND_HEALTHCHECK}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
+ SKIP_UNBOUND_HEALTHCHECK=y
fi
# Declare log function for logfile inside container
@@ -71,7 +71,7 @@ function check_netcat() {
}
-if [[ ${SKIP_DNS_CHECK} == "y" ]]; then
+if [[ ${SKIP_UNBOUND_HEALTHCHECK} == "y" ]]; then
log_to_file "Healthcheck: ALL CHECKS WERE SKIPPED! Unbound is healthy!"
exit 0
fi
diff --git a/generate_config.sh b/generate_config.sh
index 0c8a9bcfe..e936348ec 100755
--- a/generate_config.sh
+++ b/generate_config.sh
@@ -365,7 +365,7 @@ SKIP_HTTP_VERIFICATION=n
# Skip DNS check in Unbound container - y/n
-SKIP_DNS_CHECK=n
+SKIP_UNBOUND_HEALTHCHECK=n
# Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n
From aa1d92dfbbcb555caf5f1a39032b7361254240aa Mon Sep 17 00:00:00 2001
From: KagurazakaNyaa
Date: Thu, 18 Jan 2024 23:50:26 +0800
Subject: [PATCH 004/755] add SKIP_UNBOUND_HEALTHCHECK to docker-compose.yml
---
docker-compose.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/docker-compose.yml b/docker-compose.yml
index 5a0730c7e..4f5a4d31c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,6 +5,7 @@ services:
image: mailcow/unbound:1.19.1
environment:
- TZ=${TZ}
+ - SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
volumes:
- ./data/hooks/unbound:/hooks:Z
- ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro,Z
From d2edf359ac3ebdc51d56aab488ffc5dd927db13b Mon Sep 17 00:00:00 2001
From: KagurazakaNyaa
Date: Thu, 18 Jan 2024 23:53:08 +0800
Subject: [PATCH 005/755] update config comment
---
generate_config.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/generate_config.sh b/generate_config.sh
index e936348ec..e62d16892 100755
--- a/generate_config.sh
+++ b/generate_config.sh
@@ -363,7 +363,7 @@ SKIP_IP_CHECK=n
SKIP_HTTP_VERIFICATION=n
-# Skip DNS check in Unbound container - y/n
+# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n
SKIP_UNBOUND_HEALTHCHECK=n
From 9d4055fc4d3a67221160f0d8342f41f77e28dd8e Mon Sep 17 00:00:00 2001
From: KagurazakaNyaa
Date: Fri, 19 Jan 2024 00:07:51 +0800
Subject: [PATCH 006/755] add parameter SKIP_UNBOUND_HEALTHCHECK to old
installations
---
update.sh | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/update.sh b/update.sh
index 623242d5b..ad77beac7 100755
--- a/update.sh
+++ b/update.sh
@@ -480,6 +480,7 @@ CONFIG_ARRAY=(
"WATCHDOG_VERBOSE"
"WEBAUTHN_ONLY_TRUSTED_VENDORS"
"SPAMHAUS_DQS_KEY"
+ "SKIP_UNBOUND_HEALTHCHECK"
)
detect_bad_asn
@@ -747,6 +748,12 @@ for option in ${CONFIG_ARRAY[@]}; do
echo '# Enable watchdog verbose logging' >> mailcow.conf
echo 'WATCHDOG_VERBOSE=n' >> mailcow.conf
fi
+ elif [[ ${option} == "SKIP_UNBOUND_HEALTHCHECK" ]]; then
+ if ! grep -q ${option} mailcow.conf; then
+ echo "Adding new option \"${option}\" to mailcow.conf"
+ echo '# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n' >> mailcow.conf
+ echo 'SKIP_UNBOUND_HEALTHCHECK=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 25bdc4c9ed93392e71ee0b32bcdb51572bd75172 Mon Sep 17 00:00:00 2001
From: Luca Barbato
Date: Mon, 22 Jan 2024 09:50:24 +0100
Subject: [PATCH 007/755] Test for openrc configuration file instead of alpine
This way other distro using openrc can be supported.
---
update.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/update.sh b/update.sh
index 623242d5b..4e16f1193 100755
--- a/update.sh
+++ b/update.sh
@@ -116,11 +116,11 @@ migrate_docker_nat() {
echo "Working on IPv6 NAT, please wait..."
echo ${NAT_CONFIG} > /etc/docker/daemon.json
ip6tables -F -t nat
- [[ -e /etc/alpine-release ]] && rc-service docker restart || systemctl restart docker.service
+ [[ -e /etc/rc.conf ]] && rc-service docker restart || systemctl restart docker.service
if [[ $? -ne 0 ]]; then
echo -e "\e[31mError:\e[0m Failed to activate IPv6 NAT! Reverting and exiting."
rm /etc/docker/daemon.json
- if [[ -e /etc/alpine-release ]]; then
+ if [[ -e /etc/rc.conf ]]; then
rc-service docker restart
else
systemctl reset-failed docker.service
From 53be119e39b0db25c45bb0f058f5259e6b9d1347 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Mon, 22 Jan 2024 10:22:24 +0100
Subject: [PATCH 008/755] compose: bump unbound version
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 4f5a4d31c..4e7420567 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,7 +2,7 @@ version: '2.1'
services:
unbound-mailcow:
- image: mailcow/unbound:1.19.1
+ image: mailcow/unbound:1.20
environment:
- TZ=${TZ}
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
From 6e7a0eb66222e52d8144802c132c2131d1badd45 Mon Sep 17 00:00:00 2001
From: Nya Candy
Date: Thu, 18 Jan 2024 15:00:54 +0800
Subject: [PATCH 009/755] fix: watchdog webhook body variables injector
---
data/Dockerfiles/watchdog/watchdog.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh
index d43cb38ac..cb342c138 100755
--- a/data/Dockerfiles/watchdog/watchdog.sh
+++ b/data/Dockerfiles/watchdog/watchdog.sh
@@ -170,7 +170,7 @@ function notify_error() {
fi
# Replace subject and body placeholders
- WEBHOOK_BODY=$(echo ${WATCHDOG_NOTIFY_WEBHOOK_BODY} | sed "s|\$SUBJECT\|\${SUBJECT}|$SUBJECT|g" | sed "s|\$BODY\|\${BODY}|$BODY|")
+ WEBHOOK_BODY=$(echo ${WATCHDOG_NOTIFY_WEBHOOK_BODY} | sed "s/\$SUBJECT\|\${SUBJECT}/$SUBJECT/g" | sed "s/\$BODY\|\${BODY}/$BODY/g")
# POST to webhook
curl -X POST -H "Content-Type: application/json" ${CURL_VERBOSE} -d "${WEBHOOK_BODY}" ${WATCHDOG_NOTIFY_WEBHOOK}
From 7da5e3697e4373fb8220bbc5bcfa79aa98793743 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Mon, 22 Jan 2024 10:31:27 +0100
Subject: [PATCH 010/755] compose: bump watchdog version
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 5a0730c7e..7dbfe0e5f 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -457,7 +457,7 @@ services:
- /lib/modules:/lib/modules:ro
watchdog-mailcow:
- image: mailcow/watchdog:2.01
+ image: mailcow/watchdog:2.02
dns:
- ${IPV4_NETWORK:-172.22.1}.254
tmpfs:
From a0613e4b1085d3a4de8f5872b0a6deeed8efc066 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Mon, 22 Jan 2024 11:26:26 +0100
Subject: [PATCH 011/755] fix: rollback of Alpine 3.19 were possible
---
data/Dockerfiles/acme/Dockerfile | 2 +-
data/Dockerfiles/phpfpm/Dockerfile | 2 +-
data/Dockerfiles/unbound/Dockerfile | 2 +-
data/Dockerfiles/watchdog/Dockerfile | 2 +-
docker-compose.yml | 4 ++--
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/data/Dockerfiles/acme/Dockerfile b/data/Dockerfiles/acme/Dockerfile
index 08271bddb..254b5b331 100644
--- a/data/Dockerfiles/acme/Dockerfile
+++ b/data/Dockerfiles/acme/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.19
+FROM alpine:3.18
LABEL maintainer "The Infrastructure Company GmbH GmbH "
diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile
index c1a35f4d3..22036b9b3 100644
--- a/data/Dockerfiles/phpfpm/Dockerfile
+++ b/data/Dockerfiles/phpfpm/Dockerfile
@@ -1,4 +1,4 @@
-FROM php:8.2-fpm-alpine3.19
+FROM php:8.2-fpm-alpine3.18
LABEL maintainer "The Infrastructure Company GmbH "
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?.*)$
diff --git a/data/Dockerfiles/unbound/Dockerfile b/data/Dockerfiles/unbound/Dockerfile
index 4411a1d26..f56cbc6e5 100644
--- a/data/Dockerfiles/unbound/Dockerfile
+++ b/data/Dockerfiles/unbound/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.19
+FROM alpine:3.18
LABEL maintainer "The Infrastructure Company GmbH GmbH "
diff --git a/data/Dockerfiles/watchdog/Dockerfile b/data/Dockerfiles/watchdog/Dockerfile
index b94789aac..73acde68f 100644
--- a/data/Dockerfiles/watchdog/Dockerfile
+++ b/data/Dockerfiles/watchdog/Dockerfile
@@ -1,4 +1,4 @@
-FROM alpine:3.19
+FROM alpine:3.18
LABEL maintainer "The Infrastructure Company GmbH "
# Installation
diff --git a/docker-compose.yml b/docker-compose.yml
index 739108bcb..c1883f907 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -108,7 +108,7 @@ services:
- rspamd
php-fpm-mailcow:
- image: mailcow/phpfpm:1.86
+ image: mailcow/phpfpm:1.87
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
depends_on:
- redis-mailcow
@@ -399,7 +399,7 @@ services:
condition: service_started
unbound-mailcow:
condition: service_healthy
- image: mailcow/acme:1.86
+ image: mailcow/acme:1.87
dns:
- ${IPV4_NETWORK:-172.22.1}.254
environment:
From deb6f0babc5017a2d140d971a8dbab289e5f3072 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Tue, 23 Jan 2024 08:46:06 +0100
Subject: [PATCH 012/755] issue: added architecture as dropdown
---
.github/ISSUE_TEMPLATE/Bug_report.yml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/.github/ISSUE_TEMPLATE/Bug_report.yml b/.github/ISSUE_TEMPLATE/Bug_report.yml
index 3cfbbe0dc..afa1a27f8 100644
--- a/.github/ISSUE_TEMPLATE/Bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/Bug_report.yml
@@ -62,6 +62,16 @@ body:
- nightly
validations:
required: true
+ - type: dropdown
+ attributes:
+ label: "Which architecture are you using?"
+ description: "#### `uname -m`"
+ multiple: false
+ options:
+ - x86
+ - ARM64 (aarch64)
+ validations:
+ required: true
- type: input
attributes:
label: "Operating System:"
From f74573f5d04cf578e4101a5e32a0814d9fd849ae Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Wed, 31 Jan 2024 16:14:42 +0100
Subject: [PATCH 013/755] chore(deps): update peter-evans/create-pull-request
action to v6 (#5683)
Signed-off-by: milkmaker
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
.github/workflows/update_postscreen_access_list.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/update_postscreen_access_list.yml b/.github/workflows/update_postscreen_access_list.yml
index 42502f303..ddfa7ac86 100644
--- a/.github/workflows/update_postscreen_access_list.yml
+++ b/.github/workflows/update_postscreen_access_list.yml
@@ -22,7 +22,7 @@ jobs:
bash helper-scripts/update_postscreen_whitelist.sh
- name: Create Pull Request
- uses: peter-evans/create-pull-request@v5
+ uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.mailcow_action_Update_postscreen_access_cidr_pat }}
commit-message: update postscreen_access.cidr
From cc77caad671f0ae40068351861d81712da8f2b9e Mon Sep 17 00:00:00 2001
From: milkmaker
Date: Thu, 1 Feb 2024 00:13:51 +0000
Subject: [PATCH 014/755] update postscreen_access.cidr
---
data/conf/postfix/postscreen_access.cidr | 81 +++++++++++++++++-------
1 file changed, 59 insertions(+), 22 deletions(-)
diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr
index 0497e64a0..e8273ecc5 100644
--- a/data/conf/postfix/postscreen_access.cidr
+++ b/data/conf/postfix/postscreen_access.cidr
@@ -1,9 +1,10 @@
-# Whitelist generated by Postwhite v3.4 on Mon Jan 1 00:15:22 UTC 2024
+# Whitelist generated by Postwhite v3.4 on Thu Feb 1 00:13:50 UTC 2024
# https://github.com/stevejenkins/postwhite/
-# 2052 total rules
+# 2089 total rules
2a00:1450:4000::/36 permit
2a01:111:f400::/48 permit
2a01:111:f403:8000::/50 permit
+2a01:111:f403:8000::/51 permit
2a01:111:f403::/49 permit
2a01:111:f403:c000::/51 permit
2a01:111:f403:f000::/52 permit
@@ -116,7 +117,6 @@
40.92.0.0/16 permit
40.107.0.0/16 permit
40.112.65.63 permit
-40.117.80.0/24 permit
43.228.184.0/22 permit
44.206.138.57 permit
44.209.42.157 permit
@@ -206,7 +206,6 @@
52.95.49.88/29 permit
52.96.91.34 permit
52.96.111.82 permit
-52.96.172.98 permit
52.96.214.50 permit
52.96.222.194 permit
52.96.222.226 permit
@@ -405,7 +404,6 @@
66.196.81.228/30 permit
66.196.81.232/31 permit
66.196.81.234 permit
-66.211.168.230/31 permit
66.211.170.88/29 permit
66.211.184.0/23 permit
66.218.74.64/30 permit
@@ -594,9 +592,10 @@
74.112.67.243 permit
74.125.0.0/16 permit
74.202.227.40 permit
-74.208.4.192/26 permit
-74.208.5.64/26 permit
-74.208.122.0/26 permit
+74.208.4.200 permit
+74.208.4.201 permit
+74.208.4.220 permit
+74.208.4.221 permit
74.209.250.0/24 permit
75.2.70.75 permit
76.223.128.0/19 permit
@@ -624,12 +623,20 @@
77.238.189.148/30 permit
81.7.169.128/25 permit
81.223.46.0/27 permit
-82.165.159.0/24 permit
-82.165.159.0/26 permit
-82.165.229.31 permit
-82.165.229.130 permit
-82.165.230.21 permit
-82.165.230.22 permit
+82.165.159.2 permit
+82.165.159.3 permit
+82.165.159.4 permit
+82.165.159.12 permit
+82.165.159.13 permit
+82.165.159.14 permit
+82.165.159.34 permit
+82.165.159.35 permit
+82.165.159.40 permit
+82.165.159.41 permit
+82.165.159.42 permit
+82.165.159.45 permit
+82.165.159.130 permit
+82.165.159.131 permit
84.116.6.0/23 permit
84.116.36.0/24 permit
84.116.50.0/23 permit
@@ -1430,6 +1437,7 @@
135.84.216.0/22 permit
136.143.160.0/24 permit
136.143.161.0/24 permit
+136.143.178.49 permit
136.143.182.0/23 permit
136.143.184.0/24 permit
136.143.188.0/24 permit
@@ -1952,12 +1960,41 @@
212.82.111.228/31 permit
212.82.111.230 permit
212.123.28.40 permit
-212.227.15.0/24 permit
-212.227.15.0/25 permit
-212.227.17.0/27 permit
-212.227.126.128/25 permit
+212.227.15.3 permit
+212.227.15.4 permit
+212.227.15.5 permit
+212.227.15.6 permit
+212.227.15.14 permit
+212.227.15.15 permit
+212.227.15.18 permit
+212.227.15.19 permit
+212.227.15.25 permit
+212.227.15.26 permit
+212.227.15.29 permit
+212.227.15.44 permit
+212.227.15.45 permit
+212.227.15.46 permit
+212.227.15.47 permit
+212.227.15.50 permit
+212.227.15.52 permit
+212.227.15.53 permit
+212.227.15.54 permit
+212.227.15.55 permit
+212.227.17.11 permit
+212.227.17.12 permit
+212.227.17.18 permit
+212.227.17.19 permit
+212.227.17.20 permit
+212.227.17.21 permit
+212.227.17.22 permit
+212.227.17.26 permit
+212.227.17.28 permit
+212.227.17.29 permit
+212.227.126.224 permit
+212.227.126.225 permit
+212.227.126.226 permit
+212.227.126.227 permit
213.46.255.0/24 permit
-213.165.64.0/23 permit
213.199.128.139 permit
213.199.128.145 permit
213.199.138.181 permit
@@ -2021,10 +2058,10 @@
216.203.30.55 permit
216.203.33.178/31 permit
216.205.24.0/24 permit
+216.221.160.0/19 permit
216.239.32.0/19 permit
-217.72.192.64/26 permit
-217.72.192.248/29 permit
-217.72.207.0/27 permit
+217.72.192.77 permit
+217.72.192.78 permit
217.77.141.52 permit
217.77.141.59 permit
217.175.194.0/24 permit
From 93e4d586060aa1045395aae1bcf7a7126bbdc9f1 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Thu, 1 Feb 2024 08:41:11 +0100
Subject: [PATCH 015/755] sogo: fix ACL allow authenticated users + rebuild on
Bookworm
---
data/Dockerfiles/sogo/Dockerfile | 7 ++++---
docker-compose.yml | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile
index 54d676b9a..a4601c405 100644
--- a/data/Dockerfiles/sogo/Dockerfile
+++ b/data/Dockerfiles/sogo/Dockerfile
@@ -1,7 +1,8 @@
-FROM debian:bullseye-slim
+FROM debian:bookworm-slim
LABEL maintainer "The Infrastructure Company GmbH GmbH "
ARG DEBIAN_FRONTEND=noninteractive
+ARG DEBIAN_VERSION=bookworm
ARG SOGO_DEBIAN_REPOSITORY=http://www.axis.cz/linux/debian
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$
ARG GOSU_VERSION=1.17
@@ -21,7 +22,7 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
syslog-ng-core \
syslog-ng-mod-redis \
dirmngr \
- netcat \
+ netcat-traditional \
psmisc \
wget \
patch \
@@ -32,7 +33,7 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
&& mkdir /usr/share/doc/sogo \
&& touch /usr/share/doc/sogo/empty.sh \
&& apt-key adv --keyserver keys.openpgp.org --recv-key 74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 \
- && echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} bullseye sogo-v5" > /etc/apt/sources.list.d/sogo.list \
+ && echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} ${DEBIAN_VERSION} sogo-v5" > /etc/apt/sources.list.d/sogo.list \
&& apt-get update && apt-get install -y --no-install-recommends \
sogo \
sogo-activesync \
diff --git a/docker-compose.yml b/docker-compose.yml
index c1883f907..8dc193ebe 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -172,7 +172,7 @@ services:
- phpfpm
sogo-mailcow:
- image: mailcow/sogo:1.121
+ image: mailcow/sogo:1.122
environment:
- DBNAME=${DBNAME}
- DBUSER=${DBUSER}
From b236fd3ac683ea1434521807c5d118040b54882c Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Tue, 30 Jan 2024 10:15:33 +0100
Subject: [PATCH 016/755] [Netfilter] add mailcow isolation rule to MAILCOW
chain
[Netfilter] add mailcow rule to docker-user chain
[Netfilter] add mailcow isolation rule to MAILCOW chain
[Netfilter] add mailcow isolation rule to MAILCOW chain
[Netfilter] set mailcow isolation rule before redis
[Netfilter] clear bans in redis after connecting
[Netfilter] simplify mailcow isolation rule for compatibility with iptables-nft
[Netfilter] stop container after mariadb, redis, dovecot, solr
[Netfilter] simplify mailcow isolation rule for compatibility with iptables-nft
[Netfilter] add exception for mailcow isolation rule for HA setups
[Netfilter] add exception for mailcow isolation rule for HA setups
[Netfilter] add DISABLE_NETFILTER_ISOLATION_RULE
[Netfilter] fix wrong var name
[Netfilter] add DISABLE_NETFILTER_ISOLATION_RULE to update and generate_config sh
---
.gitignore | 1 +
data/Dockerfiles/dovecot/docker-entrypoint.sh | 9 +
data/Dockerfiles/netfilter/main.py | 90 ++++++----
.../Dockerfiles/netfilter/modules/IPTables.py | 39 +++++
data/Dockerfiles/netfilter/modules/Logger.py | 3 +-
.../Dockerfiles/netfilter/modules/NFTables.py | 165 +++++++++++++++++-
data/conf/dovecot/dovecot.conf | 3 +
docker-compose.yml | 16 +-
generate_config.sh | 3 +
update.sh | 8 +
10 files changed, 290 insertions(+), 47 deletions(-)
diff --git a/.gitignore b/.gitignore
index 3595ecb1e..e25639a70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,6 +13,7 @@ data/conf/dovecot/acl_anyone
data/conf/dovecot/dovecot-master.passwd
data/conf/dovecot/dovecot-master.userdb
data/conf/dovecot/extra.conf
+data/conf/dovecot/mail_replica.conf
data/conf/dovecot/global_sieve_*
data/conf/dovecot/last_login
data/conf/dovecot/lua
diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh
index f1e2e9668..a9545f338 100755
--- a/data/Dockerfiles/dovecot/docker-entrypoint.sh
+++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh
@@ -335,6 +335,15 @@ sys.exit()
EOF
fi
+# Set mail_replica for HA setups
+if [[ -n ${MAILCOW_REPLICA_IP} && -n ${DOVEADM_REPLICA_PORT} ]]; then
+ cat < /etc/dovecot/mail_replica.conf
+# Autogenerated by mailcow
+mail_replica = tcp:${MAILCOW_REPLICA_IP}:${DOVEADM_REPLICA_PORT}
+EOF
+fi
+
+
# 401 is user dovecot
if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then
openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem
diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py
index d5c1db502..8480c9efa 100644
--- a/data/Dockerfiles/netfilter/main.py
+++ b/data/Dockerfiles/netfilter/main.py
@@ -21,28 +21,6 @@ from modules.IPTables import IPTables
from modules.NFTables import NFTables
-# connect to redis
-while True:
- try:
- redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '')
- redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '')
- if "".__eq__(redis_slaveof_ip):
- r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0)
- else:
- r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0)
- r.ping()
- except Exception as ex:
- print('%s - trying again in 3 seconds' % (ex))
- time.sleep(3)
- else:
- break
-pubsub = r.pubsub()
-
-# rename fail2ban to netfilter
-if r.exists('F2B_LOG'):
- r.rename('F2B_LOG', 'NETFILTER_LOG')
-
-
# globals
WHITELIST = []
BLACKLIST= []
@@ -50,18 +28,8 @@ bans = {}
quit_now = False
exit_code = 0
lock = Lock()
-
-
-# init Logger
-logger = Logger(r)
-# init backend
-backend = sys.argv[1]
-if backend == "nftables":
- logger.logInfo('Using NFTables backend')
- tables = NFTables("MAILCOW", logger)
-else:
- logger.logInfo('Using IPTables backend')
- tables = IPTables("MAILCOW", logger)
+chain_name = "MAILCOW"
+r = None
def refreshF2boptions():
@@ -250,9 +218,10 @@ def clear():
with lock:
tables.clearIPv4Table()
tables.clearIPv6Table()
- r.delete('F2B_ACTIVE_BANS')
- r.delete('F2B_PERM_BANS')
- pubsub.unsubscribe()
+ if r:
+ r.delete('F2B_ACTIVE_BANS')
+ r.delete('F2B_PERM_BANS')
+ pubsub.unsubscribe()
def watch():
logger.logInfo('Watching Redis channel F2B_CHANNEL')
@@ -409,15 +378,60 @@ def quit(signum, frame):
if __name__ == '__main__':
- refreshF2boptions()
+ # init Logger
+ logger = Logger(None)
+
+ # init backend
+ backend = sys.argv[1]
+ if backend == "nftables":
+ logger.logInfo('Using NFTables backend')
+ tables = NFTables(chain_name, logger)
+ else:
+ logger.logInfo('Using IPTables backend')
+ tables = IPTables(chain_name, logger)
+
# In case a previous session was killed without cleanup
clear()
+
# Reinit MAILCOW chain
# Is called before threads start, no locking
logger.logInfo("Initializing mailcow netfilter chain")
tables.initChainIPv4()
tables.initChainIPv6()
+ if os.getenv("DISABLE_NETFILTER_ISOLATION_RULE").lower() in ("y", "yes"):
+ logger.logInfo(f"Skipping {chain_name} isolation")
+ else:
+ logger.logInfo(f"Setting {chain_name} isolation")
+ tables.create_mailcow_isolation_rule("br-mailcow", [3306, 6379, 8983, 12345], os.getenv("MAILCOW_REPLICA_IP"))
+
+ # connect to redis
+ while True:
+ try:
+ redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '')
+ redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '')
+ if "".__eq__(redis_slaveof_ip):
+ r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0)
+ else:
+ r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0)
+ r.ping()
+ except Exception as ex:
+ print('%s - trying again in 3 seconds' % (ex))
+ time.sleep(3)
+ else:
+ break
+ pubsub = r.pubsub()
+ Logger.r = r
+
+ # rename fail2ban to netfilter
+ if r.exists('F2B_LOG'):
+ r.rename('F2B_LOG', 'NETFILTER_LOG')
+ # clear bans in redis
+ r.delete('F2B_ACTIVE_BANS')
+ r.delete('F2B_PERM_BANS')
+
+ refreshF2boptions()
+
watch_thread = Thread(target=watch)
watch_thread.daemon = True
watch_thread.start()
diff --git a/data/Dockerfiles/netfilter/modules/IPTables.py b/data/Dockerfiles/netfilter/modules/IPTables.py
index c60ecc613..29a9fb65a 100644
--- a/data/Dockerfiles/netfilter/modules/IPTables.py
+++ b/data/Dockerfiles/netfilter/modules/IPTables.py
@@ -1,5 +1,6 @@
import iptc
import time
+import os
class IPTables:
def __init__(self, chain_name, logger):
@@ -211,3 +212,41 @@ class IPTables:
target = rule.create_target("SNAT")
target.to_source = snat_target
return rule
+
+ def create_mailcow_isolation_rule(self, _interface:str, _dports:list, _allow:str = ""):
+ try:
+ chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), self.chain_name)
+
+ # insert mailcow isolation rule
+ rule = iptc.Rule()
+ rule.in_interface = f'! {_interface}'
+ rule.out_interface = _interface
+ rule.protocol = 'tcp'
+ rule.create_target("DROP")
+ match = rule.create_match("multiport")
+ match.dports = ','.join(map(str, _dports))
+
+ if rule in chain.rules:
+ chain.delete_rule(rule)
+ chain.insert_rule(rule, position=0)
+
+ # insert mailcow isolation exception rule
+ if _allow != "":
+ rule = iptc.Rule()
+ rule.src = _allow
+ rule.in_interface = f'! {_interface}'
+ rule.out_interface = _interface
+ rule.protocol = 'tcp'
+ rule.create_target("ACCEPT")
+ match = rule.create_match("multiport")
+ match.dports = ','.join(map(str, _dports))
+
+ if rule in chain.rules:
+ chain.delete_rule(rule)
+ chain.insert_rule(rule, position=0)
+
+
+ return True
+ except Exception as e:
+ self.logger.logCrit(f"Error adding {self.chain_name} isolation: {e}")
+ return False
\ No newline at end of file
diff --git a/data/Dockerfiles/netfilter/modules/Logger.py b/data/Dockerfiles/netfilter/modules/Logger.py
index d60d52fad..2a40de0ce 100644
--- a/data/Dockerfiles/netfilter/modules/Logger.py
+++ b/data/Dockerfiles/netfilter/modules/Logger.py
@@ -10,7 +10,8 @@ class Logger:
tolog['time'] = int(round(time.time()))
tolog['priority'] = priority
tolog['message'] = message
- self.r.lpush('NETFILTER_LOG', json.dumps(tolog, ensure_ascii=False))
+ if self.r:
+ self.r.lpush('NETFILTER_LOG', json.dumps(tolog, ensure_ascii=False))
print(message)
def logWarn(self, message):
diff --git a/data/Dockerfiles/netfilter/modules/NFTables.py b/data/Dockerfiles/netfilter/modules/NFTables.py
index d341dc36b..e8e02c476 100644
--- a/data/Dockerfiles/netfilter/modules/NFTables.py
+++ b/data/Dockerfiles/netfilter/modules/NFTables.py
@@ -1,5 +1,6 @@
import nftables
import ipaddress
+import os
class NFTables:
def __init__(self, chain_name, logger):
@@ -266,6 +267,17 @@ class NFTables:
return self.nft_exec_dict(delete_command)
+ def delete_filter_rule(self, _family:str, _chain: str, _handle:str):
+ delete_command = self.get_base_dict()
+ _rule_opts = {'family': _family,
+ 'table': 'filter',
+ 'chain': _chain,
+ 'handle': _handle }
+ _delete = {'delete': {'rule': _rule_opts} }
+ delete_command["nftables"].append(_delete)
+
+ return self.nft_exec_dict(delete_command)
+
def snat_rule(self, _family: str, snat_target: str, source_address: str):
chain_name = self.nft_chain_names[_family]['nat']['postrouting']
@@ -381,7 +393,7 @@ class NFTables:
break
return chain_handle
- def get_rules_handle(self, _family: str, _table: str, chain_name: str):
+ def get_rules_handle(self, _family: str, _table: str, chain_name: str, _comment_filter = "mailcow"):
rule_handle = []
# Command: 'nft list chain {family} {table} {chain_name}'
_chain_opts = {'family': _family, 'table': _table, 'name': chain_name}
@@ -397,7 +409,7 @@ class NFTables:
rule = _object["rule"]
if rule["family"] == _family and rule["table"] == _table and rule["chain"] == chain_name:
- if rule.get("comment") and rule["comment"] == "mailcow":
+ if rule.get("comment") and rule["comment"] == _comment_filter:
rule_handle.append(rule["handle"])
return rule_handle
@@ -493,3 +505,152 @@ class NFTables:
position+=1
return position if rule_found else False
+
+ def create_mailcow_isolation_rule(self, _interface:str, _dports:list, _allow:str = ""):
+ family = "ip"
+ table = "filter"
+ comment_filter_drop = "mailcow isolation"
+ comment_filter_allow = "mailcow isolation allow"
+ json_command = self.get_base_dict()
+
+ # Delete old mailcow isolation rules
+ handles = self.get_rules_handle(family, table, self.chain_name, comment_filter_drop)
+ for handle in handles:
+ self.delete_filter_rule(family, self.chain_name, handle)
+ handles = self.get_rules_handle(family, table, self.chain_name, comment_filter_allow)
+ for handle in handles:
+ self.delete_filter_rule(family, self.chain_name, handle)
+
+ # insert mailcow isolation rule
+ _match_dict_drop = [
+ {
+ "match": {
+ "op": "!=",
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "right": _interface
+ }
+ },
+ {
+ "match": {
+ "op": "==",
+ "left": {
+ "meta": {
+ "key": "oifname"
+ }
+ },
+ "right": _interface
+ }
+ },
+ {
+ "match": {
+ "op": "==",
+ "left": {
+ "payload": {
+ "protocol": "tcp",
+ "field": "dport"
+ }
+ },
+ "right": {
+ "set": _dports
+ }
+ }
+ },
+ {
+ "counter": {
+ "packets": 0,
+ "bytes": 0
+ }
+ },
+ {
+ "drop": None
+ }
+ ]
+ rule_drop = { "insert": { "rule": {
+ "family": family,
+ "table": table,
+ "chain": self.chain_name,
+ "comment": comment_filter_drop,
+ "expr": _match_dict_drop
+ }}}
+ json_command["nftables"].append(rule_drop)
+
+ # insert mailcow isolation allow rule
+ if _allow != "":
+ _match_dict_allow = [
+ {
+ "match": {
+ "op": "==",
+ "left": {
+ "payload": {
+ "protocol": "ip",
+ "field": "saddr"
+ }
+ },
+ "right": _allow
+ }
+ },
+ {
+ "match": {
+ "op": "!=",
+ "left": {
+ "meta": {
+ "key": "iifname"
+ }
+ },
+ "right": _interface
+ }
+ },
+ {
+ "match": {
+ "op": "==",
+ "left": {
+ "meta": {
+ "key": "oifname"
+ }
+ },
+ "right": _interface
+ }
+ },
+ {
+ "match": {
+ "op": "==",
+ "left": {
+ "payload": {
+ "protocol": "tcp",
+ "field": "dport"
+ }
+ },
+ "right": {
+ "set": _dports
+ }
+ }
+ },
+ {
+ "counter": {
+ "packets": 0,
+ "bytes": 0
+ }
+ },
+ {
+ "accept": None
+ }
+ ]
+ rule_allow = { "insert": { "rule": {
+ "family": family,
+ "table": table,
+ "chain": self.chain_name,
+ "comment": comment_filter_allow,
+ "expr": _match_dict_allow
+ }}}
+ json_command["nftables"].append(rule_allow)
+
+ success = self.nft_exec_dict(json_command)
+ if success == False:
+ self.logger.logCrit(f"Error adding {self.chain_name} isolation")
+ return False
+
+ return True
\ No newline at end of file
diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf
index 159e39f41..729686fb1 100644
--- a/data/conf/dovecot/dovecot.conf
+++ b/data/conf/dovecot/dovecot.conf
@@ -247,6 +247,9 @@ plugin {
mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
mail_log_fields = uid box msgid size
mail_log_cached_only = yes
+
+ # Try set mail_replica
+ !include_try /etc/dovecot/mail_replica.conf
}
service quota-warning {
executable = script /usr/local/bin/quota_notify.py
diff --git a/docker-compose.yml b/docker-compose.yml
index c1883f907..fa92546ad 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -21,6 +21,7 @@ services:
image: mariadb:10.5
depends_on:
- unbound-mailcow
+ - netfilter-mailcow
stop_grace_period: 45s
volumes:
- mysql-vol-1:/var/lib/mysql/
@@ -46,6 +47,8 @@ services:
volumes:
- redis-vol-1:/data/
restart: always
+ depends_on:
+ - netfilter-mailcow
ports:
- "${REDIS_PORT:-127.0.0.1:7654}:6379"
environment:
@@ -222,6 +225,7 @@ services:
image: mailcow/dovecot:1.27
depends_on:
- mysql-mailcow
+ - netfilter-mailcow
dns:
- ${IPV4_NETWORK:-172.22.1}.254
cap_add:
@@ -242,6 +246,8 @@ services:
environment:
- DOVECOT_MASTER_USER=${DOVECOT_MASTER_USER:-}
- DOVECOT_MASTER_PASS=${DOVECOT_MASTER_PASS:-}
+ - MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
+ - DOVEADM_REPLICA_PORT=${DOVEADM_REPLICA_PORT:-}
- LOG_LINES=${LOG_LINES:-9999}
- DBNAME=${DBNAME}
- DBUSER=${DBUSER}
@@ -437,12 +443,6 @@ services:
netfilter-mailcow:
image: mailcow/netfilter:1.55
stop_grace_period: 30s
- depends_on:
- - dovecot-mailcow
- - postfix-mailcow
- - sogo-mailcow
- - php-fpm-mailcow
- - redis-mailcow
restart: always
privileged: true
environment:
@@ -453,6 +453,8 @@ services:
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
+ - MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
+ - DISABLE_NETFILTER_ISOLATION_RULE=${DISABLE_NETFILTER_ISOLATION_RULE:-n}
network_mode: "host"
volumes:
- /lib/modules:/lib/modules:ro
@@ -553,6 +555,8 @@ services:
solr-mailcow:
image: mailcow/solr:1.8.2
restart: always
+ depends_on:
+ - netfilter-mailcow
volumes:
- solr-vol-1:/opt/solr/server/solr/dovecot-fts/data
ports:
diff --git a/generate_config.sh b/generate_config.sh
index e62d16892..05d9ee2f1 100755
--- a/generate_config.sh
+++ b/generate_config.sh
@@ -494,6 +494,9 @@ WEBAUTHN_ONLY_TRUSTED_VENDORS=n
# Otherwise it will work normally.
SPAMHAUS_DQS_KEY=
+# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n
+# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost
+DISABLE_NETFILTER_ISOLATION_RULE=n
EOF
mkdir -p data/assets/ssl
diff --git a/update.sh b/update.sh
index 5df32e00e..f1e31652c 100755
--- a/update.sh
+++ b/update.sh
@@ -481,6 +481,7 @@ CONFIG_ARRAY=(
"WEBAUTHN_ONLY_TRUSTED_VENDORS"
"SPAMHAUS_DQS_KEY"
"SKIP_UNBOUND_HEALTHCHECK"
+ "DISABLE_NETFILTER_ISOLATION_RULE"
)
detect_bad_asn
@@ -754,6 +755,13 @@ for option in ${CONFIG_ARRAY[@]}; do
echo '# Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n' >> mailcow.conf
echo 'SKIP_UNBOUND_HEALTHCHECK=n' >> mailcow.conf
fi
+ elif [[ ${option} == "DISABLE_NETFILTER_ISOLATION_RULE" ]]; then
+ if ! grep -q ${option} mailcow.conf; then
+ echo "Adding new option \"${option}\" to mailcow.conf"
+ 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
elif ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo "${option}=n" >> mailcow.conf
From 2072301d89683cdbe9a398150b199630d1109d81 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 2 Feb 2024 11:08:44 +0100
Subject: [PATCH 017/755] [Netfilter] only perform cleanup at exit if SIGTERM
was recieved
---
data/Dockerfiles/netfilter/main.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py
index 8480c9efa..7f8dd9fbf 100644
--- a/data/Dockerfiles/netfilter/main.py
+++ b/data/Dockerfiles/netfilter/main.py
@@ -376,6 +376,11 @@ def quit(signum, frame):
global quit_now
quit_now = True
+def quit_clear(signum, frame):
+ global exit_code
+ clear()
+ sys.exit(exit_code)
+
if __name__ == '__main__':
# init Logger
@@ -474,8 +479,7 @@ if __name__ == '__main__':
whitelistupdate_thread.daemon = True
whitelistupdate_thread.start()
- signal.signal(signal.SIGTERM, quit)
- atexit.register(clear)
+ signal.signal(signal.SIGTERM, quit_clear)
while not quit_now:
time.sleep(0.5)
From 2e57325dde15062fbecdf5ca49e29072f70a4814 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Fri, 2 Feb 2024 11:27:46 +0100
Subject: [PATCH 018/755] docker-compose.yml: Bump dovecot + netfilter version
---
docker-compose.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index fa92546ad..31923d46c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -222,7 +222,7 @@ services:
- sogo
dovecot-mailcow:
- image: mailcow/dovecot:1.27
+ image: mailcow/dovecot:1.28
depends_on:
- mysql-mailcow
- netfilter-mailcow
@@ -441,7 +441,7 @@ services:
- acme
netfilter-mailcow:
- image: mailcow/netfilter:1.55
+ image: mailcow/netfilter:1.56
stop_grace_period: 30s
restart: always
privileged: true
From 39589bd441291c7068f6642782be6edff0bcb371 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 2 Feb 2024 12:46:50 +0100
Subject: [PATCH 019/755] [Netfilter] only perform cleanup at exit if SIGTERM
was recieved
---
data/Dockerfiles/netfilter/main.py | 37 +++++++++++++++++++-----------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py
index 7f8dd9fbf..c3b19c4e8 100644
--- a/data/Dockerfiles/netfilter/main.py
+++ b/data/Dockerfiles/netfilter/main.py
@@ -30,6 +30,8 @@ exit_code = 0
lock = Lock()
chain_name = "MAILCOW"
r = None
+pubsub = None
+clear_before_quit = False
def refreshF2boptions():
@@ -218,10 +220,12 @@ def clear():
with lock:
tables.clearIPv4Table()
tables.clearIPv6Table()
- if r:
- r.delete('F2B_ACTIVE_BANS')
- r.delete('F2B_PERM_BANS')
- pubsub.unsubscribe()
+ try:
+ if r is not None:
+ r.delete('F2B_ACTIVE_BANS')
+ r.delete('F2B_PERM_BANS')
+ except Exception as ex:
+ logger.logWarn('Error clearing redis keys F2B_ACTIVE_BANS and F2B_PERM_BANS: %s' % ex)
def watch():
logger.logInfo('Watching Redis channel F2B_CHANNEL')
@@ -229,6 +233,7 @@ def watch():
global quit_now
global exit_code
+ global pubsub
while not quit_now:
try:
@@ -249,6 +254,7 @@ def watch():
ban(addr)
except Exception as ex:
logger.logWarn('Error reading log line from pubsub: %s' % ex)
+ pubsub = None
quit_now = True
exit_code = 2
@@ -372,17 +378,22 @@ def blacklistUpdate():
permBan(net=net, unban=True)
time.sleep(60.0 - ((time.time() - start_time) % 60.0))
-def quit(signum, frame):
- global quit_now
- quit_now = True
-
-def quit_clear(signum, frame):
- global exit_code
- clear()
+def sigterm_quit(signum, frame):
+ global clear_before_quit
+ clear_before_quit = True
sys.exit(exit_code)
+def berfore_quit():
+ if clear_before_quit:
+ clear()
+ if pubsub is not None:
+ pubsub.unsubscribe()
+
if __name__ == '__main__':
+ atexit.register(berfore_quit)
+ signal.signal(signal.SIGTERM, sigterm_quit)
+
# init Logger
logger = Logger(None)
@@ -420,12 +431,12 @@ if __name__ == '__main__':
else:
r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0)
r.ping()
+ pubsub = r.pubsub()
except Exception as ex:
print('%s - trying again in 3 seconds' % (ex))
time.sleep(3)
else:
break
- pubsub = r.pubsub()
Logger.r = r
# rename fail2ban to netfilter
@@ -479,8 +490,6 @@ if __name__ == '__main__':
whitelistupdate_thread.daemon = True
whitelistupdate_thread.start()
- signal.signal(signal.SIGTERM, quit_clear)
-
while not quit_now:
time.sleep(0.5)
From c941e802d4177a7d8278f3a80359d833d9770bec Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 2 Feb 2024 12:57:21 +0100
Subject: [PATCH 020/755] [Netfilter] only perform cleanup at exit if SIGTERM
was recieved
---
data/Dockerfiles/netfilter/main.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py
index c3b19c4e8..f4acd4612 100644
--- a/data/Dockerfiles/netfilter/main.py
+++ b/data/Dockerfiles/netfilter/main.py
@@ -228,12 +228,12 @@ def clear():
logger.logWarn('Error clearing redis keys F2B_ACTIVE_BANS and F2B_PERM_BANS: %s' % ex)
def watch():
- logger.logInfo('Watching Redis channel F2B_CHANNEL')
- pubsub.subscribe('F2B_CHANNEL')
-
+ global pubsub
global quit_now
global exit_code
- global pubsub
+
+ logger.logInfo('Watching Redis channel F2B_CHANNEL')
+ pubsub.subscribe('F2B_CHANNEL')
while not quit_now:
try:
From a3104934850cd6663c9e7347478f6f8902def03a Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 2 Feb 2024 16:52:41 +0100
Subject: [PATCH 021/755] [Dovecot] fix repl_health.sh
---
data/Dockerfiles/dovecot/repl_health.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/data/Dockerfiles/dovecot/repl_health.sh b/data/Dockerfiles/dovecot/repl_health.sh
index 05d891421..93b66da49 100755
--- a/data/Dockerfiles/dovecot/repl_health.sh
+++ b/data/Dockerfiles/dovecot/repl_health.sh
@@ -11,7 +11,7 @@ fi
# Is replication active?
# grep on file is less expensive than doveconf
-if ! grep -qi mail_replica /etc/dovecot/dovecot.conf; then
+if [ -n ${MAILCOW_REPLICA_IP} ]; then
${REDIS_CMDLINE} SET DOVECOT_REPL_HEALTH 1 > /dev/null
exit
fi
From 909f07939e93af0135cc9bd6b5aeb2f9ee50d8fe Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Fri, 2 Feb 2024 17:06:31 +0100
Subject: [PATCH 022/755] dovecot: bump version for repl fix
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index d75d61cb2..26a224b53 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -222,7 +222,7 @@ services:
- sogo
dovecot-mailcow:
- image: mailcow/dovecot:1.28
+ image: mailcow/dovecot:1.28.1
depends_on:
- mysql-mailcow
- netfilter-mailcow
From 57e67ea8f79a1fe218cb0f0ea8ad95a53b9f0179 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 2 Feb 2024 17:40:44 +0100
Subject: [PATCH 023/755] [Netfilter] fix mailcow isolation rule for iptables
---
data/Dockerfiles/netfilter/modules/IPTables.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/data/Dockerfiles/netfilter/modules/IPTables.py b/data/Dockerfiles/netfilter/modules/IPTables.py
index 29a9fb65a..3d3d43974 100644
--- a/data/Dockerfiles/netfilter/modules/IPTables.py
+++ b/data/Dockerfiles/netfilter/modules/IPTables.py
@@ -219,7 +219,7 @@ class IPTables:
# insert mailcow isolation rule
rule = iptc.Rule()
- rule.in_interface = f'! {_interface}'
+ rule.in_interface = f'!{_interface}'
rule.out_interface = _interface
rule.protocol = 'tcp'
rule.create_target("DROP")
@@ -234,7 +234,7 @@ class IPTables:
if _allow != "":
rule = iptc.Rule()
rule.src = _allow
- rule.in_interface = f'! {_interface}'
+ rule.in_interface = f'!{_interface}'
rule.out_interface = _interface
rule.protocol = 'tcp'
rule.create_target("ACCEPT")
From 464b6f2e9328b64b0548deba7ab1c9edb096bf62 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Mon, 5 Feb 2024 09:47:19 +0100
Subject: [PATCH 024/755] [Netfilter] fix redis logs
---
data/Dockerfiles/netfilter/main.py | 4 ++--
data/Dockerfiles/netfilter/modules/Logger.py | 7 +++++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py
index f4acd4612..62e0dda75 100644
--- a/data/Dockerfiles/netfilter/main.py
+++ b/data/Dockerfiles/netfilter/main.py
@@ -395,7 +395,7 @@ if __name__ == '__main__':
signal.signal(signal.SIGTERM, sigterm_quit)
# init Logger
- logger = Logger(None)
+ logger = Logger()
# init backend
backend = sys.argv[1]
@@ -437,7 +437,7 @@ if __name__ == '__main__':
time.sleep(3)
else:
break
- Logger.r = r
+ logger.set_redis(r)
# rename fail2ban to netfilter
if r.exists('F2B_LOG'):
diff --git a/data/Dockerfiles/netfilter/modules/Logger.py b/data/Dockerfiles/netfilter/modules/Logger.py
index 2a40de0ce..25562965f 100644
--- a/data/Dockerfiles/netfilter/modules/Logger.py
+++ b/data/Dockerfiles/netfilter/modules/Logger.py
@@ -2,7 +2,10 @@ import time
import json
class Logger:
- def __init__(self, redis):
+ def __init__(self):
+ self.r = None
+
+ def set_redis(self, redis):
self.r = redis
def log(self, priority, message):
@@ -10,7 +13,7 @@ class Logger:
tolog['time'] = int(round(time.time()))
tolog['priority'] = priority
tolog['message'] = message
- if self.r:
+ if self.r is not None:
self.r.lpush('NETFILTER_LOG', json.dumps(tolog, ensure_ascii=False))
print(message)
From 77e6ef218c9d5b0ceeb873b43435aee4173cc86c Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Mon, 5 Feb 2024 09:54:16 +0100
Subject: [PATCH 025/755] [Netfilter] Update to 1.57
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index 26a224b53..17559bedd 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -441,7 +441,7 @@ services:
- acme
netfilter-mailcow:
- image: mailcow/netfilter:1.56
+ image: mailcow/netfilter:1.57
stop_grace_period: 30s
restart: always
privileged: true
From 38cc85fa4ca08723363c7a672a36383fccf259e2 Mon Sep 17 00:00:00 2001
From: vicente
Date: Wed, 7 Feb 2024 15:36:04 +0100
Subject: [PATCH 026/755] set strict=False
---
data/Dockerfiles/netfilter/modules/NFTables.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/data/Dockerfiles/netfilter/modules/NFTables.py b/data/Dockerfiles/netfilter/modules/NFTables.py
index e8e02c476..38b31ebff 100644
--- a/data/Dockerfiles/netfilter/modules/NFTables.py
+++ b/data/Dockerfiles/netfilter/modules/NFTables.py
@@ -309,8 +309,8 @@ class NFTables:
rule_handle = rule["handle"]
break
- dest_net = ipaddress.ip_network(source_address)
- target_net = ipaddress.ip_network(snat_target)
+ dest_net = ipaddress.ip_network(source_address, strict=False)
+ target_net = ipaddress.ip_network(snat_target, strict=False)
if rule_found:
saddr_ip = rule["expr"][0]["match"]["right"]["prefix"]["addr"]
@@ -321,9 +321,9 @@ class NFTables:
target_ip = rule["expr"][3]["snat"]["addr"]
- saddr_net = ipaddress.ip_network(saddr_ip + '/' + str(saddr_len))
- daddr_net = ipaddress.ip_network(daddr_ip + '/' + str(daddr_len))
- current_target_net = ipaddress.ip_network(target_ip)
+ saddr_net = ipaddress.ip_network(saddr_ip + '/' + str(saddr_len), strict=False)
+ daddr_net = ipaddress.ip_network(daddr_ip + '/' + str(daddr_len), strict=False)
+ current_target_net = ipaddress.ip_network(target_ip, strict=False)
match = all((
dest_net == saddr_net,
@@ -417,7 +417,7 @@ class NFTables:
json_command = self.get_base_dict()
expr_opt = []
- ipaddr_net = ipaddress.ip_network(ipaddr)
+ ipaddr_net = ipaddress.ip_network(ipaddr, strict=False)
right_dict = {'prefix': {'addr': str(ipaddr_net.network_address), 'len': int(ipaddr_net.prefixlen) } }
left_dict = {'payload': {'protocol': _family, 'field': 'saddr'} }
@@ -466,7 +466,7 @@ class NFTables:
current_rule_net = ipaddress.ip_network(current_rule_ip)
# ip to ban
- candidate_net = ipaddress.ip_network(ipaddr)
+ candidate_net = ipaddress.ip_network(ipaddr, strict=False)
if current_rule_net == candidate_net:
rule_handle = _object["rule"]["handle"]
From eb91d9905bc1f4dbdde486e635592bea4ee02726 Mon Sep 17 00:00:00 2001
From: vicente
Date: Wed, 7 Feb 2024 15:48:49 +0100
Subject: [PATCH 027/755] fix typpo in chain order message
---
data/Dockerfiles/netfilter/modules/NFTables.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/data/Dockerfiles/netfilter/modules/NFTables.py b/data/Dockerfiles/netfilter/modules/NFTables.py
index 38b31ebff..4cb0110ae 100644
--- a/data/Dockerfiles/netfilter/modules/NFTables.py
+++ b/data/Dockerfiles/netfilter/modules/NFTables.py
@@ -41,6 +41,7 @@ class NFTables:
exit_code = 2
if chain_position > 0:
+ chain_position += 1
self.logger.logCrit(f'MAILCOW target is in position {chain_position} in the {filter_table} {chain} table, restarting container to fix it...')
err = True
exit_code = 2
From 5a9702771cba4fedbc79331e92ff757f734df58e Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Wed, 7 Feb 2024 17:18:20 +0100
Subject: [PATCH 028/755] [SOGo] Fixed SOGo crash on older kernels < 5.10.0-X
---
data/Dockerfiles/sogo/Dockerfile | 4 ++--
docker-compose.yml | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile
index a4601c405..59fc66804 100644
--- a/data/Dockerfiles/sogo/Dockerfile
+++ b/data/Dockerfiles/sogo/Dockerfile
@@ -1,8 +1,8 @@
-FROM debian:bookworm-slim
+FROM debian:bullseye-slim
LABEL maintainer "The Infrastructure Company GmbH GmbH "
ARG DEBIAN_FRONTEND=noninteractive
-ARG DEBIAN_VERSION=bookworm
+ARG DEBIAN_VERSION=bullseye
ARG SOGO_DEBIAN_REPOSITORY=http://www.axis.cz/linux/debian
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$
ARG GOSU_VERSION=1.17
diff --git a/docker-compose.yml b/docker-compose.yml
index 17559bedd..b36f45b8b 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -175,7 +175,7 @@ services:
- phpfpm
sogo-mailcow:
- image: mailcow/sogo:1.122
+ image: mailcow/sogo:1.122.1
environment:
- DBNAME=${DBNAME}
- DBUSER=${DBUSER}
From d08ccbce789880eb81ebebca48d440637ab36983 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Wed, 7 Feb 2024 17:28:49 +0100
Subject: [PATCH 029/755] dovecot: fix wrong timestamps inside logs
---
data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf | 1 +
data/Dockerfiles/dovecot/syslog-ng.conf | 1 +
2 files changed, 2 insertions(+)
diff --git a/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf b/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf
index f7fc20b7e..519928954 100644
--- a/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf
+++ b/data/Dockerfiles/dovecot/syslog-ng-redis_slave.conf
@@ -7,6 +7,7 @@ options {
use_fqdn(no);
owner("root"); group("adm"); perm(0640);
stats(freq(0));
+ keep_timestamp(no);
bad_hostname("^gconfd$");
};
source s_dgram {
diff --git a/data/Dockerfiles/dovecot/syslog-ng.conf b/data/Dockerfiles/dovecot/syslog-ng.conf
index fcc13587d..3e929e7b9 100644
--- a/data/Dockerfiles/dovecot/syslog-ng.conf
+++ b/data/Dockerfiles/dovecot/syslog-ng.conf
@@ -7,6 +7,7 @@ options {
use_fqdn(no);
owner("root"); group("adm"); perm(0640);
stats(freq(0));
+ keep_timestamp(no);
bad_hostname("^gconfd$");
};
source s_dgram {
From 583c5b48a00bb1f1a61cbc411bc90532fce3ca3b Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Wed, 7 Feb 2024 17:29:36 +0100
Subject: [PATCH 030/755] dovecot: bump to docker image 1.28.1
---
docker-compose.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docker-compose.yml b/docker-compose.yml
index b36f45b8b..0dfd344b5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -222,7 +222,7 @@ services:
- sogo
dovecot-mailcow:
- image: mailcow/dovecot:1.28.1
+ image: mailcow/dovecot:1.28.2
depends_on:
- mysql-mailcow
- netfilter-mailcow
From 63bb8e8cefb4afebd50f12a485f6af5d12c98125 Mon Sep 17 00:00:00 2001
From: DerLinkman
Date: Thu, 8 Feb 2024 12:23:46 +0100
Subject: [PATCH 031/755] unbound: increase check interval to 30s
---
data/Dockerfiles/unbound/Dockerfile | 4 ++--
docker-compose.yml | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/data/Dockerfiles/unbound/Dockerfile b/data/Dockerfiles/unbound/Dockerfile
index f56cbc6e5..f6d072cc6 100644
--- a/data/Dockerfiles/unbound/Dockerfile
+++ b/data/Dockerfiles/unbound/Dockerfile
@@ -20,10 +20,10 @@ EXPOSE 53/udp 53/tcp
COPY docker-entrypoint.sh /docker-entrypoint.sh
-# healthcheck (nslookup)
+# healthcheck (dig, ping, nc)
COPY healthcheck.sh /healthcheck.sh
RUN chmod +x /healthcheck.sh
-HEALTHCHECK --interval=5s --timeout=30s CMD [ "/healthcheck.sh" ]
+HEALTHCHECK --interval=30s --timeout=30s CMD [ "/healthcheck.sh" ]
ENTRYPOINT ["/docker-entrypoint.sh"]
diff --git a/docker-compose.yml b/docker-compose.yml
index 0dfd344b5..df545c15e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,7 +2,7 @@ version: '2.1'
services:
unbound-mailcow:
- image: mailcow/unbound:1.20
+ image: mailcow/unbound:1.21
environment:
- TZ=${TZ}
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
From c90d637a48cdac86363e4937bdd787db8bc94c37 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Thu, 16 Feb 2023 15:32:53 +0100
Subject: [PATCH 032/755] [Web] redirect to sogo after failed sogo-auth
---
data/web/sogo-auth.php | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/data/web/sogo-auth.php b/data/web/sogo-auth.php
index 40fff5856..c34a60def 100644
--- a/data/web/sogo-auth.php
+++ b/data/web/sogo-auth.php
@@ -65,8 +65,7 @@ elseif (isset($_GET['login'])) {
}
}
}
- header('HTTP/1.0 403 Forbidden');
- echo "Forbidden";
+ header("Location: /SOGo/");
exit;
}
// only check for admin-login on sogo GUI requests
From cfce7086a578bc4d3883527b969d80a3067b00fb Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Thu, 16 Feb 2023 15:34:47 +0100
Subject: [PATCH 033/755] [Web] few style changes
---
data/web/css/build/013-datatables.css | 3 ---
data/web/css/build/014-mailcow.css | 20 ++++++++++++++++++++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/data/web/css/build/013-datatables.css b/data/web/css/build/013-datatables.css
index 57e2b6d94..2b19ba24e 100644
--- a/data/web/css/build/013-datatables.css
+++ b/data/web/css/build/013-datatables.css
@@ -8,9 +8,6 @@
.dtr-details {
width: 100%;
}
-.table-striped>tbody>tr:nth-of-type(odd) {
- background-color: #F2F2F2;
-}
td.child>ul>li {
display: flex;
}
diff --git a/data/web/css/build/014-mailcow.css b/data/web/css/build/014-mailcow.css
index 6c70a2a55..8c1d7c2af 100644
--- a/data/web/css/build/014-mailcow.css
+++ b/data/web/css/build/014-mailcow.css
@@ -33,6 +33,13 @@
url('/fonts/noto-sans-v12-latin_greek_cyrillic-700italic.woff2') format('woff2'),
url('/fonts/noto-sans-v12-latin_greek_cyrillic-700italic.woff') format('woff');
}
+
+body {
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background-color: #fbfbfb;
+}
#maxmsgsize { min-width: 80px; }
#slider1 .slider-selection {
background: #FFD700;
@@ -78,6 +85,19 @@
.navbar-fixed-top .navbar-collapse {
max-height: 1000px
}
+.nav-tabs .nav-link, .nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:hover, .nav-tabs .nav-link.disabled:focus {
+ border-color: #dfdfdf;
+}
+.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
+ border-color: #dfdfdf;
+ border-bottom: 1px solid #ffffff;
+}
+.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {
+ border-color: #dfdfdf;
+}
+.nav-tabs {
+ border-bottom: 1px solid #dfdfdf;
+}
.bi {
display: inline-block;
font-size: 12pt;
From 415c1d057499a4f927d4eb4edbca467785fee6a7 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Thu, 16 Feb 2023 15:39:12 +0100
Subject: [PATCH 034/755] [Web] add seperate link for logged in users
---
data/web/inc/functions.customize.inc.php | 25 +++++++++--
data/web/inc/header.inc.php | 9 ++++
data/web/js/site/admin.js | 1 +
.../templates/admin/tab-config-customize.twig | 5 ++-
data/web/templates/base.twig | 41 +++++++++++--------
data/web/templates/index.twig | 4 +-
6 files changed, 64 insertions(+), 21 deletions(-)
diff --git a/data/web/inc/functions.customize.inc.php b/data/web/inc/functions.customize.inc.php
index b72923573..c4df924d9 100644
--- a/data/web/inc/functions.customize.inc.php
+++ b/data/web/inc/functions.customize.inc.php
@@ -122,10 +122,14 @@ function customize($_action, $_item, $_data = null) {
case 'app_links':
$apps = (array)$_data['app'];
$links = (array)$_data['href'];
+ $user_links = (array)$_data['user_href'];
$out = array();
- if (count($apps) == count($links)) {
+ if (count($apps) == count($links) && count($apps) == count($user_links)) {
for ($i = 0; $i < count($apps); $i++) {
- $out[] = array($apps[$i] => $links[$i]);
+ $out[] = array($apps[$i] => array(
+ 'link' => $links[$i],
+ 'user_link' => $user_links[$i]
+ ));
}
try {
$redis->set('APP_LINKS', json_encode($out));
@@ -256,7 +260,22 @@ function customize($_action, $_item, $_data = null) {
);
return false;
}
- return ($app_links) ? $app_links : false;
+
+ if (empty($app_links)){
+ return false;
+ }
+
+ foreach($app_links as $key => $value){
+ foreach($value as $app => $details){
+ if (empty($details['user_link']) || empty($_SESSION['mailcow_cc_username'])){
+ $app_links[$key][$app]['user_link'] = $app_links[$key][$app]['link'];
+ } else {
+ $app_links[$key][$app]['user_link'] = str_replace('%u', $_SESSION['mailcow_cc_username'], $app_links[$key][$app]['user_link']);
+ }
+ }
+ }
+
+ return $app_links;
break;
case 'main_logo':
case 'main_logo_dark':
diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php
index 9afc288dd..c0e166403 100644
--- a/data/web/inc/header.inc.php
+++ b/data/web/inc/header.inc.php
@@ -30,6 +30,14 @@ if(!file_exists($CSSPath)) {
cleanupCSS($hash);
}
+$mailcow_apps_processed = $MAILCOW_APPS;
+for ($i = 0; $i < count($mailcow_apps_processed); $i++) {
+ if (!empty($_SESSION['mailcow_cc_username'])){
+ $mailcow_apps_processed[$i]['user_link'] = str_replace('%u', $_SESSION['mailcow_cc_username'], $mailcow_apps_processed[$i]['user_link']);
+ }
+}
+
+
$globalVariables = [
'mailcow_hostname' => getenv('MAILCOW_HOSTNAME'),
'mailcow_locale' => @$_SESSION['mailcow_locale'],
@@ -45,6 +53,7 @@ $globalVariables = [
'lang' => $lang,
'skip_sogo' => (getenv('SKIP_SOGO') == 'y'),
'allow_admin_email_login' => (getenv('ALLOW_ADMIN_EMAIL_LOGIN') == 'n'),
+ 'mailcow_apps_processed' => $mailcow_apps_processed,
'mailcow_apps' => $MAILCOW_APPS,
'app_links' => customize('get', 'app_links'),
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js
index 80da64167..095557311 100644
--- a/data/web/js/site/admin.js
+++ b/data/web/js/site/admin.js
@@ -711,6 +711,7 @@ jQuery(function($){
if (type == "app_link") {
cols = ' ';
cols += ' ';
+ cols += ' ';
cols += '' + lang.remove_row + ' ';
} else if (type == "f2b_regex") {
cols = ' ';
diff --git a/data/web/templates/admin/tab-config-customize.twig b/data/web/templates/admin/tab-config-customize.twig
index 7fc990a64..4b8f53231 100644
--- a/data/web/templates/admin/tab-config-customize.twig
+++ b/data/web/templates/admin/tab-config-customize.twig
@@ -58,13 +58,15 @@
{{ lang.admin.app_name }}
{{ lang.admin.link }}
+ {{ lang.admin.user_link }}
{% for row in app_links %}
{% for key, val in row %}
-
+
+
{{ lang.admin.remove_row }}
{% endfor %}
@@ -73,6 +75,7 @@
+
{{ lang.admin.remove_row }}
{% endfor %}
diff --git a/data/web/templates/base.twig b/data/web/templates/base.twig
index ca744d2a3..1c027138c 100644
--- a/data/web/templates/base.twig
+++ b/data/web/templates/base.twig
@@ -29,7 +29,7 @@
{% block navbar %}
-
+
{% endif %}
-
+
{% block content %}{% endblock %}
diff --git a/data/web/templates/index.twig b/data/web/templates/index.twig
index aa282547c..bd4f87818 100644
--- a/data/web/templates/index.twig
+++ b/data/web/templates/index.twig
@@ -77,7 +77,9 @@
{% endfor %}
{% for row in app_links %}
{% for key, val in row %}
-
{{ key }}
+
{% endfor %}
{% endfor %}
From 6e35574c721971216aa10da1ba6ace663ad4ca13 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 10 Mar 2023 15:53:09 +0100
Subject: [PATCH 035/755] [Web] add app hide option
---
data/web/inc/functions.customize.inc.php | 6 +++--
data/web/inc/header.inc.php | 24 +++++++++++++++++--
data/web/inc/vars.inc.php | 4 +++-
data/web/js/site/admin.js | 14 +++++++++++
.../templates/admin/tab-config-customize.twig | 12 ++++++++++
data/web/templates/index.twig | 12 +++++++---
6 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/data/web/inc/functions.customize.inc.php b/data/web/inc/functions.customize.inc.php
index c4df924d9..5aef7d720 100644
--- a/data/web/inc/functions.customize.inc.php
+++ b/data/web/inc/functions.customize.inc.php
@@ -123,12 +123,14 @@ function customize($_action, $_item, $_data = null) {
$apps = (array)$_data['app'];
$links = (array)$_data['href'];
$user_links = (array)$_data['user_href'];
+ $hide = (array)$_data['hide'];
$out = array();
- if (count($apps) == count($links) && count($apps) == count($user_links)) {
+ if (count($apps) == count($links) && count($apps) == count($user_links) && count($apps) == count($hide)) {
for ($i = 0; $i < count($apps); $i++) {
$out[] = array($apps[$i] => array(
'link' => $links[$i],
- 'user_link' => $user_links[$i]
+ 'user_link' => $user_links[$i],
+ 'hide' => ($hide[$i] === '0' || $hide[$i] === 0) ? false : true
));
}
try {
diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php
index c0e166403..3f80423ec 100644
--- a/data/web/inc/header.inc.php
+++ b/data/web/inc/header.inc.php
@@ -31,11 +31,29 @@ if(!file_exists($CSSPath)) {
}
$mailcow_apps_processed = $MAILCOW_APPS;
+$app_links = customize('get', 'app_links');
+$app_links_processed = $app_links;
+$hide_mailcow_apps = true;
for ($i = 0; $i < count($mailcow_apps_processed); $i++) {
+ if ($hide_mailcow_apps && !$mailcow_apps_processed[$i]['hide']){
+ $hide_mailcow_apps = false;
+ }
if (!empty($_SESSION['mailcow_cc_username'])){
$mailcow_apps_processed[$i]['user_link'] = str_replace('%u', $_SESSION['mailcow_cc_username'], $mailcow_apps_processed[$i]['user_link']);
}
}
+if ($app_links_processed){
+ for ($i = 0; $i < count($app_links_processed); $i++) {
+ $key = array_key_first($app_links_processed[$i]);
+ if ($hide_mailcow_apps && !$app_links_processed[$i][$key]['hide']){
+ $hide_mailcow_apps = false;
+ }
+ if (!empty($_SESSION['mailcow_cc_username'])){
+ $app_links_processed[$i][$key]['user_link'] = str_replace('%u', $_SESSION['mailcow_cc_username'], $app_links_processed[$i][$key]['user_link']);
+ }
+ }
+}
+
$globalVariables = [
@@ -53,9 +71,11 @@ $globalVariables = [
'lang' => $lang,
'skip_sogo' => (getenv('SKIP_SOGO') == 'y'),
'allow_admin_email_login' => (getenv('ALLOW_ADMIN_EMAIL_LOGIN') == 'n'),
- 'mailcow_apps_processed' => $mailcow_apps_processed,
+ 'hide_mailcow_apps' => $hide_mailcow_apps,
'mailcow_apps' => $MAILCOW_APPS,
- 'app_links' => customize('get', 'app_links'),
+ 'mailcow_apps_processed' => $mailcow_apps_processed,
+ 'app_links' => $app_links,
+ 'app_links_processed' => $app_links_processed,
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
'uri' => $_SERVER['REQUEST_URI'],
'last_login' => last_login('get', $_SESSION['mailcow_cc_username'], 7, 0)['ui']['time']
diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php
index afc801e44..18bc63285 100644
--- a/data/web/inc/vars.inc.php
+++ b/data/web/inc/vars.inc.php
@@ -122,7 +122,9 @@ $SHOW_DKIM_PRIV_KEYS = false;
$MAILCOW_APPS = array(
array(
'name' => 'Webmail',
- 'link' => '/SOGo/',
+ 'link' => '/SOGo/so/',
+ 'user_link' => '/sogo-auth.php?login=%u',
+ 'hide' => true
)
);
diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js
index 095557311..dd6dcce4b 100644
--- a/data/web/js/site/admin.js
+++ b/data/web/js/site/admin.js
@@ -706,20 +706,34 @@ jQuery(function($){
}
})
// App links
+ // setup eventlistener
+ setAppHideEvent();
+ function setAppHideEvent(){
+ $('.app_hide').off('change');
+ $('.app_hide').on('change', function (e) {
+ var value = $(this).is(':checked') ? '1' : '0';
+ console.log(value)
+ $(this).parent().children(':first-child').val(value);
+ })
+ }
function add_table_row(table_id, type) {
var row = $(' ');
if (type == "app_link") {
cols = ' ';
cols += ' ';
cols += ' ';
+ cols += '
';
cols += '' + lang.remove_row + ' ';
} else if (type == "f2b_regex") {
cols = ' ';
cols += ' ';
cols += '' + lang.remove_row + ' ';
}
+
row.append(cols);
table_id.append(row);
+ if (type == "app_link")
+ setAppHideEvent();
}
$('#app_link_table').on('click', 'tr a', function (e) {
e.preventDefault();
diff --git a/data/web/templates/admin/tab-config-customize.twig b/data/web/templates/admin/tab-config-customize.twig
index 4b8f53231..93da2bfdb 100644
--- a/data/web/templates/admin/tab-config-customize.twig
+++ b/data/web/templates/admin/tab-config-customize.twig
@@ -59,6 +59,7 @@
{{ lang.admin.app_name }}
{{ lang.admin.link }}
{{ lang.admin.user_link }}
+ {{ lang.admin.app_hide }}
{% for row in app_links %}
@@ -67,6 +68,12 @@
+
+
+
+
+
+
{{ lang.admin.remove_row }}
{% endfor %}
@@ -76,6 +83,11 @@
+
+
+
+
+
{{ lang.admin.remove_row }}
{% endfor %}
diff --git a/data/web/templates/index.twig b/data/web/templates/index.twig
index bd4f87818..420bd5318 100644
--- a/data/web/templates/index.twig
+++ b/data/web/templates/index.twig
@@ -67,19 +67,25 @@
{{ lang.login.delayed|format(login_delay) }}
{% endif %}
- {% if not oauth2_request and (mailcow_apps or app_links) %}
+ {% if not oauth2_request and (mailcow_apps or app_links) and not hide_mailcow_apps %}
{{ ui_texts.apps_name|raw }}
{% for app in mailcow_apps %}
- {% if not skip_sogo or not is_uri('SOGo', app.link) %}
-
{{ app.name }}
+ {% if not app.hide %}
+ {% if not skip_sogo or not is_uri('SOGo', app.link) %}
+
{% endif %}
+ {% endif %}
{% endfor %}
{% for row in app_links %}
{% for key, val in row %}
+ {% if not val.hide %}
+ {% endif %}
{% endfor %}
{% endfor %}
From 84ff6ff2c5b591bbbc693e22e739e51cff835cca Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 10 Mar 2023 15:53:59 +0100
Subject: [PATCH 036/755] [Web] fix user login history
---
data/web/inc/functions.inc.php | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index 3cff09b95..ee1aab236 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -960,12 +960,16 @@ function check_login($user, $pass, $app_passwd_data = false) {
);
return "pending";
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
+ unset($_SESSION['ldelay']);
// no authenticators found, login successfull
// Reactivate TFA if it was set to "deactivate TFA for next login"
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
$stmt->execute(array(':user' => $user));
-
- unset($_SESSION['ldelay']);
+ $_SESSION['return'][] = array(
+ 'type' => 'success',
+ 'log' => array(__FUNCTION__, $user, '*'),
+ 'msg' => array('logged_in_as', $user)
+ );
return "user";
}
} elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
From 56a9f1a4115194c63d37ee8c451c7e432a3291c5 Mon Sep 17 00:00:00 2001
From: FreddleSpl0it
Date: Fri, 10 Mar 2023 17:10:05 +0100
Subject: [PATCH 037/755] [Web] organize user landing
---
data/web/css/build/014-mailcow.css | 1 +
data/web/js/site/user.js | 30 +-
data/web/templates/domainadmin.twig | 141 +++++-----
data/web/templates/user.twig | 1 -
data/web/templates/user/Spamfilter.twig | 8 +-
data/web/templates/user/tab-user-auth.twig | 310 ++++++++++++---------
6 files changed, 271 insertions(+), 220 deletions(-)
diff --git a/data/web/css/build/014-mailcow.css b/data/web/css/build/014-mailcow.css
index 8c1d7c2af..d1d6ac45d 100644
--- a/data/web/css/build/014-mailcow.css
+++ b/data/web/css/build/014-mailcow.css
@@ -386,6 +386,7 @@ button[aria-expanded='true'] > .caret {
background-color: #f0f0f0;
}
.btn.btn-outline-secondary {
+ color: #000000 !important;
border-color: #cfcfcf !important;
}
.btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show {
diff --git a/data/web/js/site/user.js b/data/web/js/site/user.js
index 088321cd3..850570ef4 100644
--- a/data/web/js/site/user.js
+++ b/data/web/js/site/user.js
@@ -77,11 +77,11 @@ jQuery(function($){
acl_data = JSON.parse(acl);
$('.clear-last-logins').on('click', function () {if (confirm(lang.delete_ays)) {last_logins('reset');}})
- $(".login-history").on('click', function(e) {e.preventDefault(); last_logins('get', $(this).data('days'));$(this).addClass('active').siblings().removeClass('active');});
+ $(".login-history").on('click', function(e) {e.preventDefault(); last_logins('get', $(this).data('days'));$(this).parent().find('li a').removeClass('active');$(this).children(':first-child').addClass('active')});
function last_logins(action, days = 7) {
if (action == 'get') {
- $('.last-login').html(' ' + lang.waiting);
+ $('#spinner-last-login').removeClass('d-none');
$.ajax({
dataType: 'json',
url: '/api/v1/get/last-login/' + encodeURIComponent(mailcow_cc_username) + '/' + days,
@@ -90,26 +90,38 @@ jQuery(function($){
console.log('error reading last logins');
},
success: function (data) {
- $('.last-login').html();
+ $('.last-ui-login').html('');
+ $('.last-sasl-login').html('');
if (data.ui.time) {
- $('.last-login').html(' ' + lang.last_ui_login + ': ' + unix_time_format(data.ui.time));
+ $('.last-ui-login').html(' ' + lang.last_ui_login + ': ' + unix_time_format(data.ui.time));
} else {
- $('.last-login').text(lang.no_last_login);
+ $('.last-ui-login').text(lang.no_last_login);
}
if (data.sasl) {
- $('.last-login').append('');
}
+
+ $('#spinner-last-login').addClass('d-none');
}
})
} else if (action == 'reset') {
diff --git a/data/web/templates/domainadmin.twig b/data/web/templates/domainadmin.twig
index 070bf00cd..9cfd25599 100644
--- a/data/web/templates/domainadmin.twig
+++ b/data/web/templates/domainadmin.twig
@@ -1,80 +1,83 @@
{% extends 'base.twig' %}
{% block content %}
-{{ lang.user.user_settings }}
-
-
-
-
-
+
+
+
+
+
+
+
- {# TFA #}
-
-
{{ lang.tfa.tfa }}
-
-
{{ tfa_data.pretty }}
- {% include 'tfa_keys.twig' %}
-
-
-
-
-
{{ lang.tfa.set_tfa }}
-
-
- {{ lang.tfa.yubi_otp }}
- {{ lang.tfa.webauthn }}
- {{ lang.tfa.totp }}
- {{ lang.tfa.none }}
-
-
-
+ {# TFA #}
+
+
{{ lang.tfa.tfa }}
+
+
{{ tfa_data.pretty }}
+ {% include 'tfa_keys.twig' %}
+
+
+
+
+
{{ lang.tfa.set_tfa }}
+
+
+ {{ lang.tfa.yubi_otp }}
+ {{ lang.tfa.webauthn }}
+ {{ lang.tfa.totp }}
+ {{ lang.tfa.none }}
+
+
+
-
- {# FIDO2 #}
-
-
-
{{ lang.fido2.fido2_auth }}
-
-
-
-
{{ lang.fido2.known_ids }}:
-
-
-
-
- ID
- {{ lang.admin.action }}
-
- {% include 'fido2.twig' %}
-
-
-
-
-
-
-
-
-
{{ lang.fido2.set_fido2 }}
-
-
+
+ {# FIDO2 #}
+
+
+
{{ lang.fido2.fido2_auth }}
+
+
+
+
{{ lang.fido2.known_ids }}:
+
+
+
+
+ ID
+ {{ lang.admin.action }}
+
+ {% include 'fido2.twig' %}
+
+
+
-
-
-
-
{{ lang.fido2.register_status }}:
-
-
-
+
+
+
+ {{ lang.fido2.set_fido2 }}
+
+
+
+
+
+
+
+
{{ lang.fido2.register_status }}:
+
+
+
-
diff --git a/data/web/templates/user.twig b/data/web/templates/user.twig
index 5536abe4e..a79c5a2c5 100644
--- a/data/web/templates/user.twig
+++ b/data/web/templates/user.twig
@@ -43,7 +43,6 @@
-
{% include 'user_domainadmin_common.twig' %}
{% endblock %}
diff --git a/data/web/templates/user/Spamfilter.twig b/data/web/templates/user/Spamfilter.twig
index 280b90032..1f69df95f 100644
--- a/data/web/templates/user/Spamfilter.twig
+++ b/data/web/templates/user/Spamfilter.twig
@@ -39,10 +39,10 @@
-
+
{{ lang.user.spamfilter_wl }}
{{ lang.user.spamfilter_wl_desc|raw }}
-
-
+
{{ lang.user.spamfilter_bl }}
{{ lang.user.spamfilter_bl_desc|raw }}
-