@@ -68,45 +68,57 @@ done <<< "$v6"
6868
6969# ── Step 5: mirror the allowlist into DOCKER-USER ──────────────────────
7070# Docker bypasses UFW filter; DOCKER-USER is the documented hook.
71- # Marker-delimited block in after.rules so re-runs replace cleanly.
71+ # Rules are scoped to dst = Caddy container IPs so they only affect
72+ # inbound traffic, not outbound HTTPS from any container (which would
73+ # otherwise also match a naked `--dport 443 DROP`).
74+ # Caddy container IPs are pinned in docker-compose.prod.yml.
75+
76+ CADDY_IPV4=172.30.0.20
77+ CADDY_IPV6=" " # spoonet is v4-only today; left empty so v6 block no-ops
7278
7379BEGIN_MARKER=' # BEGIN cf-docker-user (managed by ufw-cloudflare.sh)'
7480END_MARKER=' # END cf-docker-user'
7581
7682write_docker_user_block () {
7783 local rules_file=" $1 "
7884 local ip_list=" $2 "
85+ local dst_ip=" $3 " # Caddy container IP for this family; "" skips
7986
8087 if grep -qF " $BEGIN_MARKER " " $rules_file " ; then
8188 echo " [ufw-cloudflare] removing prior managed block from $rules_file …"
8289 sed -i " /^$BEGIN_MARKER \$ /,/^$END_MARKER \$ /d" " $rules_file "
8390 fi
8491
92+ # Skip the file if no container IP for this family.
93+ if [[ -z " $dst_ip " ]]; then
94+ echo " [ufw-cloudflare] no container IP for $rules_file family; skipping"
95+ return
96+ fi
97+
8598 echo " [ufw-cloudflare] writing managed block to $rules_file …"
8699 {
87100 echo " "
88101 echo " $BEGIN_MARKER "
89102 echo " *filter"
90- # `:CHAIN - [0:0]` flushes existing rules so re-runs replace.
91103 echo " :DOCKER-USER - [0:0]"
92104 while IFS= read -r ip; do
93105 [[ -z " $ip " ]] && continue
94- echo " -A DOCKER-USER -p tcp -s $ip --dport 443 -j RETURN"
95- echo " -A DOCKER-USER -p udp -s $ip --dport 443 -j RETURN"
96- echo " -A DOCKER-USER -p tcp -s $ip --dport 80 -j RETURN"
106+ echo " -A DOCKER-USER -p tcp -s $ip -d $dst_ip - -dport 443 -j RETURN"
107+ echo " -A DOCKER-USER -p udp -s $ip -d $dst_ip - -dport 443 -j RETURN"
108+ echo " -A DOCKER-USER -p tcp -s $ip -d $dst_ip - -dport 80 -j RETURN"
97109 done <<< " $ip_list"
98- echo " -A DOCKER-USER -p tcp --dport 443 -j DROP"
99- echo " -A DOCKER-USER -p udp --dport 443 -j DROP"
100- echo " -A DOCKER-USER -p tcp --dport 80 -j DROP"
101- # Default Docker fall-through for traffic not on those ports .
110+ echo " -A DOCKER-USER -p tcp -d $dst_ip - -dport 443 -j DROP"
111+ echo " -A DOCKER-USER -p udp -d $dst_ip - -dport 443 -j DROP"
112+ echo " -A DOCKER-USER -p tcp -d $dst_ip - -dport 80 -j DROP"
113+ # Default Docker fall-through.
102114 echo " -A DOCKER-USER -j RETURN"
103115 echo " COMMIT"
104116 echo " $END_MARKER "
105117 } >> " $rules_file "
106118}
107119
108- write_docker_user_block /etc/ufw/after.rules " $v4 "
109- write_docker_user_block /etc/ufw/after6.rules " $v6 "
120+ write_docker_user_block /etc/ufw/after.rules " $v4 " " $CADDY_IPV4 "
121+ write_docker_user_block /etc/ufw/after6.rules " $v6 " " $CADDY_IPV6 "
110122
111123# ── Step 6: enable + reload ────────────────────────────────────────────
112124echo " [ufw-cloudflare] enabling UFW…"
0 commit comments