Explorar o código

ipv6: added ipv6 detection + removed ip6 nat container

DerLinkman hai 3 meses
pai
achega
3f9215678d
Modificáronse 2 ficheiros con 106 adicións e 31 borrados
  1. 2 31
      docker-compose.yml
  2. 104 0
      generate_config.sh

+ 2 - 31
docker-compose.yml

@@ -405,7 +405,7 @@ services:
         - TZ=${TZ}
         - SKIP_SOGO=${SKIP_SOGO:-n}
         - SKIP_RSPAMD=${SKIP_RSPAMD:-n}
-        - DISABLE_IPv6=${DISABLE_IPv6:-n}
+        - ENABLE_IPV6=${ENABLE_IPV6:-true}
         - HTTP_REDIRECT=${HTTP_REDIRECT:-n}
         - PHPFPMHOST=${PHPFPMHOST:-}
         - SOGOHOST=${SOGOHOST:-}
@@ -629,41 +629,12 @@ services:
           aliases:
             - ofelia
 
-    ipv6nat-mailcow:
-      depends_on:
-        - unbound-mailcow
-        - mysql-mailcow
-        - redis-mailcow
-        - clamd-mailcow
-        - rspamd-mailcow
-        - php-fpm-mailcow
-        - sogo-mailcow
-        - dovecot-mailcow
-        - postfix-mailcow
-        - memcached-mailcow
-        - nginx-mailcow
-        - acme-mailcow
-        - netfilter-mailcow
-        - watchdog-mailcow
-        - dockerapi-mailcow
-      environment:
-        - TZ=${TZ}
-      image: robbertkl/ipv6nat
-      security_opt:
-        - label=disable
-      restart: always
-      privileged: true
-      network_mode: "host"
-      volumes:
-        - /var/run/docker.sock:/var/run/docker.sock:ro
-        - /lib/modules:/lib/modules:ro
-
 networks:
   mailcow-network:
     driver: bridge
     driver_opts:
       com.docker.network.bridge.name: br-mailcow
-    enable_ipv6: true
+    enable_ipv6: ${ENABLE_IPV6:-true}
     ipam:
       driver: default
       config:

+ 104 - 0
generate_config.sh

@@ -217,6 +217,104 @@ if [ ! -z "${MAILCOW_BRANCH}" ]; then
   git_branch=${MAILCOW_BRANCH}
 fi
 
+# Check IPv6 support on the host
+if grep -qs '^1' /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null \
+  || ! ip -6 route show default &>/dev/null; then
+  ENABLE_IPV6_LINE="ENABLE_IPV6=false"
+  echo "IPv6 not detected on host — disabling IPv6 support."
+else
+  ENABLE_IPV6_LINE="ENABLE_IPV6=true"
+  echo "IPv6 detected on host — leaving IPv6 support enabled."
+fi
+
+# Check Docker daemon IPv6 settings
+# We require in /etc/docker/daemon.json:
+#   "ipv6": true
+#   "fixed-cidr-v6": "fd00:dead:beef:c0::/80"
+# For Docker < 27:
+#   "ip6tables": true
+#   "experimental": true
+DOCKER_DAEMON_CONFIG="/etc/docker/daemon.json"
+MISSING=()
+
+_has_kv() {
+  grep -Eq "\"$1\"\s*:\s*$2" "$DOCKER_DAEMON_CONFIG" 2>/dev/null
+}
+
+if [[ -f "$DOCKER_DAEMON_CONFIG" ]]; then
+  # ---- JSON validation ----
+  if command -v jq &>/dev/null; then
+    if ! jq empty "$DOCKER_DAEMON_CONFIG" 2>/dev/null; then
+      echo "ERROR: $DOCKER_DAEMON_CONFIG contains invalid JSON."
+      echo "Please fix the syntax (e.g. missing commas/braces) and rerun this script."
+      exit 1
+    fi
+  else
+    echo "WARNING: jq not found — cannot validate JSON syntax. Continuing anyway."
+  fi
+
+  # require "ipv6": true
+  if ! _has_kv ipv6 true; then
+    MISSING+=("ipv6: true")
+  fi
+
+  # require "fixed-cidr-v6": "fd00:dead:beef:c0::/80"
+  if ! grep -Eq '"fixed-cidr-v6"\s*:\s*".+"' "$DOCKER_DAEMON_CONFIG"; then
+    MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"')
+  fi
+
+  # determine Docker major version
+  DOCKER_MAJOR=$(docker version --format '{{.Server.Version}}' 2>/dev/null | cut -d. -f1)
+
+  if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
+    # for Docker < 27, also require ip6tables and experimental
+    if _has_kv ipv6 true && ! _has_kv ip6tables true; then
+      MISSING+=("ip6tables: true")
+    fi
+    if ! _has_kv experimental true; then
+      MISSING+=("experimental: true")
+    fi
+  else
+    echo "Docker >= 27 detected — no ip6tables/experimental flags required."
+  fi
+
+  if (( ${#MISSING[@]} > 0 )); then
+    echo "Your Docker daemon.json is missing: ${MISSING[*]}"
+    read -p "Would you like to update $DOCKER_DAEMON_CONFIG now? [Y/n] " answer
+    answer=${answer:-Y}
+    if [[ $answer =~ ^[Yy]$ ]]; then
+      cp "$DOCKER_DAEMON_CONFIG" "${DOCKER_DAEMON_CONFIG}.bak"
+      echo "Backed up original to ${DOCKER_DAEMON_CONFIG}.bak"
+      if command -v jq &>/dev/null; then
+        TMP=$(mktemp)
+        # build jq filter
+        JQ_FILTER='.ipv6 = true | .["fixed-cidr-v6"] = "fd00:dead:beef:c0::/80"'
+        if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
+          JQ_FILTER+=' | .ip6tables = true | .experimental = true'
+        fi
+        jq "$JQ_FILTER" "$DOCKER_DAEMON_CONFIG" > "$TMP" && mv "$TMP" "$DOCKER_DAEMON_CONFIG"
+        echo "Updated $DOCKER_DAEMON_CONFIG."
+        echo "Restarting Docker daemon..."
+        if command -v systemctl &>/dev/null; then
+          systemctl restart docker
+        else
+          service docker restart
+        fi
+        echo "Docker restarted. Please rerun this script."
+        exit 1
+      else
+        echo "Please install jq or edit $DOCKER_DAEMON_CONFIG manually (add ipv6:true, fixed-cidr-v6:\"fd00:dead:beef:c0::/80\", plus ip6tables/experimental if Docker<27), then restart Docker and rerun this script."
+        exit 1
+      fi
+    else
+      ENABLE_IPV6_LINE="ENABLE_IPV6=false"
+      echo "User declined Docker config update — disabling IPv6 support."
+    fi
+  fi
+else
+  echo "Warning: $DOCKER_DAEMON_CONFIG not found — cannot verify Docker IPv6 settings."
+fi
+
 [ ! -f ./data/conf/rspamd/override.d/worker-controller-password.inc ] && echo '# Placeholder' > ./data/conf/rspamd/override.d/worker-controller-password.inc
 
 cat << EOF > mailcow.conf
@@ -510,6 +608,12 @@ WEBAUTHN_ONLY_TRUSTED_VENDORS=n
 # Otherwise it will work normally.
 SPAMHAUS_DQS_KEY=
 
+# IPv6 Controller Section
+# This variable controls the usage of IPv6 within mailcow.
+# Defaults to true
+# WARNING: MAKE SURE TO PROPERLY CONFIGURE IPv6 ON YOUR HOST FIRST BEFORE ENABLING THIS AS FAULTY CONFIGURATIONS CAN LEAD TO OPEN RELAYS!
+$ENABLE_IPV6_LINE
+
 # 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