Skip to content

fix: disable IPv6 in agent container to prevent squid proxy bypass#1544

Merged
lpcox merged 3 commits intomainfrom
fix/ipv6-squid-chroot
Apr 1, 2026
Merged

fix: disable IPv6 in agent container to prevent squid proxy bypass#1544
lpcox merged 3 commits intomainfrom
fix/ipv6-squid-chroot

Conversation

@lpcox
Copy link
Copy Markdown
Collaborator

@lpcox lpcox commented Apr 1, 2026

Problem

Claude Code running inside the AWF chroot fails to reach the Anthropic API because connections arrive at Squid via IPv6 (::1), which Squid cannot handle. Squid logs 49 transaction-end-before-headers errors matching Claude Code's retry pattern.

Reported in github/gh-aw#23765.

Working (API proxy, IPv4):

{"client":"172.30.0.20","host":"api.anthropic.com:443","method":"CONNECT","status":200}

Failing (Claude Code, IPv6):

{"client":"::1","host":"-","method":"-","status":0,"decision":"NONE_NONE","url":"error:transaction-end-before-headers"}

Root Cause

Three gaps combine:

  1. Squid only listens on IPv4http_port 3128 binds to 0.0.0.0, not [::]
  2. No ip6tables DNAT rules — IPv4-only DNAT redirects port 443 → Squid; IPv6 connections bypass this
  3. IPv6 only disabled when ip6tables is unavailable — on ubuntu-latest (where ip6tables IS available), IPv6 remains enabled with no DNAT rules

Node.js happy-eyeballs (RFC 8305) prefers IPv6 when available, so Claude Code's HTTPS connections go via ::1 instead of IPv4, bypassing the proxy entirely.

Fix

1. Always disable IPv6 in agent container (setup-iptables.sh)

Unconditionally disable IPv6 via sysctl regardless of ip6tables availability. The awf-net Docker network is IPv4-only and Squid listens on IPv4, so IPv6 serves no purpose:

sysctl -w net.ipv6.conf.all.disable_ipv6=1
sysctl -w net.ipv6.conf.default.disable_ipv6=1

This forces DNS to return only A records (no AAAA), eliminating the happy-eyeballs race.

2. Add IPv6 listener to Squid (squid-config.ts) — defense-in-depth

Add http_port [::]:3128 alongside the IPv4 listener (both standard and SSL-bump modes). If IPv6 traffic somehow reaches Squid, it can handle it rather than silently rejecting.

Testing

  • All 146 squid-config tests pass
  • All 1229 root tests pass (3 pre-existing failures in docker-manager.test.ts, unrelated)

Closes #1543

Always disable IPv6 via sysctl in setup-iptables.sh regardless of
ip6tables availability. The awf-net Docker network is IPv4-only and
Squid only listens on IPv4, so IPv6 serves no purpose in the agent
container. Leaving it enabled causes Node.js happy-eyeballs to prefer
IPv6, resulting in connections to ::1 that Squid rejects with
transaction-end-before-headers.

Also add IPv6 listeners to Squid config (http_port [::]:3128) as
defense-in-depth, so any residual IPv6 traffic is handled rather
than silently rejected.

Closes #1543

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lpcox lpcox requested a review from Mossaka as a code owner April 1, 2026 03:05
Copilot AI review requested due to automatic review settings April 1, 2026 03:05
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 82.67% 82.77% 📈 +0.10%
Statements 82.34% 82.43% 📈 +0.09%
Functions 81.22% 81.22% ➡️ +0.00%
Branches 75.94% 76.00% 📈 +0.06%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 85.8% → 86.2% (+0.41%) 85.3% → 85.7% (+0.40%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to prevent IPv6-based proxy bypass / connectivity issues in the agent runtime by disabling IPv6 in the agent network namespace and adding an IPv6 listener to the generated Squid configuration as a defense-in-depth measure.

Changes:

  • Update setup-iptables.sh to disable IPv6 via sysctl unconditionally in the agent network namespace.
  • Update generateSquidConfig() / SSL-bump config generation to add http_port [::]:<port> listeners alongside IPv4.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/squid-config.ts Adds IPv6 http_port listeners in both normal and SSL-bump generated Squid configs.
containers/agent/setup-iptables.sh Disables IPv6 unconditionally to prevent IPv6 traffic bypassing IPv4-only NAT redirection.
Comments suppressed due to low confidence (1)

src/squid-config.ts:431

  • Same as above: “(see #1543)” is ambiguous and inconsistent with existing issue-link style in this repo/file. Please change to “gh-aw-firewall issue #1543” or a full #1543 URL.
  // Port configuration: Use normal proxy mode (not intercept mode)
  // With targeted port redirection in iptables, traffic is explicitly redirected
  // to Squid on specific ports (80, 443, + user-specified), maintaining defense-in-depth
  // Listen on both IPv4 and IPv6 as defense-in-depth (see #1543)
  let portConfig = `http_port ${port}\nhttp_port [::]:${port}`;

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

🤖 Smoke test results for run 23829922192:

Test Result
GitHub MCP: Last 2 merged PRs #1539 feat: add token usage tracking to api-proxy sidecar (@lpcox) · #1534 feat: add smoke-services workflow for --allow-host-service-ports e2e testing (@lpcox)
Playwright: github.com title ✅ "GitHub · Change is constant. GitHub keeps you ahead. · GitHub"
File write/read /tmp/gh-aw/agent/smoke-test-copilot-23829922192.txt created and verified
Bash tool ✅ Commands executed successfully

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot for issue #1544

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke test results (run 23829922222)

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1544

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3
Node.js v24.14.0 v20.20.1
Go go1.22.12 go1.22.12

Overall: ❌ Not all runtimes match — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1544

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color 1/1 passed ✅ PASS
Go env 1/1 passed ✅ PASS
Go uuid 1/1 passed ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx All passed ✅ PASS
Node.js execa All passed ✅ PASS
Node.js p-limit All passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — ✅ PASS

Generated by Build Test Suite for issue #1544 ·

@github-actions

This comment has been minimized.

@github-actions github-actions bot mentioned this pull request Apr 1, 2026
lpcox and others added 2 commits March 31, 2026 20:38
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

🚬 Smoke test results for PR #1544@lpcox

Test Result
GitHub MCP: last 2 merged PRs #1539 feat: add token usage tracking to api-proxy sidecar / #1534 feat: add smoke-services workflow
Playwright: github.com title ✅ "GitHub · Change is constant. GitHub keeps you ahead."
File write /tmp/gh-aw/agent/smoke-test-copilot-23830751963.txt created
Bash verify ✅ File read back successfully

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot for issue #1544

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results — Run 23830751977

Test Result
GitHub MCP: #1539 feat: add token usage tracking to api-proxy sidecar
GitHub MCP: #1534 feat: add smoke-services workflow for --allow-host-service-ports e2e testing
Playwright: github.com title contains "GitHub"
File write: smoke-test-claude-23830751977.txt
Bash verify: file read back successfully

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude for issue #1544

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3 ❌ NO
Node.js v24.14.0 v20.20.1 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.

Tested by Smoke Chroot for issue #1544

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test: GitHub Actions Services Connectivity ✅

All checks passed:

Check Method Result
Redis PING @ host.docker.internal:6379 bash /dev/tcp (redis-cli not installed) +PONG
PostgreSQL pg_isready @ host.docker.internal:5432 pg_isready ✅ accepting connections
PostgreSQL SELECT 1 on smoketest db psql as postgres ✅ returns 1

Note: redis-cli was not available in the environment; Redis connectivity was verified via raw TCP (/dev/tcp).

🔌 Service connectivity validated by Smoke Services

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results

PR titles: "feat: add token usage tracking to api-proxy sidecar" | "feat: add smoke-services workflow for --allow-host-service-ports e2e testing"

  1. GitHub MCP review last 2 merged PRs: ✅
  2. safeinputs-gh PR query: ❌
  3. Playwright GitHub title check: ❌
  4. Tavily web search: ❌
  5. File write /tmp/gh-aw/agent/smoke-test-codex-23830751964.txt: ✅
  6. Bash cat verification: ✅
  7. Discussion interaction + mystical comment: ❌
  8. npm ci && npm run build: ✅
    Overall status: FAIL

🔮 The oracle has spoken through Smoke Codex

@lpcox lpcox merged commit 850e7a0 into main Apr 1, 2026
64 of 65 checks passed
@lpcox lpcox deleted the fix/ipv6-squid-chroot branch April 1, 2026 04:03
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Smoke Test Results — run 23848925605

✅ GitHub MCP: #1544 fix: disable IPv6 in agent container to prevent squid proxy bypass, #1539 feat: add token usage tracking to api-proxy sidecar
✅ Playwright: github.com title contains "GitHub"
✅ File write: /tmp/gh-aw/agent/smoke-test-claude-23848925605.txt created
✅ Bash verify: file content confirmed

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Squid proxy rejects IPv6 localhost connections from chroot (transaction-end-before-headers)

2 participants