dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.16k stars 4.72k forks source link

Support for Socks4/5 proxy in HttpClient/WebRequests #17740

Closed abdullah2993 closed 3 years ago

abdullah2993 commented 8 years ago

Any chances of this happening?

davidsh commented 8 years ago

cc: @stephentoub @CIPop @himadrisarkar

CIPop commented 8 years ago

The current status:

@Abdullah2993, can you please share more details about the scenario?

joshfree commented 8 years ago

@ericeil can you comment on linux/mac socks4/5 proxy?

abdullah2993 commented 8 years ago

@CIPop It would be helpful in almost all possible scenarios where you require a proxy besides socks4/5 proxies are available in abundance and most of the HTTP Stacks support them. Another plus point would be integration with TOR

ericeil commented 8 years ago

It looks like CURL does support SOCKS4, 4a, and 5. It also looks like this may already be supported in the current System.Net implementation on Linux/Mac, by setting the request's Proxy property to something that returns, e.g., socks5://proxyhost.domain.com.

CIPop commented 8 years ago

@himadrisarkar In order to support this on Windows, the underlying components (WinINet and WinHTTP) need to be changed. Please follow-up with their respective owners internally.

abdullah2993 commented 7 years ago

Any updates?

davidsh commented 7 years ago

There are no current plans to implement this functionality. Implementing this on Window will require changes to the native HTTP stacks. A linux-only implementation might be possible.

Feel free to submit a PR for this if you need it soon.

karelz commented 7 years ago

Windows doesn't support it (we would need managed implementation or use curl). Curl supports it - we may support it there.

coderb commented 7 years ago

How about creating a pluggable proxy transport underneath the HttpWebRequest/Response?

In other words, allow the user application to register a proxy scheme and have an API for implementing it. The SOCKS protocol is extremely simple but I understand you not wanting to explicitly support it. This would allow others who need it to get by with a "good enough" internal implementation that MS is not on the hook for and have a low support burden.

From what I can tell this would likely involve altering ServicePointManager et al to allow custom ServicePoints. Seems relatively straightforward.

lobster2012-user commented 6 years ago

Add https/socks5 for SocketsHttpClient. Thank you.

mkurz commented 6 years ago

+1

Priya91 commented 6 years ago

+1 Please add support for socketshttpclient, and i assume clientwebsocket will automatically benefit

https://github.com/MicrosoftDocs/live-share/issues/844#issuecomment-417046902

karelz commented 6 years ago

Please upvote the top post - that is searchable and sortable via GitHub ;)

zepprebel commented 5 years ago

how many thumbs up need? to release that

karelz commented 5 years ago

50+ will start to be interesting ...

vfrz commented 4 years ago

Interested about this feature too. Should be possible to implement it through SocketsHttpHandler.

vova-lantsov-dev commented 4 years ago

There is also an implementation of this feature https://github.com/MihaZupan/HttpToSocks5Proxy

karelz commented 4 years ago

Maybe we can ask @MihaZupan to chime in, how difficult it would be to port into our repo ... Anyone is willing to out up a PR?

MihaZupan commented 4 years ago

For people that just want to use a socks5 proxy in their .Net apps right away, the library mentioned above should work fine and should work in every scenario as it implements the IWebProxy interface.

Having built-in support would be better in terms of performance overhead and resolving issues (some error information is swallowed by the library).

Having looked at the code, adding support shouldn't be too difficult now that there is a common managed implementation between platforms. It also likely wouldn't affect the public API surface at all as the type of proxy (http/socks4/socks4a/socks5) can be specified in the Uri scheme.

I think this is reasonable to implement as I've received a lot of requests for this functionality from the community, hence the aforementioned library.

MihaZupan commented 4 years ago

If any community member would like to take this and try implementing it, ping me so I can assign the issue to you. I can help out with PR review.

Otherwise I will look into this in the following weeks.

caunt commented 3 years ago

+1

huoyaoyuan commented 3 years ago

@MihaZupan I'm interested in this because I've read socks5 spec and done some tiny implementation.

MihaZupan commented 3 years ago

@huoyaoyuan That's great to hear!

The idea would be to allow this:

var handler = new HttpClientHandler
{
    Proxy = new WebProxy("socks5://127.0.0.1", 9050)
};
var httpClient = new HttpClient(handler);

Console.WriteLine(await httpClient.GetStringAsync("https://httpbin.org/ip"));

Essentially allowing socks* Uri schemes for IWebProxys and adding logic to handle them inside handlers. Just like we have special code-paths to handle http/connect proxying, we would have another one for establishing a socks tunnel.

This will require changes in HttpConnectionPool, AuthenticationHelper and similar, but won't affect the public API.

I'll be happy to assist if you need help with the implementation/in PR review.

huoyaoyuan commented 3 years ago

@MihaZupan How will this interop with ConnectCallback? For http proxy, ConnectCallback will deal with a http CONNECT request. But there isn't similar concept for socks.

MihaZupan commented 3 years ago

ConnectCallback will be used for the connection to the proxy server - same as with an http proxy (including connect).

In case of an HTTP CONNECT, we create the tunnel by asking the connection pool manager to send a new HttpRequestMessage with the Connect method to the proxy. This request ends up using the ConnectToTcpHostAsync helper that takes ConnectCallback into account. The tunnel (Stream) we use for the actual request is the content stream of the Connect response.

For a Socks tunnel, we would instead use the ConnectToTcpHostAsync helper (to connect to the proxyUri) and perform a Socks tunnel handshake (for the actual host).

huoyaoyuan commented 3 years ago

I'm meaning that if a user specifies both Socks proxy and ConnectCallback, what will they get?

MihaZupan commented 3 years ago

ConnectCallback will still be used to establish the connection. We will use the callback with the Uri of the proxy.

What we do after that (socks handshake / http connect ...) stays the same, regardless of whether the callback was used.

So the behavior for socks would be the same as for an http proxy - if specified, the callback is used for the connection to the proxy (as that is the only connection we're creating ourselves).

ConnectCallback is just used for creating the underlying transport stream. It doesn't care about whether we'll be layering socks/tls on top of it.

huoyaoyuan commented 3 years ago

So, the InitialRequestMessage will be just the original message? Sure

MihaZupan commented 3 years ago

So, the InitialRequestMessage will be just the original message?

Yes

huoyaoyuan commented 3 years ago

After reading implementation, I'm not sure how to carry the information from request to HttpConnectionPool. HttpConnectionKind has complex members because http proxy interacts differently with http and https. However, socks proxy is at socket level and orthogonal with http kind. A new field in HttpConnectionKey feels better to me.