请求中止:无法创建SSL/TLS安全通道

716

由于以下错误信息,我们无法使用WebRequest连接到HTTPS服务器:

The request was aborted: Could not create SSL/TLS secure channel.

我们知道服务器在所使用的路径上没有有效的HTTPS证书,但为了绕过这个问题,我们使用从另一个StackOverflow帖子中获取的以下代码:

private void Somewhere() {
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}

private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
   return true;
}

问题在于服务器从未验证证书,因此出现上述错误。有人知道我该怎么做吗?


我应该提到,几周前我和一位同事进行了测试,并且使用类似我上面写的东西正常工作。我们发现唯一的“主要区别”是我使用的是Windows 7,而他使用的是Windows XP。这会改变什么吗?


4
也请查看这个链接 https://dev59.com/I3I-5IYBdhLWcg3w8dYQ - Oskar Kjellin
135
到了2018年,这个问题已经被查看了308,056次,但仍然没有适当的解决方法!!我会随机遇到这个问题,这里或其他线程提到的任何修复措施都不能解决我的问题。 - Nigel Fds
7
@NigelFds 错误The request was aborted: Could not create SSL/TLS secure channel是一个非常通用的错误。它基本上表示“由于许多可能的原因之一,SSL/TLS/HTTPS连接初始化失败”。因此,如果您在特定情况下经常遇到这个错误,最好的选择是提出一个具体的问题,并提供有关该情况的具体细节。同时,检查事件查看器以获取更多信息。另外,启用一些.NET客户端调试以获取更多详细信息(例如服务器证书是否不受信任?是否存在密码匹配问题?SSL/TLS协议版本不匹配等)。 - MarnixKlooster ReinstateMonica
6
@MarnixKlooster,我已经检查了所有内容,证书不可能是问题,因为如果我重试它,它就可以工作。我怀疑如果我在 SO 上提出这个问题,没有人会标记它为重复或其他什么。 - Nigel Fds
5
使用4.5.2几乎肯定是问题的主要原因。运行时确定安全协议的默认设置,而4.5.x只启用了SSL 3.0和TLS 1.0,这意味着如果您的应用程序调用了一个已禁用TLS 1.0的API,它将无法工作。尝试使用更高版本的.NET Framework,最好是4.7或更高版本。请参见我的答案获取更多详细信息,特别是如果您的应用程序是ASP.NET站点。 - JLRishe
显示剩余14条评论
51个回答

4

我知道回答晚了,但当我尝试从Win Server 2012 R2(客户端)调用托管在Win Server 2016上的API时,遇到了相同的问题。

经过大量调查,发现该问题与操作系统级别的握手问题有关,具体是客户端的密码列表不受主机服务器支持。

当我使用Wireshark跟踪连接时,发现发送的密码不受支持,从而得知这个问题。

Window Server 2012 R2对新密码的支持有限,可能会导致TLS / SSL握手问题。

起点是当我在事件查看器中(事件查看器 >> 自定义视图 >> 管理事件)看到这个错误“从远程端点接收到致命警报。 TLS协议定义的致命警报代码为40”。


4

这对我有用,需要将Network Service添加到权限列表中。 右键单击证书 > 所有任务 > 管理私钥... > 添加... > 添加"Network Service"。


1
你能否请附上截图来详细说明答案? - Ash K

4
我们在客户端Windows Server 2012R2中遇到了同样的问题。 错误40意味着客户端和服务器不同意使用的密码套件。 在大多数情况下,服务器需要一个客户端无法识别的密码套件。
如果您无法修改服务器设置,则解决方案是通过以下方式向客户端添加这些“缺失”的密码套件:
  1. 首先,前往SSLLabs SSL Labs
  2. 输入您无法连接的站点/ API的URL
  3. 等待几分钟直到测试完成
  4. 进入“密码套件”部分,仔细阅读TLS 1.3 / TLS 1.2
  5. 在那里,您将找到服务器接受的密码套件
  6. 现在,在您的Windows服务器上,转到Regedit
  7. 打开键:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL
  8. 在那里,您将找到2个文件夹:00010002 -->TLS 1.2和00010003 --> TLS 1.3
  9. 现在,编辑Functions密钥,并添加服务器所需的密码套件
  10. 在我们的情况下,我们需要将TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384添加到00010002文件夹中

3

没错,我也是这么做的。为了解决它,我按照Nick Gotch的回答所说的去做了:将应用程序池标识更改为LocalSystem。这对我很有帮助。 - Judah Gabriel Himango

3

这个问题有很多答案,因为它涉及到一个通用的错误信息。我们在一些服务器上遇到了这个问题,但在开发机器上没有。在抓狂了很久之后,我们发现这是一个微软的 bug。

https://support.microsoft.com/en-us/help/4458166/applications-that-rely-on-tls-1-2-strong-encryption-experience-connect

基本上,微软认为你想要更弱的加密,但操作系统已经修补程序只允许TLS 1.2,因此您会收到可怕的“请求被中止:无法创建SSL/TLS安全通道”错误消息。
有三种解决方法。
1.使用正确的更新程序修补操作系统:http://www.catalog.update.microsoft.com/Search.aspx?q=kb4458166 2.在您的app.config/web.config文件中添加设置(如上面的链接所述):
3.降低.NET Framework版本。
    <runtime>
       <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false" />
    </runtime>
  1. 添加一个在另一个答案中提到的注册表设置。

所有这些都在我发布的知识库文章中提到了。


此外,请确保您的应用程序中只设置了一次ServicePointManager.SecurityProtocol。我们在我们的应用程序中发现了第二个调用(该应用程序相当复杂,可以在运行时加载可选程序集),它将其设置为SSL3,然后抛出了相同的错误消息。 - Michael Silver
回答不完整。2)哪个设置? - ElektroStudios

3

在我的情况下,我正在使用Visual Studio 2022。一次又一次地遇到这个错误。查看代码后,我发现它成功地检索了证书。安全性被设置为TLS1.2,以上两个答案都是正确的。但无论什么原因,“以管理员身份运行Visual Studio”才能使其正常工作! 也许有人可以向我解释一下,为什么代码可以成功地从存储中检索证书。我可以看到它和所有属性。为什么它不会处理请求,除非我以管理员模式运行VS?


2

在我的情况下,当Windows服务尝试连接Web服务时,我遇到了这个问题。查看Windows事件日志,最终我找到了一个错误代码。

引发了事件ID 36888(Schannel):

The following fatal alert was generated: 40. The internal error state is 808.

最终,这个问题与Windows热补丁有关。在我的情况下:KB3172605和KB3177186。
vmware论坛中提出的解决方案是在Windows中添加一个注册表项。添加以下注册表后,一切正常。
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]
"ClientMinKeyBitLength"=dword:00000200
显然,这与客户端端口的https握手中缺少值有关。
请列出您的Windows热补丁:
wmic qfe list

解决线程:

https://communities.vmware.com/message/2604912#2604912

希望能够帮到您。


2

我在一个网站上遇到了这个问题,后来发现该网站只支持RC4加密。为了增强服务器的安全性,我之前关闭了RC4加密,重新启用后问题得以解决。


1
不要使用链接,因为它们可能在将来无法使用。 - Rodrigo López

2
如果你已经有这个
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
                                                   | SecurityProtocolType.Tls13
                                                   | SecurityProtocolType.Tls12
                                                   | SecurityProtocolType.Tls11
                                                   | SecurityProtocolType.Tls;

在你的代码中,你或者你的客户仍然遇到这个错误。我找到了一个对我们公司有效的解决方法:
我们发现越来越多的错误来自于较新版本的Windows操作系统。我相信这是因为微软开始在最新的Windows更新中停用旧版TLS协议,并且这些协议不再受Windows操作系统支持。似乎上面的枚举类型在套接字握手过程中使用,用于协商安全协议。通过设置这样的枚举类型,你误导地宣称支持操作系统不支持的安全协议。当安全通道打开并且客户端和服务器之间协商出一种不受支持的协议时,就会出现上述错误。从.NET Framework 4.7开始,你不应该显式设置安全协议,而是保留其默认值,即一组操作系统支持的协议。这样,你就不会协商到不受支持的协议,也就不会出现我们所讨论的错误。

1

经过几天的苦思冥想,我们终于解决了问题。我尝试了这篇文章中提到的所有方法,但都不适用于我。我们的客户在Windows虚拟机上运行着一个基本的.NET Framework 4.8控制台应用程序,而我们与其通信的本地服务器要求关闭SSL证书验证。我们的团队成员发现该服务器要求我们使用TLS 1.0,而VM的注册表设置却禁用了TLS 1.0。一旦我们启用了它,问题就得以解决。我还需要添加以下两行代码,正如之前多次提到的:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

很高兴看到即使过了12年,这篇文章仍然在不断地发展和演变,因为每个人都在分享他们的经验。最初的问题肯定已经发生了很大的变化,解决方案也是如此。那么我很高兴你找到了一种方法来让它工作。 - Simon Dugré

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接