Skip to content

Commit b89f060

Browse files
KATO-Hiroclaude
andcommitted
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 <noreply@anthropic.com>
1 parent 4a420ae commit b89f060

1 file changed

Lines changed: 8 additions & 45 deletions

File tree

‎.devcontainer/init-firewall.sh‎

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -111,43 +111,6 @@ if ! db_addresses="$(getent ahostsv4 db | awk '$2 == "STREAM" { print $1 }' | so
111111
exit 1
112112
fi
113113

114-
115-
# Obtain Docker's upstream DNS servers before applying firewall rules.
116-
# Docker records them in the ExtServers comment in /etc/resolv.conf.
117-
upstream_dns_line="$(
118-
sed -n 's/^# ExtServers: \[\(.*\)\]$/\1/p' /etc/resolv.conf
119-
)"
120-
121-
if [[ -z "${upstream_dns_line}" ]]; then
122-
echo 'Failed to obtain Docker upstream DNS servers' >&2
123-
exit 1
124-
fi
125-
126-
IFS=',' read -r -a upstream_dns_servers <<< "${upstream_dns_line}"
127-
128-
# Validate upstream DNS addresses before changing firewall policies.
129-
for i in "${!upstream_dns_servers[@]}"; do
130-
dns="${upstream_dns_servers[$i]}"
131-
dns="${dns//[[:space:]]/}"
132-
133-
if [[ ! "${dns}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
134-
echo "Unsupported upstream DNS address: ${dns}" >&2
135-
exit 1
136-
fi
137-
138-
IFS='.' read -r -a octets <<< "${dns}"
139-
for octet in "${octets[@]}"; do
140-
if (( 10#${octet} > 255 )); then
141-
echo "Invalid upstream DNS address: ${dns}" >&2
142-
exit 1
143-
fi
144-
done
145-
146-
upstream_dns_servers[$i]="${dns}"
147-
done
148-
149-
printf 'Docker upstream DNS: %s\n' "${upstream_dns_servers[@]}"
150-
151114
# Rebuild on every start so an interrupted IPv4 or IPv6 installation is repaired.
152115
# Set policies first so a failed rule insertion leaves outbound traffic blocked.
153116
ip6tables -P OUTPUT DROP
@@ -167,18 +130,18 @@ iptables -A NOVISTEPS_INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
167130
iptables -A NOVISTEPS_INPUT -j DROP
168131
iptables -A NOVISTEPS_OUTPUT -o lo -j ACCEPT
169132

170-
# Allow Docker's embedded DNS.
133+
# Only Docker's DNS servers; port 53 to any other IP would bypass the allowlist.
171134
iptables -A NOVISTEPS_OUTPUT -p udp -d 127.0.0.11/32 --dport 53 -j ACCEPT
172135
iptables -A NOVISTEPS_OUTPUT -p tcp -d 127.0.0.11/32 --dport 53 -j ACCEPT
173136

174-
# Allow DNS forwarding only to Docker's configured upstream servers.
175-
# Do not permit port 53 to arbitrary destinations.
176-
for dns in "${upstream_dns_servers[@]}"; do
177-
iptables -A NOVISTEPS_OUTPUT \
178-
-p udp -d "${dns}/32" --dport 53 -j ACCEPT
137+
# Docker queries bare ExtServers addresses from the container's namespace and host(...) ones from the host's.
138+
read -r -a upstream_dns_entries <<<"$(sed -n 's/^# ExtServers: \[\(.*\)\]$/\1/p' /etc/resolv.conf)"
179139

180-
iptables -A NOVISTEPS_OUTPUT \
181-
-p tcp -d "${dns}/32" --dport 53 -j ACCEPT
140+
for upstream_dns in "${upstream_dns_entries[@]}"; do
141+
if [[ "${upstream_dns}" =~ ^[0-9.]+$ ]]; then
142+
iptables -A NOVISTEPS_OUTPUT -p udp -d "${upstream_dns}" --dport 53 -j ACCEPT
143+
iptables -A NOVISTEPS_OUTPUT -p tcp -d "${upstream_dns}" --dport 53 -j ACCEPT
144+
fi
182145
done
183146

184147
while IFS= read -r db_address; do

0 commit comments

Comments
 (0)