From 0ef0d9676ea4f0dc04797f527fb835abce6d46c0 Mon Sep 17 00:00:00 2001 From: river0525 <0525sotaro@gmail.com> Date: Mon, 2 Nov 2026 09:00:02 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix:=E3=83=95=E3=82=A1=E3=82=A4=E3=82=A2?= =?UTF-8?q?=E3=82=A6=E3=82=A9=E3=83=BC=E3=83=AB=E3=81=8C=E4=B8=8A=E6=B5=81?= =?UTF-8?q?=20DNS=20=E3=81=B8=E3=81=AE=E5=95=8F=E3=81=84=E5=90=88=E3=82=8F?= =?UTF-8?q?=E3=81=9B=E3=82=92=E9=81=AE=E6=96=AD=E3=81=99=E3=82=8B=E5=95=8F?= =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .devcontainer/init-firewall.sh | 49 +++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/.devcontainer/init-firewall.sh b/.devcontainer/init-firewall.sh index a90a93663..283e200a1 100644 --- a/.devcontainer/init-firewall.sh +++ b/.devcontainer/init-firewall.sh @@ -111,6 +111,43 @@ if ! db_addresses="$(getent ahostsv4 db | awk '$2 == "STREAM" { print $1 }' | so exit 1 fi + +# Obtain Docker's upstream DNS servers before applying firewall rules. +# Docker records them in the ExtServers comment in /etc/resolv.conf. +upstream_dns_line="$( + sed -n 's/^# ExtServers: \[\(.*\)\]$/\1/p' /etc/resolv.conf +)" + +if [[ -z "${upstream_dns_line}" ]]; then + echo 'Failed to obtain Docker upstream DNS servers' >&2 + exit 1 +fi + +IFS=',' read -r -a upstream_dns_servers <<< "${upstream_dns_line}" + +# Validate upstream DNS addresses before changing firewall policies. +for i in "${!upstream_dns_servers[@]}"; do + dns="${upstream_dns_servers[$i]}" + dns="${dns//[[:space:]]/}" + + if [[ ! "${dns}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then + echo "Unsupported upstream DNS address: ${dns}" >&2 + exit 1 + fi + + IFS='.' read -r -a octets <<< "${dns}" + for octet in "${octets[@]}"; do + if (( 10#${octet} > 255 )); then + echo "Invalid upstream DNS address: ${dns}" >&2 + exit 1 + fi + done + + upstream_dns_servers[$i]="${dns}" +done + +printf 'Docker upstream DNS: %s\n' "${upstream_dns_servers[@]}" + # Rebuild on every start so an interrupted IPv4 or IPv6 installation is repaired. # Set policies first so a failed rule insertion leaves outbound traffic blocked. ip6tables -P OUTPUT DROP @@ -130,10 +167,20 @@ iptables -A NOVISTEPS_INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A NOVISTEPS_INPUT -j DROP iptables -A NOVISTEPS_OUTPUT -o lo -j ACCEPT -# Only Docker's embedded DNS; port 53 to any other IP would bypass the allowlist. +# Allow Docker's embedded DNS. iptables -A NOVISTEPS_OUTPUT -p udp -d 127.0.0.11/32 --dport 53 -j ACCEPT iptables -A NOVISTEPS_OUTPUT -p tcp -d 127.0.0.11/32 --dport 53 -j ACCEPT +# Allow DNS forwarding only to Docker's configured upstream servers. +# Do not permit port 53 to arbitrary destinations. +for dns in "${upstream_dns_servers[@]}"; do + iptables -A NOVISTEPS_OUTPUT \ + -p udp -d "${dns}/32" --dport 53 -j ACCEPT + + iptables -A NOVISTEPS_OUTPUT \ + -p tcp -d "${dns}/32" --dport 53 -j ACCEPT +done + while IFS= read -r db_address; do iptables -A NOVISTEPS_OUTPUT -p tcp -d "${db_address}" --dport 5432 -j ACCEPT done <<<"${db_addresses}" From b89f060c79306a18429b3f7f7a300523aa1fab57 Mon Sep 17 00:00:00 2001 From: "k.hiro1818" Date: Mon, 2 Nov 2026 12:35:05 +0000 Subject: [PATCH 2/2] fix: allow only bare upstream DNS servers through the firewall Docker queries bare ExtServers addresses from the container's namespace and host(...) ones from the host's, so the strict validation blocked legitimate upstream DNS. Co-Authored-By: Claude Sonnet 5.5 --- .devcontainer/init-firewall.sh | 53 +++++----------------------------- 1 file changed, 8 insertions(+), 45 deletions(-) diff --git a/.devcontainer/init-firewall.sh b/.devcontainer/init-firewall.sh index 877724af3..0c3fb30d3 100644 --- a/.devcontainer/init-firewall.sh +++ b/.devcontainer/init-firewall.sh @@ -111,43 +111,6 @@ if ! db_addresses="$(getent ahostsv4 db | awk '$2 == "STREAM" { print $1 }' | so exit 1 fi - -# Obtain Docker's upstream DNS servers before applying firewall rules. -# Docker records them in the ExtServers comment in /etc/resolv.conf. -upstream_dns_line="$( - sed -n 's/^# ExtServers: \[\(.*\)\]$/\1/p' /etc/resolv.conf -)" - -if [[ -z "${upstream_dns_line}" ]]; then - echo 'Failed to obtain Docker upstream DNS servers' >&2 - exit 1 -fi - -IFS=',' read -r -a upstream_dns_servers <<< "${upstream_dns_line}" - -# Validate upstream DNS addresses before changing firewall policies. -for i in "${!upstream_dns_servers[@]}"; do - dns="${upstream_dns_servers[$i]}" - dns="${dns//[[:space:]]/}" - - if [[ ! "${dns}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then - echo "Unsupported upstream DNS address: ${dns}" >&2 - exit 1 - fi - - IFS='.' read -r -a octets <<< "${dns}" - for octet in "${octets[@]}"; do - if (( 10#${octet} > 255 )); then - echo "Invalid upstream DNS address: ${dns}" >&2 - exit 1 - fi - done - - upstream_dns_servers[$i]="${dns}" -done - -printf 'Docker upstream DNS: %s\n' "${upstream_dns_servers[@]}" - # Rebuild on every start so an interrupted IPv4 or IPv6 installation is repaired. # Set policies first so a failed rule insertion leaves outbound traffic blocked. ip6tables -P OUTPUT DROP @@ -167,18 +130,18 @@ iptables -A NOVISTEPS_INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A NOVISTEPS_INPUT -j DROP iptables -A NOVISTEPS_OUTPUT -o lo -j ACCEPT -# Allow Docker's embedded DNS. +# Only Docker's DNS servers; port 53 to any other IP would bypass the allowlist. iptables -A NOVISTEPS_OUTPUT -p udp -d 127.0.0.11/32 --dport 53 -j ACCEPT iptables -A NOVISTEPS_OUTPUT -p tcp -d 127.0.0.11/32 --dport 53 -j ACCEPT -# Allow DNS forwarding only to Docker's configured upstream servers. -# Do not permit port 53 to arbitrary destinations. -for dns in "${upstream_dns_servers[@]}"; do - iptables -A NOVISTEPS_OUTPUT \ - -p udp -d "${dns}/32" --dport 53 -j ACCEPT +# Docker queries bare ExtServers addresses from the container's namespace and host(...) ones from the host's. +read -r -a upstream_dns_entries <<<"$(sed -n 's/^# ExtServers: \[\(.*\)\]$/\1/p' /etc/resolv.conf)" - iptables -A NOVISTEPS_OUTPUT \ - -p tcp -d "${dns}/32" --dport 53 -j ACCEPT +for upstream_dns in "${upstream_dns_entries[@]}"; do + if [[ "${upstream_dns}" =~ ^[0-9.]+$ ]]; then + iptables -A NOVISTEPS_OUTPUT -p udp -d "${upstream_dns}" --dport 53 -j ACCEPT + iptables -A NOVISTEPS_OUTPUT -p tcp -d "${upstream_dns}" --dport 53 -j ACCEPT + fi done while IFS= read -r db_address; do