Skip to content

fix: enable Squid intercept mode for NAT-redirected traffic#520

Open
Mossaka wants to merge 1 commit intomainfrom
fix/squid-intercept-port
Open

fix: enable Squid intercept mode for NAT-redirected traffic#520
Mossaka wants to merge 1 commit intomainfrom
fix/squid-intercept-port

Conversation

@Mossaka
Copy link
Collaborator

@Mossaka Mossaka commented Feb 5, 2026

Summary

When traffic is NAT'd (DNAT) to Squid proxy, clients send relative URLs (GET /path) because they don't know they're talking to a proxy. Squid's normal proxy mode requires absolute URLs (GET http://example.com/path), causing "Invalid URL - Missing hostname" errors.

This is the root cause of Codex smoke test failures - the rmcp client's OAuth discovery requests get NAT'd to Squid but fail because Squid can't process the relative URL.

Changes

  • Add interceptPort to SquidConfig interface for transparent proxy traffic
  • Configure Squid with http_port 3129 intercept for NAT'd traffic
  • Update iptables rules to redirect to intercept port (3129) not regular port (3128)
  • Keep regular port (3128) for explicit proxy usage via HTTP_PROXY

How it works

Port Mode Used For
3128 Normal proxy Explicit proxy (HTTP_PROXY env var) - expects absolute URLs
3129 Intercept NAT/DNAT redirected traffic - handles relative URLs via Host header

Test plan

  • Unit tests pass (121 tests in squid-config.test.ts)
  • New tests for intercept port configuration
  • Integration testing with Codex smoke tests after release

Related

🤖 Generated with Claude Code

When traffic is NAT'd (DNAT) to Squid proxy, clients send relative URLs
(GET /path) because they don't know they're talking to a proxy. Squid's
normal proxy mode requires absolute URLs (GET http://example.com/path),
causing "Invalid URL - Missing hostname" errors.

This fix:
- Adds interceptPort to SquidConfig for transparent proxy traffic
- Configures Squid with `http_port 3129 intercept` for NAT'd traffic
- Updates iptables rules to redirect to intercept port (3129) not
  regular port (3128)
- Keeps regular port (3128) for explicit proxy usage via HTTP_PROXY

This fixes Codex/rmcp OAuth discovery timeouts - requests now reach
the MCP gateway instead of being blocked by Squid.

Fixes #519

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 5, 2026 03:56
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Chroot tests failed Smoke Chroot failed - See logs for details.

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 82.08% 82.10% 📈 +0.02%
Statements 82.12% 82.14% 📈 +0.02%
Functions 81.95% 81.95% ➡️ +0.00%
Branches 75.41% 75.44% 📈 +0.03%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/squid-config.ts 95.1% → 95.2% (+0.06%) 95.2% → 95.2% (+0.05%)

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

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

C++ Build Test Results

Project CMake Build Status
fmt PASS
json PASS

Overall: PASS

All C++ projects configured and built successfully.

AI generated by Build Test C++

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Deno Build Test Results

Project Tests Status
oak 1/1 ✅ PASS
std 1/1 ✅ PASS

Overall: ✅ PASS

All Deno tests passed successfully.

AI generated by Build Test Deno

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Node.js Build Test Results

Project Install Tests Status
clsx PASS PASS
execa PASS PASS
p-limit PASS PASS

Overall: PASS

All Node.js projects built and tested successfully.

AI generated by Build Test Node.js

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Go Build Test Results

Project Download Tests Status
color 1/1 PASS
env 1/1 PASS
uuid 1/1 PASS

Overall: PASS

All Go projects successfully downloaded dependencies and passed their tests.

AI generated by Build Test Go

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Smoke Test Results

✅ GitHub MCP: #515 feat: add AWF agent skill for Claude Code agents, #514 fix: add auth and error handling to build-test workflows
✅ Playwright: GitHub page title verified
✅ File Writing: Test file created successfully
✅ Bash Tool: File verified with cat

Status: PASS

cc: @Mossaka @Copilot

AI generated by Smoke Copilot

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Build Test: Bun - FAILED ❌

Project Install Tests Status
elysia ⚠️ 0/0 FAIL
hono ⚠️ 0/0 FAIL

Overall: FAIL

Error Details

Both projects encountered critical runtime failures:

elysia:

  • Install: error: An internal error occurred (NotDir)
  • Test: bun test v1.3.8 (b64edcb4) Aborted (core dumped) (exit code 134)

hono:

  • Install: error: An internal error occurred (NotDir)
  • Test: bun test v1.3.8 (b64edcb4) Aborted (core dumped) (exit code 134)

Root Cause: Bun runtime is crashing with core dumps on this environment (GitHub Actions runner). This appears to be an environment compatibility issue with Bun v1.3.8.

Action Required: This test cannot pass until the Bun runtime stability issue is resolved.

AI generated by Build Test Bun

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Smoke Test Results - Claude Engine

✅ GitHub MCP - Last 2 merged PRs:

✅ Playwright - GitHub homepage title verified

✅ File Writing - Created /tmp/gh-aw/agent/smoke-test-claude-21698153401.txt

✅ Bash Tool - File read successful

Status: PASS

AI generated by Smoke Claude

Copy link

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 fixes a critical bug where HTTP traffic redirected via iptables NAT (DNAT) to the Squid proxy fails with "Invalid URL - Missing hostname" errors. The root cause is that NAT-redirected clients send relative URLs (e.g., GET /path) because they don't know they're talking to a proxy, but Squid's normal proxy mode requires absolute URLs (e.g., GET http://example.com/path).

Changes:

  • Added interceptPort field to SquidConfig interface for transparent proxy traffic handling
  • Configured Squid with separate intercept port (3129) using http_port 3129 intercept directive
  • Updated iptables rules to redirect NAT traffic to the intercept port instead of the regular proxy port
  • Added test coverage for the new intercept port configuration

Reviewed changes

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

Show a summary per file
File Description
src/types.ts Added interceptPort optional field to SquidConfig interface with comprehensive documentation
src/squid-config.ts Added intercept port configuration to Squid config generation with explanatory comments
src/squid-config.test.ts Added tests verifying intercept port is included when specified and excluded when not
src/docker-manager.ts Passed SQUID_INTERCEPT_PORT constant to Squid config generation
containers/agent/setup-iptables.sh Updated NAT redirection rules to use intercept port for transparent proxy traffic

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

Comment on lines +418 to +420
if (interceptPort) {
portConfig += `\nhttp_port ${interceptPort} intercept`;
}
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

When SSL Bump is enabled, the intercept port configuration added here will be ignored. On line 436 (visible in surrounding context), portConfig is set to empty string when sslBump is enabled, and the SSL Bump section uses a hardcoded port configuration.

The generateSslBumpSection function (called on line 428-434) hardcodes "http_port 3128 ssl-bump" and doesn't receive the port or interceptPort parameters. This means NAT-redirected traffic will fail with "Invalid URL - Missing hostname" errors when SSL Bump is enabled, which is the exact issue this PR is trying to fix.

To fix this, generateSslBumpSection needs to be updated to:

  1. Accept port and interceptPort parameters
  2. Generate both "http_port [port] ssl-bump" and "http_port [interceptPort] ssl-bump intercept" configurations when interceptPort is provided

Without this fix, SSL Bump mode will continue to experience the NAT redirect failures described in issue #519.

Copilot uses AI. Check for mistakes.
Comment on lines +1124 to +1143
it('should add intercept port when specified', () => {
const config: SquidConfig = {
domains: ['github.com'],
port: 3128,
interceptPort: 3129,
};
const result = generateSquidConfig(config);
expect(result).toContain('http_port 3128');
expect(result).toContain('http_port 3129 intercept');
});

it('should not add intercept port when not specified', () => {
const config: SquidConfig = {
domains: ['github.com'],
port: 3128,
};
const result = generateSquidConfig(config);
expect(result).toContain('http_port 3128');
expect(result).not.toContain('intercept');
});
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The new tests for intercept port are placed inside the "SSL Bump Mode" describe block, but they don't actually test the combination of SSL Bump with intercept port. This misses the critical bug where SSL Bump ignores the intercept port configuration.

Add a test that verifies intercept port works with SSL Bump enabled:

  • Config with sslBump: true, interceptPort: 3129
  • Expected: both "http_port 3128 ssl-bump" and "http_port 3129 ssl-bump intercept" in output

This test would catch the bug where generateSslBumpSection doesn't support intercept port.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

❌ Build Test: Java - FAILED

Status: ENVIRONMENT FAILURE

Error

Cannot execute Java tests due to corrupted GitHub Actions runner environment. All Java binaries (across multiple installations) are being executed as bash instead of Java.

Details

Project Compile Tests Status
gson FAILED - Java not executable
caffeine FAILED - Java not executable

Overall: FAIL

Diagnostic Output

$ java -version
GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)

All Java installations tested:

  • /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk/21.0.10-7/x64/bin/java
  • /usr/lib/jvm/temurin-17-jdk-amd64/bin/java
  • /usr/lib/jvm/temurin-21-jdk-amd64/bin/java

Recommendation

This workflow needs to be re-run on a fresh GitHub Actions runner with a functional Java environment.

AI generated by Build Test Java

@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Rust Build Test Results

Project Build Tests Status
fd 1/1 PASS
zoxide 1/1 PASS

Overall: PASS ✅

All Rust projects built successfully and all tests passed.

AI generated by Build Test Rust

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.

HTTP traffic NAT'd to Squid fails with 'Invalid URL - Missing hostname'

1 participant