据我所知,.NET 似乎存在很大的限制,因为无法使用 C# 和 .NET 建立使用服务器名称指示 (SNI) 的 TLS 连接。我错过了什么还是我的理解正确?
有人知道我是否以及如何使用 OpenSSL.NET、libcurl.NET 或其他一些 3rd 方 .NET 库建立 SNI 连接?一些示例代码将不胜感激。
在我的 .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 版本中有所更改)
这是一篇相当老的帖子,但这个答案仍然可能对某些人有所帮助,至少它花了我几天的时间。
默认情况下,.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 设置的。如果您知道基于某个 URL(例如https://www.google.com )初始化请求,然后您切换RequestUri 或Host标头,SNI 标签仍将基于原始 url URL 创建。例如,如果您通过请求并将所有原始标头重新映射到新创建的请求,则可能会出现这种情况。