7

As far as I can tell, there seems to be a big limitation in .NET in that there is no way using C# and .NET to make an TLS connection that uses Server Name Indication (SNI). Have I missed something or is my understanding correct?

Does anybody know if and how I could make an SNI connection using OpenSSL.NET, libcurl.NET or some other 3rd party .NET library? Some sample code would be very much appreciated.

woollybrain
  • 843
  • 1
  • 8
  • 12
  • Our SecureBlackbox fully supports SNI in both client and server TLS components – Eugene Mayevski 'Callback Nov 14 '13 at 15:21
  • SNI is a TLS extension, not SSL, so the first step is selecting the right protocol. But yes, .NET as of 4.5 doesn't support SNI, which is a damn shame. http://connect.microsoft.com/VisualStudio/feedback/details/729925/net-4-4-5-sslstream-no-supports-the-tls-server-name-indication-sni – Bruno Rohée Nov 21 '13 at 14:35
  • @Bruno thanks I've updated question to state the correct protocol. Would have been easier if the IETF had called their version SSL v4 ;-) – woollybrain Nov 21 '13 at 19:42
  • @EugeneMayevski'EldoSCorp Is there any documentation (preferably sample code) about how to use your `TElHTTPSClient` class with SNI? [This page](https://www.eldos.com/documentation/sbb/documentation/ref_cl_httpsclient.html) only lists the class members, but provides no further guidance. There is also no sample project installed that would show how to use HTTPS. – Clemens Oct 20 '14 at 12:38
  • @Clemens Please see this forum post for example: https://www.eldos.com/forum/read.php?FID=7&TID=5534 – Eugene Mayevski 'Callback Oct 20 '14 at 13:35
  • @EugeneMayevski'EldoSCorp Thanks for the link, but that post seems to be about `TElSMTPClient`, not `TElHTTPSClient`. – Clemens Oct 20 '14 at 13:59
  • @Clemens this doesn't matter - the code is the same. You are welcome to post further questions to our forum and helpdesk - we don't provide support via StackOverflow. – Eugene Mayevski 'Callback Oct 20 '14 at 15:33

2 Answers2

5

In my .Net 4.5 project the following fails for a server using SNI:

var url = "https://www.somesite.com";
System.Net.WebClient client = new System.Net.WebClient();
client.Encoding = Encoding.UTF8;
var data = client.DownloadString(url);

But it works if explicitly specifying TLS1.2 by prefixing it with:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

The same applies to webrequest:

WebRequest request = WebRequest.Create("https://www.somesite.com");

and HttpRequestMessage:

var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");

They all need the protocol explicitly set to TLS 1.2 to work with an SNI server (this may have changed in newer .Net versions)

Tikall
  • 2,453
  • 25
  • 13
  • Where exactly do you "prefix" SecurityProtocolType.Tls12 using WebClient? Txs! – smoore4 Jan 28 '19 at 16:33
  • Apparently anywhere, like in this question? https://stackoverflow.com/questions/20064505/requesting-html-over-https-with-c-sharp-webclient – smoore4 Jan 28 '19 at 16:37
2

This is a fairly old post but still this answer might help some people, at least it cost me some days.

.NET Framework does support the Server Name Indication by default. (Tested on 4.5.1 but I guess it's same at least for .NET 4.5+)

A short example:

HttpResponseMessage response;
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");

var handler = new HttpClientHandler
{
    CookieContainer = new CookieContainer()
};
using (var client = new HttpClient(handler))
{
    response = client.SendAsync(httpRequestMessage).Result;
}

This is a very standard way to create a GET request within C#. You will see, this example does run using, in my case, TLS 1.2 with SNI. If you use Wireshark to see the actual packages which are sent, you will see a Client Hello with the Server Name Indication set to www.google.com.

An issue we ran into: The SNI tag is set by the .NET Framework (or Schannel by Windows, not sure) based on the URL passed in the constructor of HttpRequestMessage. If you know initialize the request based on some URL (for example https://www.google.com) and later on you switch the RequestUri OR the Host header, the SNI tag will still be created based on the original url URL. This might be the case for example if you pass through a request and you remap all original headers to the newly created request.

panick
  • 21
  • 1
  • 2
  • 5
  • I'm afraid I am unable to reproduce the behavior you mention in the last paragraph (which is unfortunate as I was hoping to use this as a hacky way of modifying the SNI tag). I've [posted this as a follow-up question](https://stackoverflow.com/q/54186478/5085211). – fuglede Jan 14 '19 at 17:33