fix(dns): probe iptables at /sbin, /usr/sbin when not on PATH (#557)#1168
fix(dns): probe iptables at /sbin, /usr/sbin when not on PATH (#557)#1168cv merged 1 commit intoNVIDIA:mainfrom
Conversation
📝 WalkthroughWalkthroughThe DNS proxy setup now probes for an Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/dns-proxy.test.js (1)
84-114: Add one behavioral test for the missing-iptablesbranch.These cases still only
readFileSync()the script and assert substrings, so a broken probe command or a bad no-iptablescontrol path would still pass. Please add at least onespawnSync()-style test with stubbeddocker/kubectlwrappers that actually runsscripts/setup-dns-proxy.shand 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
📒 Files selected for processing (2)
scripts/setup-dns-proxy.shtest/dns-proxy.test.js
da482b1 to
cea448f
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/setup-dns-proxy.sh (1)
185-190: Consider simplifying the absolute-path probes.The current logic using
command -vwith a fallback works correctly, but for absolute paths like/sbin/iptables, a directtest -xis 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 doneThis separates concerns:
command -vfor PATH lookup (bareiptables),test -xfor 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
📒 Files selected for processing (2)
scripts/setup-dns-proxy.shtest/dns-proxy.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
- 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.
a4a2d9c to
99305f9
Compare
|
Last force push was to fix the commit signature |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/setup-dns-proxy.sh (1)
184-190: The probing logic is sound but consider a simpler check.The current approach works correctly—
command -vreturns the executable path for both bare commands and absolute paths when they exist. However, for absolute path candidates, a directtest -x "$candidate"would be more straightforward:♻️ Optional: Simplified probing logic
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 \"\$(command -v $candidate)\"" 2>/dev/null; then IPTABLES_BIN="$candidate" break fi doneEither form is correct; the current version is functional.
🤖 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 184 - 190, The probing loop for IPTABLES_BIN can be simplified: in the for-loop over candidate and variable IPTABLES_BIN, change the kctl exec test so that if candidate is an absolute path (starts with '/'), run remote 'test -x "$candidate"', otherwise run 'command -v $candidate' (or 'test -x "$(command -v $candidate)"') via kctl exec -n openshell "$POD" -- sh -c; set IPTABLES_BIN="$candidate" and break on success. Use the existing symbols IPTABLES_BIN, candidate, kctl exec, and POD to locate and update the check accordingly.
🤖 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 184-190: The probing loop for IPTABLES_BIN can be simplified: in
the for-loop over candidate and variable IPTABLES_BIN, change the kctl exec test
so that if candidate is an absolute path (starts with '/'), run remote 'test -x
"$candidate"', otherwise run 'command -v $candidate' (or 'test -x "$(command -v
$candidate)"') via kctl exec -n openshell "$POD" -- sh -c; set
IPTABLES_BIN="$candidate" and break on success. Use the existing symbols
IPTABLES_BIN, candidate, kctl exec, and POD to locate and update the check
accordingly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 938ff663-bcdc-4f47-8d20-7dbef1bddbdf
📒 Files selected for processing (2)
scripts/setup-dns-proxy.shtest/dns-proxy.test.js
…#557) (NVIDIA#1168) ## Summary Fixes NVIDIA#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 Signed-off-by: Yimo Jiang <yimoj@nvidia.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Bug Fixes** * Enhanced DNS proxy setup to robustly detect required system utilities in multiple locations before attempting configuration. * Improved error handling with clearer messaging when DNS setup encounters missing dependencies. * Added automatic backup and restore mechanism for DNS configuration to prevent data loss during setup failures. * Fixed DNS rule verification to use dynamically discovered system utilities instead of hardcoded paths. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Summary
Fixes #557 — DNS resolution fails inside sandboxes because
iptablesis not on the sandbox image'sPATH(/sandbox/.venv/bin:/usr/local/bin:/usr/bin:/bin), even though it exists at/sbin/iptables.Problem
The
setup-dns-proxy.shscript runs bareiptablesviaip 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, causingEAI_AGAINfor allgetaddrinfocalls — including WebSocket connections (Slack Socket Mode, Discord gateway) that bypass the HTTP proxy.Fix
iptables,/sbin/iptables,/usr/sbin/iptables) to find the binary before using itresolv.confrewrite when no iptables binary is found, preserving fail-fast behavior instead of silently timing outReproduction
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.comresolves successfullyTest plan
test/dns-proxy.test.jscovering path probing, discovered binary usage, and missing-iptables warningSigned-off-by: Yimo Jiang yimoj@nvidia.com
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes