Skip to content

Gate forward SOCKS5 with --allow-socks (wire: add from_socks) (v0.6.1) - #38

Merged
guyte149 merged 6 commits into
masterfrom
feat/gate-forward-socks
May 3, 2026
Merged

Gate forward SOCKS5 with --allow-socks (wire: add from_socks) (v0.6.1)#38
guyte149 merged 6 commits into
masterfrom
feat/gate-forward-socks

Conversation

@guyte149

@guyte149 guyte149 commented May 3, 2026

Copy link
Copy Markdown
Owner

Summary

Follow-up to #37: extend the --allow-socks server gate to cover forward SOCKS5 in addition to reverse SOCKS5. Previously the flag only blocked R:socks because RemoteKind::Socks5 was the only SOCKS-typed thing on the wire — forward socks decomposes into per-target dynamic Tcp/Udp remotes that the server couldn't distinguish from regular forwards.

Fix this by stamping a wire-level from_socks: bool on every dynamic remote produced by RemoteRequest::dynamic_tcp / dynamic_udp. is_socks() now returns true for either kind == Socks5 (reverse R:socks) or from_socks == true (forward socks), so the existing control-plane gate fires for both directions. Reverse SOCKS5 keeps requiring --allow-reverse on top of --allow-socks, so R:socks needs both flags.

Resulting semantics

Server config socks (forward) R:socks (reverse)
no flags rejected rejected
--allow-socks allowed rejected (no reverse)
--allow-reverse rejected rejected (no socks)
both allowed allowed

Breaking changes

  • Wire format: RemoteRequest gains from_socks: bool (#[serde(default)]). Same precedent as 0.4.0 — clients and servers must upgrade together.
  • User-visible: existing deployments using forward socks without an explicit flag must add --allow-socks to the server invocation when upgrading from 0.6.0.

Test plan

  • New test_forward_socks_rejected_when_not_allowed in tests/edge_cases.rs: client SOCKS listener still binds (the SOCKS handshake is purely client-side), but the per-CONNECT dynamic stream is rejected by the server's --allow-socks gate, so the SOCKS5 reply is non-success.
  • New test_reverse_socks_requires_both_flags: --allow-reverse without --allow-socks still rejects R:socks.
  • Pre-existing tests untouched (test helpers default allow_socks=true so SOCKS-using tests don't all need to opt in; new start_tunnel_with_flags helper for tests that exercise the deny path).
  • cargo test --all green; cargo fmt --check green; cargo clippy --all -- -D warnings green.
  • Version bumped to 0.6.1; CHANGELOG 0.6.1 section added (the merged 0.6.0 entry is preserved verbatim).

Notes for downstream embedders

  • RemoteRequest gains pub from_socks: bool (#[serde(default)]). Hand-built RemoteRequest { ... } literals must add the field; users of RemoteRequest::new / RemoteRequest::from_str / dynamic_tcp / dynamic_udp are unaffected.

Made with Cursor

guyte149 and others added 6 commits May 3, 2026 16:27
Per review: --allow-socks should cover both forward AND reverse SOCKS5,
not just reverse. Today forward `socks` decomposes into per-target
dynamic Tcp/Udp remotes on the wire (manufactured by the client's SOCKS
handler on every CONNECT / UDP ASSOCIATE target), so the server has no
way to tell them apart from regular forwards and can't gate them.

Fix this by stamping a wire-level `from_socks: bool` on every dynamic
remote produced by `RemoteRequest::dynamic_tcp` / `dynamic_udp`.
`is_socks()` now returns `true` for either `kind == Socks5` (reverse
`R:socks`) or `from_socks == true` (forward `socks`), so the existing
control-plane gate fires for both directions. Reverse SOCKS5
(`R:socks`) keeps requiring `--allow-reverse` on top of `--allow-socks`,
matching the user-facing semantics.

This is a breaking wire change — same precedent as 0.4.0; clients and
servers must upgrade together.

New regression tests in tests/edge_cases.rs:
- test_forward_socks_rejected_when_not_allowed: client SOCKS listener
  comes up but the per-CONNECT dynamic stream is rejected by the
  server's --allow-socks gate, so the SOCKS5 reply is non-success.
- test_reverse_socks_requires_both_flags: --allow-reverse without
  --allow-socks still rejects R:socks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@guyte149
guyte149 merged commit 11a23c3 into master May 3, 2026
1 check 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.

1 participant