Skip to content

fix(sandbox): add DNS forwarder for sandbox network namespace#1

Open
nic-nvidia wants to merge 1 commit intomainfrom
fix/sandbox-dns-forwarder-v2
Open

fix(sandbox): add DNS forwarder for sandbox network namespace#1
nic-nvidia wants to merge 1 commit intomainfrom
fix/sandbox-dns-forwarder-v2

Conversation

@nic-nvidia
Copy link
Owner

Summary

Applications inside sandboxes that do not honor HTTP_PROXY cannot resolve DNS. This breaks WebSocket connections — including Discord and WhatsApp integrations in OpenClaw sandboxes.

The sandbox's only network path is through the HTTP CONNECT proxy, which works for tools like curl, fetch, and git that read HTTP_PROXY. But WebSocket libraries (Discord.js, Baileys) resolve DNS directly and fail with:

Error: getaddrinfo EAI_AGAIN gateway.discord.gg

This PR adds a lightweight DNS forwarder on the host side of the veth pair so all DNS resolution works, regardless of whether the app uses HTTP_PROXY. The proxy still enforces network policy on TCP connections — DNS resolution alone does not grant access.

Reproduction

openshell sandbox create --name dns-test --from openclaw --keep
openshell sandbox connect dns-test

# Inside sandbox:
nslookup example.com
# ;; communications error to 10.43.0.10#53: timed out
# ;; no servers could be reached

Changes

  • New dns_forwarder.rs: UDP forwarder that listens on <host_veth_ip>:53, relays queries to the pod's upstream DNS, and rewrites /etc/resolv.conf to point at itself
  • lib.rs: starts the forwarder during sandbox init (non-fatal — logs a warning and continues if it fails)
  • No new dependencies (uses tokio::net::UdpSocket already in the tree)

Why DNS is broken

The sandbox runs in an isolated network namespace where the only route is 10.200.0.1 (host side of the veth pair). The pod's /etc/resolv.conf points to CoreDNS at 10.43.0.10, but the kube-proxy iptables DNAT rules that make that address work only exist in the pod's original netns — not in the sandbox netns. Any direct DNS query times out.

Testing

  • nslookup / getent hosts resolve inside sandbox
  • Discord WebSocket gateway connects (previously failed with EAI_AGAIN)
  • Unit tests for resolv.conf parsing
  • mise run ci (no access to full CI environment)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)

The sandbox runs in an isolated network namespace where the only route
is to the host side of a veth pair (10.200.0.1). The pod resolv.conf
points to CoreDNS (10.43.0.10), which is unreachable from the sandbox
netns because kube-proxy iptables rules only exist in the pod original
netns.

Applications that honor HTTP_PROXY route through the CONNECT proxy
(which resolves DNS on the host side), but WebSocket clients and other
tools that resolve DNS directly fail with getaddrinfo EAI_AGAIN.

This adds a lightweight UDP DNS forwarder that:
- Listens on the host veth IP port 53 (reachable from sandbox)
- Forwards queries to the pod original upstream DNS server
- Overwrites /etc/resolv.conf to point at the forwarder

The proxy still enforces network policy on TCP connections. DNS
resolution alone does not grant network access.

Tested with OpenClaw sandbox: Discord WebSocket gateway now connects
successfully where it previously failed with EAI_AGAIN.

Signed-off-by: Nic Borensztein <nborensztein@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant