From f77c65411ded33a6815e63bb958e6e9b77b0c288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20L=C3=A9on?= Date: Mon, 27 Feb 2023 12:04:32 +0100 Subject: [PATCH 01/57] Fix SNAT never being added because of exception Some firewall rule object (iptc) do not have a parameter attribute, which results in an exception being triggered, and the mailcow SNAT rule to never be created. Firewall rules that trigger such exception are: - -A POSTROUTING -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN This commit just verify attribute presence, and skip the rule properly instead of triggering an exception. --- data/Dockerfiles/netfilter/server.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 0b0e2a41..b1a9f336 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -366,6 +366,8 @@ def snat4(snat_target): chain.insert_rule(new_rule) else: for position, rule in enumerate(chain.rules): + if not hasattr(rule.target, 'parameter'): + continue match = all(( new_rule.get_src() == rule.get_src(), new_rule.get_dst() == rule.get_dst(), From a5b8f1b7f75e135adc7739fc46d67d8298b72413 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 28 Feb 2023 20:08:33 +0100 Subject: [PATCH 02/57] Update to PHP 8.2 --- data/Dockerfiles/phpfpm/Dockerfile | 4 +++- docker-compose.yml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index c8713e04..ef50ab4b 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.1-fpm-alpine3.17 +FROM php:8.2-fpm-alpine3.17 LABEL maintainer "Andre Peters " # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced @@ -52,6 +52,7 @@ RUN apk add -U --no-cache autoconf \ libxpm-dev \ libzip \ libzip-dev \ + linux-headers \ make \ mysql-client \ openldap-dev \ @@ -99,6 +100,7 @@ RUN apk add -U --no-cache autoconf \ libxml2-dev \ libxpm-dev \ libzip-dev \ + linux-headers \ make \ openldap-dev \ pcre-dev \ diff --git a/docker-compose.yml b/docker-compose.yml index 7c6c5d6a..c9b03d4f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -106,7 +106,7 @@ services: - rspamd php-fpm-mailcow: - image: mailcow/phpfpm:1.82 + image: mailcow/phpfpm:1.83 command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" depends_on: - redis-mailcow From 0f59d4952be2c001100021080c9253dc9008b427 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Fri, 17 Mar 2023 19:13:49 +0100 Subject: [PATCH 03/57] Translations update from Weblate (#5131) * [Web] Updated lang.da-dk.json Co-authored-by: Victor Pahuus Petersen Co-authored-by: milkmaker * [Web] Updated lang.fr-fr.json Co-authored-by: UpSilot Co-authored-by: milkmaker --------- Co-authored-by: Victor Pahuus Petersen Co-authored-by: UpSilot --- data/web/lang/lang.da-dk.json | 2 +- data/web/lang/lang.fr-fr.json | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/data/web/lang/lang.da-dk.json b/data/web/lang/lang.da-dk.json index 61a553e6..5846181b 100644 --- a/data/web/lang/lang.da-dk.json +++ b/data/web/lang/lang.da-dk.json @@ -1048,7 +1048,7 @@ "spamfilter_table_empty": "Intet data at vise", "spamfilter_table_remove": "slet", "spamfilter_table_rule": "Regl", - "spamfilter_wl": "Hvisliste", + "spamfilter_wl": "Hvidliste", "spamfilter_wl_desc": "Hvidlistede e-mail-adresser til aldrig at klassificeres som spam. Wildcards kan bruges. Et filter anvendes kun på direkte aliaser (aliaser med en enkelt målpostkasse) eksklusive catch-aliaser og selve en postkasse.", "spamfilter_yellow": "Gul: denne besked kan være spam, vil blive tagget som spam og flyttes til din junk-mappe", "status": "Status", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index ef19d186..402e66f9 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -24,7 +24,7 @@ "spam_policy": "Liste Noire/Liste Blanche", "spam_score": "Score SPAM", "syncjobs": "Tâches de synchronisation", - "tls_policy": "Police TLS", + "tls_policy": "Politique TLS", "unlimited_quota": "Quota illimité pour les boites de courriel", "domain_desc": "Modifier la description du domaine", "domain_relayhost": "Changer le relais pour un domaine", @@ -106,7 +106,8 @@ "validate": "Valider", "validation_success": "Validation réussie", "bcc_dest_format": "La destination Cci doit être une seule adresse e-mail valide.
Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.", - "tags": "Etiquettes" + "tags": "Etiquettes", + "app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application" }, "admin": { "access": "Accès", @@ -585,7 +586,7 @@ "unchanged_if_empty": "Si non modifié, laisser en blanc", "username": "Nom d'utilisateur", "validate_save": "Valider et sauver", - "lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (.*google\\.com pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut).", + "lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (.*google\\.com pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut)", "mailbox_relayhost_info": "S'applique uniquement à la boîte aux lettres et aux alias directs, remplace le relayhost du domaine." }, "footer": { @@ -1088,9 +1089,12 @@ "username": "Nom d'utilisateur", "verify": "Vérification", "waiting": "En attente", - "week": "Semaine", + "week": "semaine", "weekly": "Hebdomadaire", - "weeks": "semaines" + "weeks": "semaines", + "months": "mois", + "year": "année", + "years": "années" }, "warning": { "cannot_delete_self": "Impossible de supprimer l’utilisateur connecté", From 6507b53bbb44c92b275fdb5649b95fc18ffaab91 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Mon, 20 Mar 2023 01:29:01 +0100 Subject: [PATCH 04/57] [web] fix mailbox badge height Signed-off-by: Kristian Feldsam --- data/web/css/site/mailbox.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/web/css/site/mailbox.css b/data/web/css/site/mailbox.css index f62ead31..e896abca 100644 --- a/data/web/css/site/mailbox.css +++ b/data/web/css/site/mailbox.css @@ -66,4 +66,6 @@ table tbody tr td input[type="checkbox"] { padding: .2em .4em .3em !important; background-color: #ececec!important; } - +.badge.bg-info .bi { + font-size: inherit; +} From e5e6418be869a373b4af152e3f5a051a0d616146 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Mon, 20 Mar 2023 01:30:06 +0100 Subject: [PATCH 05/57] [web] fixed tooltips in ajax loaded alias table Signed-off-by: Kristian Feldsam --- data/web/js/site/mailbox.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index f4039268..936ad488 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -1952,6 +1952,10 @@ jQuery(function($){ table.on('responsive-resize', function (e, datatable, columns){ hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table'); }); + + table.on( 'draw', function (){ + $('#alias_table [data-bs-toggle="tooltip"]').tooltip(); + }); } function draw_aliasdomain_table() { // just recalc width if instance already exists From e6ce5e88f748f61e2952176391da820db5d4d699 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Mon, 20 Mar 2023 10:57:40 +0100 Subject: [PATCH 06/57] [Generate.sh] Fixed broken pipe error message --- generate_config.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generate_config.sh b/generate_config.sh index 89af0f64..23e7036b 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -205,8 +205,8 @@ DBUSER=mailcow # Please use long, random alphanumeric strings (A-Za-z0-9) -DBPASS=$(LC_ALL=C /dev/null | head -c 28) +DBROOT=$(LC_ALL=C /dev/null | head -c 28) # ------------------------------ # HTTP/S Bindings From f6d135fbad5407b9dd8b7111fbc0ce20a964ae51 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Mon, 20 Mar 2023 12:05:11 +0100 Subject: [PATCH 07/57] [Update.sh] Fix docker compose detection + added failover --- update.sh | 77 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/update.sh b/update.sh index 34d17354..73ee975c 100755 --- a/update.sh +++ b/update.sh @@ -176,18 +176,19 @@ remove_obsolete_nginx_ports() { } detect_docker_compose_command(){ -if ! [ "${DOCKER_COMPOSE_VERSION}" == "native" ] && ! [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then +if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then if docker compose > /dev/null 2>&1; then if docker compose version --short | grep "2." > /dev/null 2>&1; then DOCKER_COMPOSE_VERSION=native COMPOSE_COMMAND="docker compose" echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m" echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf sleep 2 echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" exit 1 fi elif docker-compose > /dev/null 2>&1; then @@ -197,26 +198,60 @@ if ! [ "${DOCKER_COMPOSE_VERSION}" == "native" ] && ! [ "${DOCKER_COMPOSE_VERSIO COMPOSE_COMMAND="docker-compose" echo -e "\e[31mFound Docker Compose Standalone.\e[0m" echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf sleep 2 echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" exit 1 fi fi else echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" exit 1 fi elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then COMPOSE_COMMAND="docker compose" + # Check if Native Compose works and has not been deleted + if ! $COMPOSE_COMMAND > /dev/null 2>&1; then + # IF it not exists/work anymore try the other command + COMPOSE_COMMAND="docker-compose" + if ! $COMPOSE_COMMAND > /dev/null 2>&1 || ! $COMPOSE_COMMAND --version | grep "^2." > /dev/null 2>&1; then + # IF it cannot find Standalone in > 2.X, then script stops + echo -e "\e[31mCannot find Docker Compose or the Version is lower then 2.X.X.\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + exit 1 + fi + # If it finds the standalone Plugin it will use this instead and change the mailcow.conf Variable accordingly + echo -e "\e[31mFound different Docker Compose Version then declared in mailcow.conf!\e[0m" + echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable from native to standalone\e[0m" + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf + sleep 2 + fi + elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then COMPOSE_COMMAND="docker-compose" + # Check if Standalone Compose works and has not been deleted + if ! $COMPOSE_COMMAND > /dev/null 2>&1 && ! $COMPOSE_COMMAND --version > /dev/null 2>&1 | grep "^2." > /dev/null 2>&1; then + # IF it not exists/work anymore try the other command + COMPOSE_COMMAND="docker compose" + if ! $COMPOSE_COMMAND > /dev/null 2>&1; then + # IF it cannot find Native in > 2.X, then script stops + echo -e "\e[31mCannot find Docker Compose.\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + exit 1 + fi + # If it finds the native Plugin it will use this instead and change the mailcow.conf Variable accordingly + echo -e "\e[31mFound different Docker Compose Version then declared in mailcow.conf!\e[0m" + echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable from standalone to native\e[0m" + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf + sleep 2 + fi fi } @@ -326,8 +361,12 @@ while (($#)); do echo -e "\e[32mRunning in forced mode...\e[0m" FORCE=y ;; + -d|--dev) + echo -e "\e[32mRunning in Developer mode...\e[0m" + DEV=y + ;; --help|-h) - echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -h|--help] + echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -d|--dev, -h|--help] -c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates) --ours - Use merge strategy option "ours" to solve conflicts in favor of non-mailcow code (local changes over remote changes), not recommended! @@ -338,6 +377,7 @@ while (($#)); do --skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you´ve blocked any ICMP Connections to your mailcow machine) --stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly. -f|--force - Force update, do not ask questions + -d|--dev - Enables Developer Mode (No Checkout of update.sh for tests) ' exit 1 esac @@ -597,7 +637,7 @@ for option in ${CONFIG_ARRAY[@]}; do echo "Adding new option \"${option}\" to mailcow.conf" echo '# Password hash algorithm' >> mailcow.conf echo '# Only certain password hash algorithm are supported. For a fully list of supported schemes,' >> mailcow.conf - echo '# see https://mailcow.github.io/mailcow-dockerized-docs/models/model-passwd/' >> mailcow.conf + echo '# see https://docs.mailcow.email/models/model-passwd/' >> mailcow.conf echo "MAILCOW_PASS_SCHEME=BLF-CRYPT" >> mailcow.conf fi elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then @@ -617,7 +657,7 @@ for option in ${CONFIG_ARRAY[@]}; do echo '# Optional: Leave empty for none' >> mailcow.conf echo '# This value is only used on first order!' >> mailcow.conf echo '# Setting it at a later point will require the following steps:' >> mailcow.conf - echo '# https://mailcow.github.io/mailcow-dockerized-docs/troubleshooting/debug-reset_tls/' >> mailcow.conf + echo '# https://docs.mailcow.email/troubleshooting/debug-reset_tls/' >> mailcow.conf echo 'ACME_CONTACT=' >> mailcow.conf fi elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then @@ -727,15 +767,17 @@ elif [ $NEW_BRANCH == "nightly" ] && [ $CURRENT_BRANCH != "nightly" ]; then git checkout -f ${BRANCH} fi -echo -e "\e[32mChecking for newer update script...\e[0m" -SHA1_1=$(sha1sum update.sh) -git fetch origin #${BRANCH} -git checkout origin/${BRANCH} update.sh -SHA1_2=$(sha1sum update.sh) -if [[ ${SHA1_1} != ${SHA1_2} ]]; then - echo "update.sh changed, please run this script again, exiting." - chmod +x update.sh - exit 2 +if [ ! $DEV ]; then + echo -e "\e[32mChecking for newer update script...\e[0m" + SHA1_1=$(sha1sum update.sh) + git fetch origin #${BRANCH} + git checkout origin/${BRANCH} update.sh + SHA1_2=$(sha1sum update.sh) + if [[ ${SHA1_1} != ${SHA1_2} ]]; then + echo "update.sh changed, please run this script again, exiting." + chmod +x update.sh + exit 2 + fi fi if [ ! $FORCE ]; then @@ -902,9 +944,6 @@ else echo -e "\e[33mCannot determine current git repository version...\e[0m" fi -# Set DOCKER_COMPOSE_VERSION -sed -i 's/^DOCKER_COMPOSE_VERSION=$/DOCKER_COMPOSE_VERSION='$DOCKER_COMPOSE_VERSION'/g' mailcow.conf - if [[ ${SKIP_START} == "y" ]]; then echo -e "\e[33mNot starting mailcow, please run \"$COMPOSE_COMMAND up -d --remove-orphans\" to start mailcow.\e[0m" else From 0206e0886c70f242c8f8c92fe1b0f30006639f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B6rn=20J=C3=B6rger?= Date: Fri, 17 Mar 2023 01:33:40 +0100 Subject: [PATCH 08/57] implemented exponentially incrementing bantime, removed active_window code that did nothing, cleanly initialized dictionary --- data/Dockerfiles/netfilter/server.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 0b0e2a41..de4b1766 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -174,20 +174,15 @@ def ban(address): net = ipaddress.ip_network((address + (NETBAN_IPV4 if type(ip) is ipaddress.IPv4Address else NETBAN_IPV6)), strict=False) net = str(net) - if not net in bans or time.time() - bans[net]['last_attempt'] > RETRY_WINDOW: - bans[net] = { 'attempts': 0 } - active_window = RETRY_WINDOW - else: - active_window = time.time() - bans[net]['last_attempt'] + if not net in bans: + bans[net] = {'attempts': 0, 'last_attempt': 0, 'ban_counter': 0} bans[net]['attempts'] += 1 bans[net]['last_attempt'] = time.time() - active_window = time.time() - bans[net]['last_attempt'] - if bans[net]['attempts'] >= MAX_ATTEMPTS: cur_time = int(round(time.time())) - logCrit('Banning %s for %d minutes' % (net, BAN_TIME / 60)) + logCrit('Banning %s for %d minutes' % (net, BAN_TIME / 60 * 2 ** bans[net]['ban_counter'])) if type(ip) is ipaddress.IPv4Address: with lock: chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW') @@ -206,7 +201,7 @@ def ban(address): rule.target = target if rule not in chain.rules: chain.insert_rule(rule) - r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + BAN_TIME) + r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + BAN_TIME * 2 ** bans[net]['ban_counter']) else: logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)) @@ -238,7 +233,8 @@ def unban(net): r.hdel('F2B_ACTIVE_BANS', '%s' % net) r.hdel('F2B_QUEUE_UNBAN', '%s' % net) if net in bans: - del bans[net] + bans[net]['attempts'] = 0 + bans[net]['ban_counter'] += 1 def permBan(net, unban=False): global lock @@ -432,7 +428,7 @@ def autopurge(): unban(str(net)) for net in bans.copy(): if bans[net]['attempts'] >= MAX_ATTEMPTS: - if time.time() - bans[net]['last_attempt'] > BAN_TIME: + if time.time() - bans[net]['last_attempt'] > BAN_TIME * 2 ** bans[net]['ban_counter']: unban(net) def isIpNetwork(address): From 1233613bea73a22442eb000dd36376f59d7b1ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B6rn=20J=C3=B6rger?= Date: Fri, 17 Mar 2023 14:41:37 +0100 Subject: [PATCH 09/57] implemented handling of max_bantime and ban_time_increment flag --- data/Dockerfiles/netfilter/server.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index de4b1766..5533b4b3 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -67,11 +67,15 @@ def refreshF2boptions(): if not r.get('F2B_OPTIONS'): f2boptions = {} f2boptions['ban_time'] = int + f2boptions['max_ban_time'] = int + f2boptions['ban_time_increment'] = bool f2boptions['max_attempts'] = int f2boptions['retry_window'] = int f2boptions['netban_ipv4'] = int f2boptions['netban_ipv6'] = int f2boptions['ban_time'] = r.get('F2B_BAN_TIME') or 1800 + f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME') or 10000 + f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT') or True f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') or 10 f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') or 600 f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') or 32 @@ -147,6 +151,7 @@ def ban(address): global lock refreshF2boptions() BAN_TIME = int(f2boptions['ban_time']) + BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) MAX_ATTEMPTS = int(f2boptions['max_attempts']) RETRY_WINDOW = int(f2boptions['retry_window']) NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4']) @@ -182,7 +187,8 @@ def ban(address): if bans[net]['attempts'] >= MAX_ATTEMPTS: cur_time = int(round(time.time())) - logCrit('Banning %s for %d minutes' % (net, BAN_TIME / 60 * 2 ** bans[net]['ban_counter'])) + NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] + logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 )) if type(ip) is ipaddress.IPv4Address: with lock: chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW') @@ -201,7 +207,7 @@ def ban(address): rule.target = target if rule not in chain.rules: chain.insert_rule(rule) - r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + BAN_TIME * 2 ** bans[net]['ban_counter']) + r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + NET_BAN_TIME) else: logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)) @@ -421,6 +427,8 @@ def autopurge(): time.sleep(10) refreshF2boptions() BAN_TIME = int(f2boptions['ban_time']) + MAX_BAN_TIME = int(f2boptions['max_ban_time']) + BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) MAX_ATTEMPTS = int(f2boptions['max_attempts']) QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN') if QUEUE_UNBAN: @@ -428,7 +436,9 @@ def autopurge(): unban(str(net)) for net in bans.copy(): if bans[net]['attempts'] >= MAX_ATTEMPTS: - if time.time() - bans[net]['last_attempt'] > BAN_TIME * 2 ** bans[net]['ban_counter']: + NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] + TIME_SINCE_LAST_ATTEMPT = time.time() - bans[net]['last_attempt'] + if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME or TIME_SINCE_LAST_ATTEMPT > MAX_BAN_TIME: unban(net) def isIpNetwork(address): From c28a6b89f030caca6e208790f80751588d1868ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B6rn=20J=C3=B6rger?= Date: Fri, 17 Mar 2023 18:22:16 +0100 Subject: [PATCH 10/57] Added ban_time_increment and max_ban_time to UI --- data/web/api/openapi.yaml | 12 +++++++++++- data/web/inc/functions.fail2ban.inc.php | 4 ++++ data/web/lang/lang.de-de.json | 2 ++ data/web/lang/lang.en-gb.json | 2 ++ data/web/lang/lang.es-es.json | 2 ++ data/web/lang/lang.fr-fr.json | 4 +++- data/web/lang/lang.it-it.json | 2 ++ data/web/lang/lang.nl-nl.json | 2 ++ data/web/templates/admin/tab-config-f2b.twig | 8 ++++++++ 9 files changed, 36 insertions(+), 2 deletions(-) diff --git a/data/web/api/openapi.yaml b/data/web/api/openapi.yaml index 5e07c4b3..65bd1211 100644 --- a/data/web/api/openapi.yaml +++ b/data/web/api/openapi.yaml @@ -3176,8 +3176,10 @@ paths: example: attr: ban_time: "86400" + ban_time_increment: "1" blacklist: "10.100.6.5/32,10.100.8.4/32" max_attempts: "5" + max_ban_time: "86400" netban_ipv4: "24" netban_ipv6: "64" retry_window: "600" @@ -3191,11 +3193,17 @@ paths: description: the backlisted ips or hostnames separated by comma type: string ban_time: - description: the time a ip should be banned + description: the time an ip should be banned type: number + ban_time_increment: + description: if the time of the ban should increase each time + type: boolean max_attempts: description: the maximum numbe of wrong logins before a ip is banned type: number + max_ban_time: + description: the maximum time an ip should be banned + type: number netban_ipv4: description: the networks mask to ban for ipv4 type: number @@ -4113,10 +4121,12 @@ paths: response: value: ban_time: 604800 + ban_time_increment: 1 blacklist: |- 45.82.153.37/32 92.118.38.52/32 max_attempts: 1 + max_ban_time: 604800 netban_ipv4: 32 netban_ipv6: 128 perm_bans: diff --git a/data/web/inc/functions.fail2ban.inc.php b/data/web/inc/functions.fail2ban.inc.php index 2a7f11e8..2c4aa41d 100644 --- a/data/web/inc/functions.fail2ban.inc.php +++ b/data/web/inc/functions.fail2ban.inc.php @@ -239,7 +239,9 @@ function fail2ban($_action, $_data = null) { $is_now = fail2ban('get'); if (!empty($is_now)) { $ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']); + $ban_time_increment = (isset($_data['ban_time_increment']) && $_data['ban_time_increment'] == "1") ? 1 : 0; $max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['max_attempts']); + $max_ban_time = intval((isset($_data['max_ban_time'])) ? $_data['max_ban_time'] : $is_now['max_ban_time']); $retry_window = intval((isset($_data['retry_window'])) ? $_data['retry_window'] : $is_now['retry_window']); $netban_ipv4 = intval((isset($_data['netban_ipv4'])) ? $_data['netban_ipv4'] : $is_now['netban_ipv4']); $netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']); @@ -256,6 +258,8 @@ function fail2ban($_action, $_data = null) { } $f2b_options = array(); $f2b_options['ban_time'] = ($ban_time < 60) ? 60 : $ban_time; + $f2b_options['ban_time_increment'] = ($ban_time_increment == 1) ? true : false; + $f2b_options['max_ban_time'] = ($max_ban_time < 60) ? 60 : $max_ban_time; $f2b_options['netban_ipv4'] = ($netban_ipv4 < 8) ? 8 : $netban_ipv4; $f2b_options['netban_ipv6'] = ($netban_ipv6 < 8) ? 8 : $netban_ipv6; $f2b_options['netban_ipv4'] = ($netban_ipv4 > 32) ? 32 : $netban_ipv4; diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 8ff1cf06..4bd4b3fa 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -175,10 +175,12 @@ "empty": "Keine Einträge vorhanden", "excludes": "Diese Empfänger ausschließen", "f2b_ban_time": "Bannzeit in Sekunden", + "f2b_ban_time_increment": "Bannzeit erhöht sich mit jedem Bann", "f2b_blacklist": "Blacklist für Netzwerke und Hosts", "f2b_filter": "Regex-Filter", "f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. Die Aktualisierung der Liste dauert einige Sekunden.", "f2b_max_attempts": "Max. Versuche", + "f2b_max_ban_time": "Maximale Bannzeit in Sekunden", "f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)", "f2b_netban_ipv6": "Netzbereich für IPv6-Banns (8-128)", "f2b_parameters": "Fail2ban-Parameter", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index bfac011e..df83987c 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -177,10 +177,12 @@ "empty": "No results", "excludes": "Excludes these recipients", "f2b_ban_time": "Ban time (s)", + "f2b_ban_time_increment": "Ban time is incremented with each ban", "f2b_blacklist": "Blacklisted networks/hosts", "f2b_filter": "Regex filters", "f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. List updates will take a few seconds to be applied.", "f2b_max_attempts": "Max. attempts", + "f2b_max_ban_time": "Max. ban time (s)", "f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)", "f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)", "f2b_parameters": "Fail2ban parameters", diff --git a/data/web/lang/lang.es-es.json b/data/web/lang/lang.es-es.json index d9c3bfd3..e56e6bdd 100644 --- a/data/web/lang/lang.es-es.json +++ b/data/web/lang/lang.es-es.json @@ -141,9 +141,11 @@ "empty": "Sin resultados", "excludes": "Excluye a estos destinatarios", "f2b_ban_time": "Tiempo de restricción (s)", + "f2b_ban_time_increment": "Tiempo de restricción se incrementa con cada restricción", "f2b_blacklist": "Redes y hosts en lista negra", "f2b_list_info": "Un host o red en lista negra siempre superará a una entidad de la lista blanca. Las actualizaciones de la lista tardarán unos segundos en aplicarse.", "f2b_max_attempts": "Max num. de intentos", + "f2b_max_ban_time": "Max tiempo de restricción (s)", "f2b_netban_ipv4": "Tamaño de subred IPv4 para aplicar la restricción (8-32)", "f2b_netban_ipv6": "Tamaño de subred IPv6 para aplicar la restricción (8-128)", "f2b_parameters": "Parametros Fail2ban", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 402e66f9..d64f62f7 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -172,11 +172,13 @@ "edit": "Editer", "empty": "Aucun résultat", "excludes": "Exclure ces destinataires", - "f2b_ban_time": "Durée du bannissement(s)", + "f2b_ban_time": "Durée du bannissement (s)", + "f2b_ban_time_increment": "Durée du bannissement est augmentée à chaque bannissement", "f2b_blacklist": "Réseaux/Domaines sur Liste Noire", "f2b_filter": "Filtre(s) Regex", "f2b_list_info": "Un hôte ou un réseau sur liste noire l'emportera toujours sur une entité de liste blanche. L'application des mises à jour de liste prendra quelques secondes.", "f2b_max_attempts": "Nb max. de tentatives", + "f2b_max_ban_time": "Max. durée du bannissement (s)", "f2b_netban_ipv4": "Taille du sous-réseau IPv4 pour l'application du bannissement (8-32)", "f2b_netban_ipv6": "Taille du sous-réseau IPv6 pour l'application du bannissement (8-128)", "f2b_parameters": "Paramètres Fail2ban", diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index d8d6978c..4d21547c 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -175,10 +175,12 @@ "empty": "Nessun risultato", "excludes": "Esclude questi destinatari", "f2b_ban_time": "Tempo di blocco (s)", + "f2b_ban_time_increment": "Tempo di blocco aumenta ad ogni blocco", "f2b_blacklist": "Host/reti in blacklist", "f2b_filter": "Filtri Regex", "f2b_list_info": "Un host oppure una rete in blacklist, avrà sempre un peso maggiore rispetto ad una in whitelist. L'aggiornamento della lista richiede alcuni secondi per la sua entrata in azione.", "f2b_max_attempts": "Tentativi massimi", + "f2b_max_ban_time": "Tempo massimo di blocco (s)", "f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)", "f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)", "f2b_parameters": "Parametri Fail2ban", diff --git a/data/web/lang/lang.nl-nl.json b/data/web/lang/lang.nl-nl.json index 774627ca..4c2ea0b1 100644 --- a/data/web/lang/lang.nl-nl.json +++ b/data/web/lang/lang.nl-nl.json @@ -168,10 +168,12 @@ "empty": "Geen resultaten", "excludes": "Exclusief", "f2b_ban_time": "Verbanningstijd (s)", + "f2b_ban_time_increment": "Verbanningstijd wordt verhoogd met elk verbanning", "f2b_blacklist": "Netwerken/hosts op de blacklist", "f2b_filter": "Regex-filters", "f2b_list_info": "Een host of netwerk op de blacklist staat altijd boven eenzelfde op de whitelist. Het doorvoeren van wijzigingen kan enkele seconden in beslag nemen.", "f2b_max_attempts": "Maximaal aantal pogingen", + "f2b_max_ban_time": "Maximaal verbanningstijd (s)", "f2b_netban_ipv4": "Voer de IPv4-subnetgrootte in waar de verbanning van kracht moet zijn (8-32)", "f2b_netban_ipv6": "Voer de IPv6-subnetgrootte in waar de verbanning van kracht moet zijn (8-128)", "f2b_parameters": "Fail2ban", diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index bbd3e367..c15fb72f 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -12,6 +12,14 @@ +
+ + +
+
+ + +
From 5bc3d93545f9f0d24773477022cf8fa0315983d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B6rn=20J=C3=B6rger?= Date: Tue, 21 Mar 2023 11:12:07 +0100 Subject: [PATCH 11/57] log exception of redis pubsub subscription --- data/Dockerfiles/netfilter/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 0b0e2a41..4b6b3820 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -332,7 +332,7 @@ def watch(): logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data'])) ban(addr) except Exception as ex: - logWarn('Error reading log line from pubsub') + logWarn('Error reading log line from pubsub: %s' % ex) quit_now = True exit_code = 2 From 9fd4aa93e9136f88a68f97f7ed6d55265f4c9450 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 10:32:21 +0000 Subject: [PATCH 12/57] Update mailcow/rspamd Docker tag to v1.93 Signed-off-by: milkmaker --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index ad3053ae..d40933f8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -76,7 +76,7 @@ services: - clamd rspamd-mailcow: - image: mailcow/rspamd:1.92 + image: mailcow/rspamd:1.93 stop_grace_period: 30s depends_on: - dovecot-mailcow From 62f3603588ce9484d8e9faf30884c3e083b49829 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Mar 2023 15:00:55 +0100 Subject: [PATCH 13/57] Update actions/stale action to v8 (#5143) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/close_old_issues_and_prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/close_old_issues_and_prs.yml b/.github/workflows/close_old_issues_and_prs.yml index 64002617..21ab3a8e 100644 --- a/.github/workflows/close_old_issues_and_prs.yml +++ b/.github/workflows/close_old_issues_and_prs.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Mark/Close Stale Issues and Pull Requests 🗑️ - uses: actions/stale@v7.0.0 + uses: actions/stale@v8.0.0 with: repo-token: ${{ secrets.STALE_ACTION_PAT }} days-before-stale: 60 From cf3dc584d0390e05fe449306e516f941e8d8cbcc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Mar 2023 14:18:29 +0000 Subject: [PATCH 14/57] Update dependency nextcloud/server to v25.0.5 Signed-off-by: milkmaker --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 9377ddbb..262be218 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=25.0.4 +NEXTCLOUD_VERSION=25.0.5 echo -ne "Checking prerequisites..." sleep 1 From e808e595eb4864c5beed87b3519195f1be1ad7e4 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 24 Mar 2023 16:05:35 +0100 Subject: [PATCH 15/57] Update dependency composer/composer to v2.5.5 --- data/Dockerfiles/phpfpm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index ef50ab4b..937eec6c 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -12,7 +12,7 @@ ARG MEMCACHED_PECL_VERSION=3.2.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced ARG REDIS_PECL_VERSION=5.3.7 # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced -ARG COMPOSER_VERSION=2.5.4 +ARG COMPOSER_VERSION=2.5.5 RUN apk add -U --no-cache autoconf \ aspell-dev \ From db2fb12837d95660680fc9eb5e84b22991abd161 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 24 Mar 2023 16:08:19 +0100 Subject: [PATCH 16/57] Install sysvsem for Nextcloud 26 --- data/Dockerfiles/phpfpm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 937eec6c..0ff47206 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -76,7 +76,7 @@ RUN apk add -U --no-cache autoconf \ --with-webp \ --with-xpm \ --with-avif \ - && docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \ + && docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets sysvsem zip bcmath gmp \ && docker-php-ext-configure imap --with-imap --with-imap-ssl \ && docker-php-ext-install -j 4 imap \ && curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER_VERSION} \ From 22cd12f37b28e2906839b9b6a596c28944e6d902 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 Mar 2023 18:48:22 +0000 Subject: [PATCH 17/57] Update dependency nextcloud/server to v26 Signed-off-by: milkmaker --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 262be218..03913b64 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=25.0.5 +NEXTCLOUD_VERSION=26.0.0 echo -ne "Checking prerequisites..." sleep 1 From 4021613059694356d1a5659c3ba0dc6759b35881 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Tue, 28 Mar 2023 10:59:08 +0200 Subject: [PATCH 18/57] delete vmail_index when mbox is deleted --- data/Dockerfiles/dockerapi/dockerapi.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/dockerapi/dockerapi.py b/data/Dockerfiles/dockerapi/dockerapi.py index 9e699c22..6d3b1012 100644 --- a/data/Dockerfiles/dockerapi/dockerapi.py +++ b/data/Dockerfiles/dockerapi/dockerapi.py @@ -380,7 +380,12 @@ class DockerUtils: if 'maildir' in request_json: for container in self.docker_client.containers.list(filters={"id": container_id}): sane_name = re.sub(r'\W+', '', request_json['maildir']) - cmd = ["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"] + vmail_name = request_json['maildir'].replace("'", "'\\''") + index_name = request_json['maildir'].split("/") + index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''") + cmd_vmail = "if [[ -d '/var/vmail/" + vmail_name + "' ]]; then /bin/mv '/var/vmail/" + vmail_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi" + cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi" + cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index] maildir_cleanup = container.exec_run(cmd, user='vmail') return exec_run_handler('generic', maildir_cleanup) # api call: container_post - post_action: exec - cmd: rspamd - task: worker_password From 26c34b484a87e3690451567ab97cf096f4c8f4fd Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Tue, 28 Mar 2023 11:01:14 +0200 Subject: [PATCH 19/57] increase dockerapi image --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b8b9a0d1..493b8877 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -510,7 +510,7 @@ services: - watchdog dockerapi-mailcow: - image: mailcow/dockerapi:2.01 + image: mailcow/dockerapi:2.02 security_opt: - label=disable restart: always From 67955779b03ee807a9cd3463159c774e7c89c4db Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 28 Mar 2023 11:17:59 +0200 Subject: [PATCH 20/57] Fix broken pipe error in reset-admin.sh --- helper-scripts/mailcow-reset-admin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/mailcow-reset-admin.sh b/helper-scripts/mailcow-reset-admin.sh index ee95d3e9..ea8a4a43 100755 --- a/helper-scripts/mailcow-reset-admin.sh +++ b/helper-scripts/mailcow-reset-admin.sh @@ -19,7 +19,7 @@ read -r -p "Are you sure you want to reset the mailcow administrator account? [y response=${response,,} # tolower if [[ "$response" =~ ^(yes|y)$ ]]; then echo -e "\nWorking, please wait..." - random=$( /dev/null | head -c${1:-16}) password=$(docker exec -it $(docker ps -qf name=dovecot-mailcow) doveadm pw -s SSHA256 -p ${random} | tr -d '\r') docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin WHERE username='admin';" docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';" From 4cd5f93cdfbced2627d3445775965a322599fb9b Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 28 Mar 2023 11:22:49 +0200 Subject: [PATCH 21/57] Fixed broken pipe errors in nextcloud.sh --- helper-scripts/nextcloud.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 03913b64..71c9a73f 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -122,7 +122,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then && chmod +x ./data/web/nextcloud/occ echo -e "\033[33mCreating 'nextcloud' database...\033[0m" - NC_DBPASS=$( /dev/null | head -c 28) NC_DBUSER=nextcloud NC_DBNAME=nextcloud @@ -138,7 +138,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then echo "" echo -e "\033[33mInstalling Nextcloud...\033[0m" - ADMIN_NC_PASS=$( /dev/null | head -c 28) echo -ne "[1/4] Setting correct permissions for www-data" docker exec -it $(docker ps -f name=php-fpm-mailcow -q) /bin/bash -c "chown -R www-data:www-data /web/nextcloud" From 4336a99c6a3dbdb94195915f5949949dd8450f86 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 28 Mar 2023 11:40:00 +0200 Subject: [PATCH 22/57] [Nextcloud] Changed default X-Robots Tag behavior --- data/assets/nextcloud/nextcloud.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/assets/nextcloud/nextcloud.conf b/data/assets/nextcloud/nextcloud.conf index 3755c4a7..eda2c779 100644 --- a/data/assets/nextcloud/nextcloud.conf +++ b/data/assets/nextcloud/nextcloud.conf @@ -24,7 +24,7 @@ server { add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; - add_header X-Robots-Tag "none" always; + add_header X-Robots-Tag "noindex, nofollow" always; add_header X-XSS-Protection "1; mode=block" always; fastcgi_hide_header X-Powered-By; From e010f0814321cafe65be6c0e932df2fb99a2dd68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B6rn=20J=C3=B6rger?= Date: Wed, 29 Mar 2023 15:18:11 +0200 Subject: [PATCH 23/57] verify options after loading them, set defaults if options are missing or invalid --- data/Dockerfiles/netfilter/server.py | 35 +++++++++++++++++----------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 5533b4b3..2bf8b2b4 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -66,30 +66,37 @@ def refreshF2boptions(): global exit_code if not r.get('F2B_OPTIONS'): f2boptions = {} - f2boptions['ban_time'] = int - f2boptions['max_ban_time'] = int - f2boptions['ban_time_increment'] = bool - f2boptions['max_attempts'] = int - f2boptions['retry_window'] = int - f2boptions['netban_ipv4'] = int - f2boptions['netban_ipv6'] = int - f2boptions['ban_time'] = r.get('F2B_BAN_TIME') or 1800 - f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME') or 10000 - f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT') or True - f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') or 10 - f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') or 600 - f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') or 32 - f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') or 128 + f2boptions['ban_time'] = r.get('F2B_BAN_TIME') + f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME') + f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT') + f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') + f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') + f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') + f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') + verifyF2boptions(f2boptions) r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False)) else: try: f2boptions = {} f2boptions = json.loads(r.get('F2B_OPTIONS')) + verifyF2boptions(f2boptions) except ValueError: print('Error loading F2B options: F2B_OPTIONS is not json') quit_now = True exit_code = 2 +def verifyF2boptions(f2boptions): + verifyF2boption(f2boptions,'ban_time', 1800) + verifyF2boption(f2boptions,'max_ban_time', 10000) + verifyF2boption(f2boptions,'ban_time_increment', True) + verifyF2boption(f2boptions,'max_attempts', 10) + verifyF2boption(f2boptions,'retry_window', 600) + verifyF2boption(f2boptions,'netban_ipv4', 32) + verifyF2boption(f2boptions,'netban_ipv6', 128) + +def verifyF2boption(f2boptions, f2boption, f2bdefault): + f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault + def refreshF2bregex(): global f2bregex global quit_now From 096e2a41e96c981bccf4629d0df4803d5f756481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B6rn=20J=C3=B6rger?= Date: Wed, 29 Mar 2023 17:09:25 +0200 Subject: [PATCH 24/57] Push verified options to redis after each check --- data/Dockerfiles/netfilter/server.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data/Dockerfiles/netfilter/server.py b/data/Dockerfiles/netfilter/server.py index 2bf8b2b4..d0c652e2 100644 --- a/data/Dockerfiles/netfilter/server.py +++ b/data/Dockerfiles/netfilter/server.py @@ -64,8 +64,10 @@ def refreshF2boptions(): global f2boptions global quit_now global exit_code + + f2boptions = {} + if not r.get('F2B_OPTIONS'): - f2boptions = {} f2boptions['ban_time'] = r.get('F2B_BAN_TIME') f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME') f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT') @@ -73,18 +75,17 @@ def refreshF2boptions(): f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') - verifyF2boptions(f2boptions) - r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False)) else: try: - f2boptions = {} f2boptions = json.loads(r.get('F2B_OPTIONS')) - verifyF2boptions(f2boptions) except ValueError: print('Error loading F2B options: F2B_OPTIONS is not json') quit_now = True exit_code = 2 + verifyF2boptions(f2boptions) + r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False)) + def verifyF2boptions(f2boptions): verifyF2boption(f2boptions,'ban_time', 1800) verifyF2boption(f2boptions,'max_ban_time', 10000) From 400939faf676af0c08940402d62339f173d1f17c Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 30 Mar 2023 08:44:38 +0200 Subject: [PATCH 25/57] [Netfilter] Update to 1.52 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index db9c0241..63341865 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -425,7 +425,7 @@ services: - acme netfilter-mailcow: - image: mailcow/netfilter:1.51 + image: mailcow/netfilter:1.52 stop_grace_period: 30s depends_on: - dovecot-mailcow From f53ca24bb08ecd11188b4943d774816859aab0cc Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 30 Mar 2023 16:00:21 +0200 Subject: [PATCH 26/57] [SOGo] Update to 5.8.2 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 63341865..a2d40cd8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -169,7 +169,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.115 + image: mailcow/sogo:1.116 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} From 80dacc015a0e9a4b7d9e5a079ce0796d6de7c059 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Mon, 20 Mar 2023 01:37:49 +0100 Subject: [PATCH 27/57] [web] fixed mailbox/user settings buttons styling Signed-off-by: Kristian Feldsam [web] fixed mailbox/user settings buttons styling Signed-off-by: Kristian Feldsam --- data/web/css/themes/mailcow-darkmode.css | 17 ++++++++----- data/web/templates/edit/mailbox.twig | 18 +++++++------- .../web/templates/user/tab-user-settings.twig | 24 +++++++++---------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/data/web/css/themes/mailcow-darkmode.css b/data/web/css/themes/mailcow-darkmode.css index 6e0db0e9..abaa7499 100644 --- a/data/web/css/themes/mailcow-darkmode.css +++ b/data/web/css/themes/mailcow-darkmode.css @@ -20,6 +20,11 @@ legend { background-color: #7a7a7a !important; border-color: #5c5c5c !important; } +.btn-dark { + color: #000 !important;; + background-color: #f6f6f6 !important;; + border-color: #ddd !important;; +} .btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle { border-color: #7a7a7a !important; } @@ -299,22 +304,22 @@ a:hover { } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { background-color: #7a7a7a !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before { background-color: #7a7a7a !important; border: 1.5px solid #5c5c5c !important; color: #fff !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before { background-color: #949494; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { background-color: #444444; } @@ -327,7 +332,7 @@ table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { } .btn.btn-outline-secondary { color: #fff !important; - border-color: #7a7a7a !important; + border-color: #7a7a7a !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 { background-color: #9b9b9b !important; diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index 36fe053b..f8cde7da 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -109,25 +109,25 @@
- - - - - - -
- - -
- -
- - - -
- - -