Repository navigation
SOCKS5 handshake rejects valid replies split across TCP reads #1127
Unanswered
AryanRG
asked this question in
Potential Issue
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
On current
master(10a658221deb38a4c5b16db55ab554b0bf731707), valid SOCKS5 replies fail when split across TCP reads. Both sync and async_init_socks5_connection()pass a single read directly to socksio at each handshake stage.A real loopback SOCKS peer reproduces this through public
ConnectionPool/AsyncConnectionPoolrequests, using username/password auth (user/pass) andGET http://example.com/. The peer handles the handshake and serves HTTP locally; no external origin or transport mock is involved. At one stage per run, it sends the first reply byte, waits 100 ms, then sends the remainder. The complete replies are:05 02.01 00.05 00 00 01 7f 00 00 01 00 50.Actual: split method/CONNECT replies raise socksio
ProtocolError: Malformed reply; split password replies raiseProxyError: Invalid username/password, before the HTTP request reaches the peer. Identical unsplit replies succeed. Expected: accumulate the complete reply despite short reads, then continue to HTTP 200 with bodyOK. TCP reads need not align with SOCKS message boundaries (RFC 1928, RFC 1929).Fresh local reproduction: 9 failed / 3 passed on master; 12 passed with a local candidate, covering sync, asyncio and Trio. Environment: macOS arm64, Python 3.12.15, socksio 1.0.0, AnyIO 4.15.1, Trio 0.34.0.
The unpublished candidate reads fixed-length auth replies and frames CONNECT by IPv4/IPv6/domain length, preserves trailing bytes and rejects premature EOF. It includes sync/async tests and mock-stream support for bounded reads, with no public API change. Prior local validation produced 253 passed and six unchanged HTTP/2 cancellation XPASSes, plus passing lint/type/generation checks. Independent review was automated. The real-socket probe covers authenticated HTTP and an IPv4 bound reply; other address types use scripted tests. Hosted CI, other OS/Python combinations and TLS-over-SOCKS fragmentation are unverified; Twine metadata validation fails identically on base and candidate.
Scope limits: existing missing handshake timeouts (#1015, #1089) and failure/cancellation socket cleanup remain unresolved. A peer that stops after a prefix can still wait indefinitely; cancellation propagates but can leave a CONNECTING pool entry until pool closure. socksio 1.0.0 also rejects complete domain replies of lengths 128/255 and accepts some invalid version/reserved fields on both versions; this candidate does not fix those dependency behaviors. The related timeout proposals inspected still use single reads; I found no matching framing report in the public search.
Would you consider this framing behavior worth a scoped fix? The candidate code remains local pending maintainer triage. AI agents assisted the investigation, tests, candidate and this report.
All reactions