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.

1 comment

Leave a Reply

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