据我所知,.NET中似乎存在很大的局限性,因为使用C#和.NET无法建立使用服务器名称指示(SNI)的TLS连接。我错过了什么或者我的理解是否正确?
是否有人知道我是否以及如何使用OpenSSL.NET,libcurl.NET或其他第三方.NET库进行SNI连接?我们非常感谢一些示例代码。
答案 0 :(得分:3)
在我的.Net 4.5项目中,对于使用SNI的服务器,以下操作失败:
var url = "https://www.somesite.com";
System.Net.WebClient client = new System.Net.WebClient();
client.Encoding = Encoding.UTF8;
var data = client.DownloadString(url);
但是如果通过以下方式明确指定TLS1.2,它就可以工作:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
同样适用于webrequest:
WebRequest request = WebRequest.Create("https://www.somesite.com");
和HttpRequestMessage:
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "https://www.google.com");
他们都需要将协议显式设置为TLS 1.2才能与SNI服务器一起使用(在新的.Net版本中可能已更改)
答案 1 :(得分:1)
这是一个相当古老的帖子,但这个答案可能对某些人有所帮助,至少它花了我几天。
.NET Framework默认支持服务器名称指示。 (测试4.5.1但我认为至少对于.NET 4.5+它是相同的)
一个简短的例子:
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;
}
这是在C#中创建GET请求的一种非常标准的方法。你会看到,在我的例子中,这个例子确实使用了带有SNI的TLS 1.2。如果您使用Wireshark查看发送的实际包,您将看到一个客户端Hello,其服务器名称指示设置为www.google.com。
我们遇到的一个问题:SNI标记是由.NET Framework(或Windows的Schannel,不确定)根据HttpRequestMessage的构造函数中传递的URL设置的。如果您知道根据某些网址(例如https://www.google.com)初始化请求,稍后您可以切换 RequestUri 或 主机标题,仍将基于原始URL URL创建SNI标记。例如,如果您通过请求并将所有原始标头重新映射到新创建的请求,则可能就是这种情况。