.NET 6 中的 TLS v1.2 密码套件/GET 请求超时
TLS v1.2 Cipher Suites in .NET 6 / GET Request Timeout
我目前正在尝试连接到至少需要 TLS v1.2 的 AWS REST API。客户端还必须支持具有完美前向保密 (PFS) 的密码套件的文档统计信息,例如短暂 Diffie-Hellman (DHE) 或椭圆曲线短暂 Diffie-Hellman (ECDHE)。
当使用 HttpClient
发送 GET
请求时,连接只是超时。我已将 TLS 版本明确设置为 TLSv1.2
,如下所示:
httpClientHandler.SslProtocols = SslProtocols.Tls12;
这有效,我可以在 Wireshark 跟踪中看到使用了正确的 TLS 版本。我还确认没有防火墙问题或类似问题。
工作示例 (CURL)
使用 cURL 时,我可以看到 Sever Hello
响应中的密码套件是 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
,这也是服务器要求的。
错误的示例(带有 HttpClient 的 .NET 6)
在.NET 6中使用HttpClient
时,上面提到的密码套件在Client Hello
中提供,但是服务器响应突然使用TLS_RSA_WITH_AES_256_GCM_SHA384
:
我可以看到 cURL 请求中有其他扩展,例如 Extension: psk_key_exchange_modes
。除了第一个密码套件外,服务器为什么没有任何解释?根据我的理解,第一个提供的密码套件应该是首选,对吗?
有没有办法在 .NET 6 中强制使用特定的密码套件?
这是我用来重现问题的示例:
public async void PollUrl(string url)
{
HttpResponseMessage msg = new HttpResponseMessage();
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
using HttpClientHandler httpClientHandler = new();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true;
httpClientHandler.SslProtocols = SslProtocols.Tls12;
using HttpClient client = new(httpClientHandler);
// This content type is required for the API call
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
try
{
client.Timeout = TimeSpan.FromSeconds(5);
msg = await client.GetAsync(url);
}
catch (Exception e)
{
Console.WriteLine(e);
}
string stringValue = await msg.Content.ReadAsStringAsync();
Console.WriteLine(stringValue);
}
该应用程序在 Server 2016 上 运行。
终于找到原因了。 Windows 没有启用所需的密码套件。我们已经使用IISCrypto启用了相应的密码套件,现在一切正常。
看起来可以强制 .NET 到 TLS 1.2,即使它没有在服务器本身上启用。
我目前正在尝试连接到至少需要 TLS v1.2 的 AWS REST API。客户端还必须支持具有完美前向保密 (PFS) 的密码套件的文档统计信息,例如短暂 Diffie-Hellman (DHE) 或椭圆曲线短暂 Diffie-Hellman (ECDHE)。
当使用 HttpClient
发送 GET
请求时,连接只是超时。我已将 TLS 版本明确设置为 TLSv1.2
,如下所示:
httpClientHandler.SslProtocols = SslProtocols.Tls12;
这有效,我可以在 Wireshark 跟踪中看到使用了正确的 TLS 版本。我还确认没有防火墙问题或类似问题。
工作示例 (CURL)
使用 cURL 时,我可以看到 Sever Hello
响应中的密码套件是 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
,这也是服务器要求的。
错误的示例(带有 HttpClient 的 .NET 6)
在.NET 6中使用HttpClient
时,上面提到的密码套件在Client Hello
中提供,但是服务器响应突然使用TLS_RSA_WITH_AES_256_GCM_SHA384
:
我可以看到 cURL 请求中有其他扩展,例如 Extension: psk_key_exchange_modes
。除了第一个密码套件外,服务器为什么没有任何解释?根据我的理解,第一个提供的密码套件应该是首选,对吗?
有没有办法在 .NET 6 中强制使用特定的密码套件?
这是我用来重现问题的示例:
public async void PollUrl(string url)
{
HttpResponseMessage msg = new HttpResponseMessage();
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
using HttpClientHandler httpClientHandler = new();
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => true;
httpClientHandler.SslProtocols = SslProtocols.Tls12;
using HttpClient client = new(httpClientHandler);
// This content type is required for the API call
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
try
{
client.Timeout = TimeSpan.FromSeconds(5);
msg = await client.GetAsync(url);
}
catch (Exception e)
{
Console.WriteLine(e);
}
string stringValue = await msg.Content.ReadAsStringAsync();
Console.WriteLine(stringValue);
}
该应用程序在 Server 2016 上 运行。
终于找到原因了。 Windows 没有启用所需的密码套件。我们已经使用IISCrypto启用了相应的密码套件,现在一切正常。
看起来可以强制 .NET 到 TLS 1.2,即使它没有在服务器本身上启用。