Server Name Indication from C#

佐手、 提交于 2019-12-08 18:01:08

问题


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.


回答1:


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)




回答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.



来源:https://stackoverflow.com/questions/19971236/server-name-indication-from-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!