Skip to content

fix(dns): probe iptables at /sbin, /usr/sbin when not on PATH (#557)#1168

Open
yimoj wants to merge 1 commit intoNVIDIA:mainfrom
yimoj:fix/dns-proxy-iptables-path-557
Open

fix(dns): probe iptables at /sbin, /usr/sbin when not on PATH (#557)#1168
yimoj wants to merge 1 commit intoNVIDIA:mainfrom
yimoj:fix/dns-proxy-iptables-path-557

Conversation

@yimoj
Copy link
Copy Markdown
Contributor

@yimoj yimoj commented Mar 31, 2026

Summary

Fixes #557 — DNS resolution fails inside sandboxes because iptables is not on the sandbox image's PATH (/sandbox/.venv/bin:/usr/local/bin:/usr/bin:/bin), even though it exists at /sbin/iptables.

Problem

The setup-dns-proxy.sh script runs bare iptables via ip netns exec, which searches PATH and fails silently. Without the iptables UDP:53 exception rule, DNS queries from the sandbox never reach the pod-side forwarder, causing EAI_AGAIN for all getaddrinfo calls — including WebSocket connections (Slack Socket Mode, Discord gateway) that bypass the HTTP proxy.

Fix

  • Probe well-known paths (iptables, /sbin/iptables, /usr/sbin/iptables) to find the binary before using it
  • Use the discovered path for both rule insertion and runtime verification
  • Skip the resolv.conf rewrite when no iptables binary is found, preserving fail-fast behavior instead of silently timing out
  • Warn clearly when iptables is not found at any path

Reproduction

Verified on macOS (Apple Silicon) with OpenShell 0.0.16 + Colima + ghcr.io/nvidia/openshell-community/sandboxes/base:latest:

Before: socket.gaierror: [Errno -3] Temporary failure in name resolution (EAI_AGAIN)
After: All 4 verification checks pass, wss-primary.slack.com resolves successfully

Test plan

  • 3 new tests in test/dns-proxy.test.js covering path probing, discovered binary usage, and missing-iptables warning
  • Full suite: 683 passed, 3 skipped

Summary by CodeRabbit

  • Bug Fixes

    • Improved DNS proxy setup with iptables discovery across multiple fallback paths and use of the discovered binary for rule checks.
    • Avoids rewriting /etc/resolv.conf when iptables is unavailable; creates a one-time backup and restores it on failure.
    • Emits clearer warnings when sandbox iptables are missing; validation prevents partial rule application.
  • Tests

    • Added tests for iptables discovery, rule insertion/checking, backup/restore behavior, and related warning messages.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

The DNS proxy setup script now probes for an iptables executable inside the sandbox (checking iptables, /sbin/iptables, /usr/sbin/iptables) and only adds the UDP:53 ACCEPT rule and rewrites /etc/resolv.conf if a usable IPTABLES_BIN is found. Tests were expanded to cover fallback discovery, verification using IPTABLES_BIN, and behavior when iptables is missing.

Changes

Cohort / File(s) Summary
DNS Proxy Setup Script
scripts/setup-dns-proxy.sh
Probe for iptables at iptables, /sbin/iptables, /usr/sbin/iptables and set IPTABLES_BIN accordingly; only add UDP:53 ACCEPT rule and rewrite /etc/resolv.conf when IPTABLES_BIN is usable. Use IPTABLES_BIN for runtime rule checks and update final incomplete-setup warning to reference #626 and #557. Preserve previous warning when sandbox namespace is missing; emit warnings and restore /etc/resolv.conf from /tmp/resolv.conf.orig if iptables absent.
DNS Proxy Tests
test/dns-proxy.test.js
Adjust assertions to match -C OUTPUT substring; add tests for discovery of fallback iptables paths and for using IPTABLES_BIN in insertion and existence checks; add tests for missing-iptables warnings (“iptables not found in pod”, “Cannot add UDP DNS exception”); verify resolv.conf backup (/tmp/resolv.conf.orig) and restoration behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I sniffed through bins both near and far,
/sbin, /usr/sbin, and the default jar.
If iptables hides, I warn and restore,
So DNS stays tidy — hop, skip, encore! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: fixing DNS proxy setup by probing iptables at standard fallback paths when not on PATH, and references the associated issue #557.
Linked Issues check ✅ Passed The PR fully addresses issue #557's coding requirements: probing iptables at /sbin and /usr/sbin, using the discovered binary for rule insertion and verification, emitting clear warnings when iptables is missing, and preserving fail-fast behavior.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the iptables discovery and usage in setup-dns-proxy.sh and its corresponding test coverage; no extraneous modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/dns-proxy.test.js (1)

84-114: Add one behavioral test for the missing-iptables branch.

These cases still only readFileSync() the script and assert substrings, so a broken probe command or a bad no-iptables control path would still pass. Please add at least one spawnSync()-style test with stubbed docker/kubectl wrappers that actually runs scripts/setup-dns-proxy.sh and asserts the warning plus the no-/etc/resolv.conf-rewrite behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/dns-proxy.test.js` around lines 84 - 114, The current tests only inspect
the script text; add a behavioral test in test/dns-proxy.test.js that actually
executes scripts/setup-dns-proxy.sh via child_process.spawnSync (or a test
helper that wraps spawnSync) with environment stubs for docker/kubectl so the
probe path returns "not found", then assert the subprocess stdout/stderr
contains the iptables-missing warning ("iptables not found in pod" / "Cannot add
UDP DNS exception") and verify that the script did not attempt to rewrite
/etc/resolv.conf (e.g., by checking no writes or that the script exits before
writing that file). Stub the docker/kubectl wrappers used by the script (mock
the commands on PATH or set PATH to point to test shims) so the iptables probe
branch is exercised rather than just reading SETUP_DNS_PROXY content.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/setup-dns-proxy.sh`:
- Around line 200-213: Persist the sandbox's original /etc/resolv.conf before
the first rewrite (e.g., when you run the kctl exec ... sh -c "printf
'nameserver ${VETH_GW}...' > /etc/resolv.conf" in the Step 5 block) by saving
its contents to a safe file in the sandbox namespace (use SANDBOX_NS and POD
context, e.g., /tmp/original_resolv.conf) and then, in the else branch where
iptables is not found, restore that saved file back to /etc/resolv.conf via kctl
exec (using the same POD and SANDBOX_NS) so the original resolver is
re-established when the UDP:53 iptables exception cannot be installed; ensure
the save happens only once (detect existing backup before overwriting) and use
the same kctl/ip netns invocation pattern as the existing rewrite to locate the
correct namespace and file.

---

Nitpick comments:
In `@test/dns-proxy.test.js`:
- Around line 84-114: The current tests only inspect the script text; add a
behavioral test in test/dns-proxy.test.js that actually executes
scripts/setup-dns-proxy.sh via child_process.spawnSync (or a test helper that
wraps spawnSync) with environment stubs for docker/kubectl so the probe path
returns "not found", then assert the subprocess stdout/stderr contains the
iptables-missing warning ("iptables not found in pod" / "Cannot add UDP DNS
exception") and verify that the script did not attempt to rewrite
/etc/resolv.conf (e.g., by checking no writes or that the script exits before
writing that file). Stub the docker/kubectl wrappers used by the script (mock
the commands on PATH or set PATH to point to test shims) so the iptables probe
branch is exercised rather than just reading SETUP_DNS_PROXY content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: baaa7c8f-afa3-4af6-85bc-d5b2d6b721cf

📥 Commits

Reviewing files that changed from the base of the PR and between 36f4456 and da482b1.

📒 Files selected for processing (2)
  • scripts/setup-dns-proxy.sh
  • test/dns-proxy.test.js

…#557)

DNS setup failed silently on sandbox images where iptables was installed
at /sbin/iptables but not on PATH. The script now probes well-known
locations before giving up, and skips the resolv.conf rewrite when no
iptables binary is found to preserve fail-fast behavior.
@yimoj yimoj force-pushed the fix/dns-proxy-iptables-path-557 branch from da482b1 to cea448f Compare March 31, 2026 11:22
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/setup-dns-proxy.sh (1)

185-190: Consider simplifying the absolute-path probes.

The current logic using command -v with a fallback works correctly, but for absolute paths like /sbin/iptables, a direct test -x is clearer since the path is already fully qualified.

♻️ Suggested simplification
   IPTABLES_BIN=""
   for candidate in iptables /sbin/iptables /usr/sbin/iptables; do
-    if kctl exec -n openshell "$POD" -- sh -c "test -x \"\$(command -v $candidate 2>/dev/null || echo $candidate)\"" 2>/dev/null; then
+    if kctl exec -n openshell "$POD" -- sh -c "command -v $candidate >/dev/null 2>&1 || test -x $candidate" 2>/dev/null; then
       IPTABLES_BIN="$candidate"
       break
     fi
   done

This separates concerns: command -v for PATH lookup (bare iptables), test -x for absolute paths — making the intent clearer while preserving the same behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/setup-dns-proxy.sh` around lines 185 - 190, Loop that sets
IPTABLES_BIN currently calls command -v even for absolute paths; change the
probe to call command -v only for bare candidates (e.g., "iptables") and use a
direct test -x for absolute candidates (candidates starting with "/") inside the
kctl exec check, preserving the kctl exec -n openshell "$POD" -- sh -c wrapper
and the assignment to IPTABLES_BIN when the check succeeds.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/setup-dns-proxy.sh`:
- Around line 185-190: Loop that sets IPTABLES_BIN currently calls command -v
even for absolute paths; change the probe to call command -v only for bare
candidates (e.g., "iptables") and use a direct test -x for absolute candidates
(candidates starting with "/") inside the kctl exec check, preserving the kctl
exec -n openshell "$POD" -- sh -c wrapper and the assignment to IPTABLES_BIN
when the check succeeds.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5c80259d-2143-4d28-86df-ce69380c7323

📥 Commits

Reviewing files that changed from the base of the PR and between da482b1 and cea448f.

📒 Files selected for processing (2)
  • scripts/setup-dns-proxy.sh
  • test/dns-proxy.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/dns-proxy.test.js

@wscurran wscurran added bug Something isn't working good first issue Good for newcomers Getting Started Use this label to identify setup, installation, or onboarding issues. CI/CD Use this label to identify issues with NemoClaw CI/CD pipeline or GitHub Actions. Platform: Ubuntu Support for Linux Ubuntu priority: medium Issue that should be addressed in upcoming releases labels Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working CI/CD Use this label to identify issues with NemoClaw CI/CD pipeline or GitHub Actions. Getting Started Use this label to identify setup, installation, or onboarding issues. good first issue Good for newcomers Platform: Ubuntu Support for Linux Ubuntu priority: medium Issue that should be addressed in upcoming releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ebSocket connections fail in sandbox — DNS bypasses HTTP proxy (EAI_AGAIN) + policy set unimplemented on macOS

2 participants