SOCKS Proxy Support In C# .NET

This post is part of a series on .NET 6 and C# 10 features. Use the following links to navigate to other articles in the series and build up your .NET 6/C# 10 knowledge! While the articles are seperated into .NET 6 and C# 10 changes, these days the lines are very blurred so don’t read too much into it.

.NET 6

Minimal API Framework
DateOnly and TimeOnly Types
LINQ OrDefault Enhancements
Implicit Using Statements
IEnumerable Chunk
SOCKS Proxy Support
Priority Queue
MaxBy/MinBy

C# 10

Global Using Statements
File Scoped Namespaces


With anonymity becoming more and more important each day on the internet, people are turning to VPNs, gateways and proxies to encrypt and hide their identity on the internet. An extremely common protocol for doing this is known as SOCKS proxies.

SOCKS proxies came out (Or atleast the protocol was defined) in the ’90s. But would it surprise you to know that .NET has never supported SOCKS proxies? In fact, since .NET was open sourced on Github, there has been an open issue for adding SOCKS support since 2016 : https://github.com/dotnet/runtime/issues/17740

Well that’s now all in the past, Finally support for SOCKS proxies in .NET is here! Well, in .NET 6 anyway.

Getting Setup With .NET 6

At the time of writing, .NET 6 is in preview, and is not currently available in general release. That doesn’t mean it’s hard to set up, it just means that generally you’re not going to have it already installed on your machine if you haven’t already been playing with some of the latest fandangle features.

To get set up using .NET 6, you can go and read out guide here : https://dotnetcoretutorials.com/2021/03/13/getting-setup-with-net-6-preview/

Remember, this feature is *only* available in .NET 6. Not .NET 5, not .NET Core 3.1, or any other version you can think of. 6.

Basic Usage

The usage for a SOCKS proxy is actually the same as HTTP proxy usage with HttpClient, except that you can now specify the scheme of the address as socks. For example :

var proxy = new WebProxy();
proxy.Address = new Uri("socks5://127.0.0.1:8080");
//proxy.Credentials = new NetworkCredential(); //Used to set Proxy logins. 
var handler = new HttpClientHandler
{
    Proxy = proxy
};
var httpClient = new HttpClient(handler);

What that generally means is while documentation may be slow on actually supporting SOCKS in .NET, if you find any documentation on using proxies with a .NET HttpClient, it should be pretty much identical.

I’d love to write more about this feature but it really is that simple!

Using SOCKS with HttpClient Factories

Since .NET Core 2.1, the usage of HttpClient’s has been pushed towards using HttpClient Factories instead of new’ing up instances yourself. For more information on HttpClient Factories, you can read our helpful guide here : https://dotnetcoretutorials.com/2018/05/03/httpclient-factories-in-net-core-2-1/

Obviously if you are using HttpClient factories, you need a way to specify an HttpClientHandler somewhere in that configuration.

There’s a couple of things to note. First, if you are using named configurations, you can specify a PrimaryHttpMessageHandler yourself that configures your proxy such as :

services.AddHttpClient("proxyClient")
    .ConfigurePrimaryHttpMessageHandler(() => 
    {
        var proxy = new WebProxy();
        proxy.Address = new Uri("socks5://127.0.0.1:8080");
        return new HttpClientHandler
        {
            Proxy = proxy
        };
    });

Again, I want to stress that this is only because I specified a named factory.

This also works if you use a strongly typed factory such as so :

services.AddHttpClient<IMyClient, MyClient>()
    .ConfigurePrimaryHttpMessageHandler(() => 
    {
        var proxy = new WebProxy();
        proxy.Address = new Uri("socks5://127.0.0.1:8080");
        return new HttpClientHandler
        {
            Proxy = proxy
        };
    });

However, if I try and configure the *default* HttpClient factory with no naming, and no types, like so :

services.AddHttpClient()
    .ConfigurePrimaryHttpMessageHandler(() => 
    {
        var proxy = new WebProxy();
        proxy.Address = new Uri("socks5://127.0.0.1:8080");
        return new HttpClientHandler
        {
            Proxy = proxy
        };
    });

I instead get the following error :

'IServiceCollection' does not contain a definition for 'ConfigurePrimaryHttpMessageHandler' and the best extension method overload 'HttpClientBuilderExtensions.ConfigurePrimaryHttpMessageHandler(IHttpClientBuilder, Func<HttpMessageHandler>)' requires a receiver of type 'IHttpClientBuilder'

This is because .NET does not allow you to override the default primary message handler for the default client. If you need to specify a proxy at this level, you need to use named instances.

Again, to make sense of the above you need to read our guide on HttpClientFactories as it really is a new way of using HttpClient’s that only got introduced in the past couple of years. Our guide can be found here : https://dotnetcoretutorials.com/2018/05/03/httpclient-factories-in-net-core-2-1/

ENJOY THIS POST?
Join over 3,000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

3 comments

    1. The IWebProxy interface, and it’s official default Implementation WebProxy, are meant to to serve a very narrowly defined purpose: Proxying webrequests.

      If you implement a full blown SOCKS5 proxy, with all the features the scped can offer, then you would sit on layer 5 (hence why it got that 5 in its name). But if you check all the Socks proxies (just referring to SOCKS5 here, ignoring 4), then ull see that the majority doesnt implement the full spec. Some leave out UDP or only partially implement it. In fact, if you look at proxy server services, then most offer you the choice between SOCKS5/HTTP proxy servers – and i bet, that the majority of SOCKS5 proxies in use out there, serve no other purpose than their HTTP rivals – proxying web requests. And why have it now on the framework as implementation? Because of demand, there were only a handful of working SOCKS5 implementations of IWebProxy out there, some projects deprecated and still relying on the old WebRequests and even WebClient and the question for SOCKS5 support , natively, for HTTPClient – especially with all the improvements since NET Framework 4.x (where most third party implementations originate from) on the .NET ecosystem, the legitimation for a SOCKS5 implementation is more than justified. Every pitty browser supports SOCKS – i’m actually more wondering why the heck it took so long 😉

  1. You _can_ configure the default HttpHandler as the default HttpHandler is a named HttpHandler where the name is string.Empty.

    If you look into the code for AddHttpClient this is the last line:

    services.TryAddTransient((IServiceProvider s) => s.GetRequiredService().CreateClient(string.Empty));

    So then

    services.AddHttpClient(string.Empty)
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
    var proxy = new WebProxy();
    proxy.Address = new Uri(“socks5://127.0.0.1:8080”);
    return new HttpClientHandler
    {
    Proxy = proxy
    };
    });

    would actually configure the default client.

Leave a Reply

Your email address will not be published. Required fields are marked *