Skip to content

feat(client): add proxy::SocksV4 and proxy::SocksV5 connectors - #187

Merged
seanmonstar merged 5 commits into
hyperium:masterfrom
JPDye:socks-connector
May 19, 2025
Merged

feat(client): add proxy::SocksV4 and proxy::SocksV5 connectors#187
seanmonstar merged 5 commits into
hyperium:masterfrom
JPDye:socks-connector

Conversation

@JPDye

@JPDye JPDye commented Apr 25, 2025

Copy link
Copy Markdown
Contributor

cc hyperium/hyper#3851, hyperium/hyper#3877 #173

Adds SocksV4 and SocksV5 connectors with simple configuration for local and remote DNS. Supports SOCKSv5 user/pass authentication and allows optimistic message sending (not in RFC but supported by most servers) to reduce number of round-trips in SOCKSv5 handshake.

TODO:

  • Properly test optimistic sending against real server implementations
  • Cleanup error handling

@JPDye
JPDye marked this pull request as draft April 25, 2025 14:18
@seanmonstar

Copy link
Copy Markdown
Member

I think this looks pretty great! What's holding it back as a draft?

@JPDye
JPDye force-pushed the socks-connector branch from 591d8f7 to cf3c983 Compare May 8, 2025 12:22
@JPDye

JPDye commented May 8, 2025

Copy link
Copy Markdown
Contributor Author

Needed to test optimistic sending to see if it was worth including. 5/8 of the server implementations I tested worked so I feel like it's a worthwhile addition even if it's not in the RFC.

Will fix the failing check and some of the dirty code in a little, but I'm mostly happy with everything now

@JPDye
JPDye marked this pull request as ready for review May 8, 2025 12:41
@JPDye
JPDye force-pushed the socks-connector branch from 56e0cff to 2370f34 Compare May 12, 2025 15:27

@seanmonstar seanmonstar left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks phenomenal, thank you!

@seanmonstar
seanmonstar merged commit 7e34375 into hyperium:master May 19, 2025
@JPDye

JPDye commented May 19, 2025

Copy link
Copy Markdown
Contributor Author

Thanks for merging this. Is the goal still to refactor Reqwest to use these connectors? I'm happy to take that on to pad my stats so to speak ;)

@seanmonstar

Copy link
Copy Markdown
Member

Yes it is, just filed a new issue: seanmonstar/reqwest#2683

I've got the HTTP tunnel one nearly done, but I haven't started on the SOCKS, if you want to try that :)

seanmonstar pushed a commit that referenced this pull request Aug 2, 2026
`Request::write_to_buf` emitted two NULL bytes after DSTIP, labelled
`USERID` and `NULL`. Per SOCKS4 ("SOCKS: A protocol for TCP proxy across
firewalls", Ying-Da Lee, https://www.openssh.com/txt/socks4.protocol),
a CONNECT request is

    VN(1) CD(1) DSTPORT(2) DSTIP(4) USERID(variable) NULL(1)

where USERID is a variable-length field terminated by a single NULL.
This connector never sends a user ID, so USERID is zero bytes long and
only its terminator belongs on the wire: 9 bytes, not 10.

The extra byte breaks SOCKS4a ("SOCKS 4A: A Simple Extension to SOCKS 4
Protocol", https://www.openssh.com/txt/socks4a.protocol), which appends
a NULL-terminated hostname after the USERID terminator. A server reads
USERID up to the first NULL (correctly empty), then reads the hostname
up to the next NULL -- the stray byte -- so the destination arrives as
an empty string. The request fails, and the real hostname plus its
terminator remain in the server's receive buffer, to be relayed into the
tunnel as the first bytes of application data.

Plain SOCKS4 requests still parse, since the destination is carried in
DSTIP, but the trailing byte is likewise left over and reaches the
target as a stray leading NULL of the tunneled stream.

The bug dates back to the connectors' introduction in #187, and the
domain path had no test coverage, so a SOCKS4a test is added alongside.
Two stale comments on the touched lines are corrected as well:
`put_u16(*port)` was labelled `IP`, and the layout diagram read
"only do IP is 0.0.0.X".
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