7

据我所知,.NET 似乎存在很大的限制,因为无法使用 C# 和 .NET 建立使用服务器名称指示 (SNI) 的 TLS 连接。我错过了什么还是我的理解正确?

有人知道我是否以及如何使用 OpenSSL.NET、libcurl.NET 或其他一些 3rd 方 .NET 库建立 SNI 连接?一些示例代码将不胜感激。

4

2 回答 2

5

在我的 .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 版本中有所更改)

于 2018-06-28T08:05:27.353 回答
2

这是一篇相当老的帖子,但这个答案仍然可能对某些人有所帮助,至少它花了我几天的时间。

默认情况下,.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 创建。例如,如果您通过请求并将所有原始标头重新映射到新创建的请求,则可能会出现这种情况。

于 2016-09-26T15:21:00.243 回答