fix: add iptables bypass for container self-traffic#977
Conversation
Co-authored-by: Mossaka <5447827+Mossaka@users.noreply.github.com>
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded. |
|
🎬 THE END — Smoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨ |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
There was a problem hiding this comment.
Pull request overview
This PR fixes a bug where test frameworks that bind HTTP servers to 0.0.0.0 and connect via the container's non-loopback IP (e.g., 172.30.0.20) fail with HTTP 403 errors. The issue occurs because the iptables NAT rules redirect this self-directed traffic through the Squid proxy, which denies it as an unauthorized domain.
Changes:
- Added runtime detection of the container's own IP address from the
eth0interface - Added NAT RETURN rule to skip Squid DNAT for traffic destined to the container's own IP
- Added filter ACCEPT rule to prevent the default DROP policy from blocking self-directed traffic
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Smoke Test Results (Copilot)Last 2 Merged PRs:
Test Results:
Status: PASS cc:
|
Build Test: Bun - Results ✅
Overall: PASS ✅ All Bun projects successfully installed dependencies and passed tests.
|
C++ Build Test Results
Overall: PASS All C++ projects configured and built successfully.
|
Build Test: Node.js - Results
Overall: PASS ✅ All Node.js test projects installed successfully and passed their tests.
|
Smoke Test ResultsLast 2 Merged PRs:
Test Results: Status: PASS
|
Go Build Test Results
Overall: PASS ✅ All Go projects successfully downloaded dependencies and passed their tests.
|
|
Merged PRs: feat: update agentic workflows to v0.47.0 and add smoke-gemini; feat: set NO_COLOR=1 in agent container environment
|
.NET Build Test Results
Overall: PASS ✅ All .NET projects successfully restored, built, and ran with expected output.
|
Rust Build Test Results
Overall: PASS ✅ All Rust projects built and tested successfully.
|
Build Test: Java - Results
Overall: PASS All Java projects compiled successfully and all tests passed through the AWF firewall with Maven proxy configuration.
|
Build Test: Deno ✅All Deno tests passed successfully!
Overall: ✅ PASS
|
Chroot Runtime Version Comparison Results
Overall Result: Tests failed - not all runtime versions match between host and chroot environment. The chroot mode successfully accessed host binaries for Go, but Python and Node.js versions differ from the host system.
|
Tests that bind a server to
0.0.0.0and connect via the container's non-loopback IP (172.30.0.20) get DNAT'd to Squid and denied with 403. Loopback (127.0.0.0/8) is bypassed but the container's own eth0 IP is not.Adds a NAT RETURN + filter ACCEPT rule for the agent's own IP, detected at runtime:
DROPfrom blocking it172.30.0.20for robustness if subnet config changesOriginal prompt
This section details on the original issue you should resolve
<issue_title>Container self-traffic routed through Squid proxy causing test failures (go/echo, cpp/cpr, bun/hono, deno/hono)</issue_title>
<issue_description>## Problem
Tests that start a local HTTP server and connect to it via the container's own non-loopback IP fail with HTTP 403 Access Denied from Squid.
Affected test suites (from the v4 build-test experiment):
Typical test pattern:
The same happens when port 80/443 is used and the server listens on
0.0.0.0.Root Cause Analysis
The iptables rules in
containers/agent/setup-iptables.shcorrectly bypass the proxy for loopback traffic:# Allow localhost traffic (for stdio MCP servers) iptables -t nat -A OUTPUT -o lo -j RETURN iptables -t nat -A OUTPUT -d 127.0.0.0/8 -j RETURNHowever, there is no bypass for the container's own non-loopback IP (
172.30.0.20).When a test server binds to
0.0.0.0and the test client connects using the container's own IP (172.30.0.20), the traffic flows like this:The same rules that redirect user-specified ports (
AWF_ALLOW_HOST_PORTS) also catch self-directed traffic on those ports. Even if no extra ports are configured, ports 80 and 443 are always redirected.The existing exemptions in place are:
127.0.0.0/8-d 127.0.0.0/8 -j RETURN172.30.0.10(Squid)-d $SQUID_IP -j RETURN$AWF_API_PROXY_IP-d $AWF_API_PROXY_IP -j RETURNhost.docker.internal-d $HOST_GATEWAY_IP -j RETURN172.30.0.20(self)Proposed Fix
Add a bypass rule for the container's own IP in the NAT OUTPUT chain, placed alongside the existing loopback bypass. The IP should be detected at runtime (not hardcoded) to be robust across configurations:
This should be inserted immediately after the existing loopback bypass block (around line 66), before the DNS and Squid bypass rules, and before the port DNAT rules (lines 224–225).
Why runtime detection vs. hardcoding
172.30.0.20?docker-manager.tstoday hardcodesagentIp: '172.30.0.20', so172.30.0.20would work. However, runtime detection viaip addris more defensive — it remains correct if the network config ever changes or if--build-localis used with a different subnet.Security Considerations
This change is safe because:
Self-traffic only — The bypass applies only to traffic whose destination is the container's own IP (
172.30.0.20). External IPs are unaffected.No new exfiltration path — Any data sent to
172.30.0.20:PORTstays within the container's loopback equivalent; it cannot reach the internet.Analogy to loopback — This is functionally equivalent to the existing
127.0.0.0/8bypass. Both cases represent in-container communication that should never be proxied.Filter chain still enforces DROP — Adding a NAT RETURN alone would have left the traffic subject to the
iptables -A OUTPUT -p tcp -j DROPrule. The accompanying filter ACCEPT rule is required, scoped to just the agent's own IP.No impact on Squid domain enforcement — External HTTP/HTTPS traffic continues to flow through Squid and is subject to the domain allowlist as before.
Comparison to existing exemptions — ...
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.