Skip to content

Add SOCKS5 anti-reuse guard to prevent cross-target routing#34

Merged
39ff merged 3 commits into
claude/squid-socks-proxy-support-CqoL5from
claude/loving-thompson-h33pmh
Jun 13, 2026
Merged

Add SOCKS5 anti-reuse guard to prevent cross-target routing#34
39ff merged 3 commits into
claude/squid-socks-proxy-support-CqoL5from
claude/loving-thompson-h33pmh

Conversation

@39ff

@39ff 39ff commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds a critical safety mechanism to prevent SOCKS peer connections from being reused across different target hosts. A SOCKS-negotiated tunnel is bound to a specific target (host:port), but Squid's persistent connection pool is keyed by peer address only. Without this guard, a pooled SOCKS connection could be silently reused for a different target, causing mis-routing or protocol violations.

Key Changes

  • comm/Connection.h: Added socksNegotiated boolean flag to track whether a connection has already completed SOCKS negotiation. This per-connection marker prevents reuse of tunnels bound to previous targets.

  • FwdState.cc (dispatch hook): Added anti-reuse check that detects if a pooled connection was already SOCKS-negotiated. If so, the connection is dropped and FwdState retries on a fresh fd. Also sets the flag after successful SOCKS negotiation.

  • tunnel.cc (connectDone hook): Added similar anti-reuse guard for tunnel mode. Detects and rejects attempts to re-negotiate or reuse a connection that already carries a SOCKS tunnel. Sets the flag after successful tunnel negotiation.

  • squid-build-test.yml: Added comprehensive regression test (test-socks5-reuse) that:

    • Starts two distinct origin servers (A and B)
    • Configures Squid with server_persistent_connections on to enable connection pooling
    • Routes traffic through a SOCKS5 proxy
    • Alternates requests between targets A and B
    • Verifies that responses always come from the correct origin (no cross-target reuse)
    • Posts Squid logs to PR on failure for debugging

Implementation Details

The fix works by:

  1. Marking a connection as socksNegotiated = true immediately after successful SOCKS tunnel setup
  2. Before reusing any pooled connection for a SOCKS peer, checking if it's already negotiated
  3. If already negotiated, refusing reuse and forcing a fresh connection attempt
  4. This ensures each SOCKS tunnel remains bound to its original target throughout its lifetime

This is a regression fix for P1/P2 codex issues where SOCKS connection reuse could cause silent mis-routing even with persistent connections enabled.

https://claude.ai/code/session_01Dzbzq3FqJHPNEsdNYjGQWn

A SOCKS-negotiated cache_peer connection is a raw tunnel bound to one
target (request->url.host():port). The persistent-connection pool is
keyed by peer, not target, so a pooled SOCKS connection could be reused
for a different target (silent mis-routing, codex P1) or receive a
second SOCKS greeting injected into a live stream (codex P2).

- Add a per-connection socksNegotiated flag to Comm::Connection via a
  new patch_apply.sh section (brace-matched insertion that skips the
  forward declaration and lands the field inside the class body).
- FwdState::dispatch() and TunnelStateData::connectDone() hooks now
  refuse to reuse or re-negotiate an already-negotiated connection:
  they drop it and retry on a fresh fd, so a tunnel to target X can
  never serve target Y. proxyKeepalive=false and
  server_persistent_connections off are kept as defense-in-depth.
- Add CI regression test (test-socks5-reuse) that runs with
  server_persistent_connections ON and alternates requests to two
  distinct origins through one SOCKS peer, asserting no cross-target
  routing.

https://claude.ai/code/session_01Dzbzq3FqJHPNEsdNYjGQWn
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a08bb05a-bec8-4a0d-8125-a9ee0a372d67

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/loving-thompson-h33pmh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

CI build was failing at the tarball download step: www.squid-cache.org
is currently returning HTTP 503 (wget exit 5/8). This is unrelated to
the SOCKS patch and blocks every build (no test can run).

Fetch from multiple mirrors with retries -- GitHub release first (which
serves a byte-identical tarball; its SHA256 matches the existing pin),
then www.squid-cache.org (https, then http) as fallback. The SHA256
integrity check is unchanged, so any mirror serving different bytes
still fails the build; mirror order is therefore safe.

https://claude.ai/code/session_01Dzbzq3FqJHPNEsdNYjGQWn

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7abc3ce1ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (serverConnection()->socksNegotiated) {
debugs(17, 2, "SOCKS: peer connection to " << sp->host
<< " already negotiated; retrying on a fresh connection");
retryOrBail();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Drop the stale SOCKS connection before retrying

When this guard fires on a reused SOCKS pconn, FwdState::noteConnection() has already set destinationReceipt and syncWithServerConn() has installed serverConn/closeHandler before dispatch() runs. Calling retryOrBail() here without first closing/unregistering that fd leaves the negotiated tunnel attached, so the retry re-enters connection opening with destinationReceipt still set and the next noteConnection() can hit its assert(!destinationReceipt) instead of forcing the fresh fd promised by the comment. Please clear/drop the current server connection before retrying.

Useful? React with 👍 / 👎.

Codex flagged that the anti-reuse guard called retryOrBail() without
dropping the current server connection. Verified against the Squid 6.10
source: at FwdState::dispatch() entry, noteConnection() has already set
destinationReceipt and syncWithServerConn() installed serverConn /
closeHandler, so a bare retryOrBail() re-enters noteConnection() with
destinationReceipt still set and trips assert(!destinationReceipt).

- FwdState reuse-guard and negotiation-failure branches now mirror
  serverClosed(): closeServerConnection() + serverConn=nullptr +
  destinationReceipt=nullptr before retryOrBail().
- tunnel.cc connectDone() reuse-guard and negotiation-failure branches now
  call closePendingConnection(conn, ...) before saveError()/retryOrBail(),
  matching every other tunnel.cc error path (retryOrBail asserts
  !server.conn, which holds at connectDone() entry).

Verified by applying patch_apply.sh to the real squid-6.10 tree: patches
apply cleanly, every referenced symbol (closeServerConnection,
destinationReceipt, serverConn, closePendingConnection, saveError,
retryOrBail) resolves to a real declaration, and brace balance is preserved.

https://claude.ai/code/session_01Dzbzq3FqJHPNEsdNYjGQWn
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@39ff 39ff merged commit dc95120 into claude/squid-socks-proxy-support-CqoL5 Jun 13, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants