【问题标题】:SChannel issue with Windows 10Windows 10 的 SChannel 问题
【发布时间】:2016-02-19 20:03:09
【问题描述】:

我有一个使用 System.Net.Security.SslStream 类与服务器建立安全连接的应用程序。在 Windows 7 和 Windows 8/8.1 上,这可以正常工作。在 Windows 10 上,对 SslStream.AuthenticateAsClient 的调用会引发异常 - “AuthenticationException:对 SSPI 的调用失败,请参阅内部异常”。内部异常是“Win32Exception:无法联系本地安全机构”。这并不特定于一台 Windows 10 机器。

我认为这可能与服务器证书的公钥长度为 512 位有关,因此我使用 512 位公钥创建了自己的自签名证书,并使用它测试了 SslStream.AuthenticateAsClient Windows 10 机器。这工作得很好。

我正在尝试找出导致此功能不再起作用的 Windows 10 中的哪些变化。查看 System.Net 生成的日志和 Wireshark 的捕获,我看到客户端收到 SERVER HELLO、CERTIFICATE 和 SERVER DONE 消息,然后客户端关闭连接。在系统事件日志中,SChannel 记录了一个错误 - “已生成致命警报并将其发送到远程端点。这可能导致连接终止。TLS 协议定义的致命错误代码为 40。Windows SChannel 错误状态是 813。”显然 TLS 错误代码 40 是握手失败,但我无法找到有关 SChannel 错误状态 813 的任何信息。

通过查看 Wireshark 中的 SSL 握手,我发现正在使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密码套件。当我连接到我创建的测试服务器(使用 512 位公钥证书)时,将使用 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 密码套件。在 Windows 10 上使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 是否存在问题?

【问题讨论】:

  • 澄清一下,当您说“使用”时,我想您的意思是您在 ServerHello 中看到了它。如果您在 ServerHello 中看到了这一点,那么服务器同意使用该密码套件,因为它是在 ClientHello 中提供的,因此这不是密码套件问题。
  • 握手失败的具体原因是什么?
  • 正确,这是我在 ServerHello 中看到的密码套件。握手看似成功完成,但在收到 ServerDone 后,客户端立即关闭连接。 InitializeSecurityContext 函数返回错误代码 0x80090304。
  • 好的,握手的工作方式,客户端发送它支持的密码列表,服务器选择一个并在 ServerHello 中响应。因此,我们可以在这里看到它并不是专门的密码套件,因为客户端和服务器都同意 TLS_RSA_WITH_3DES_EDE_CBC_SHA。我认为我知道发生了什么。我会写一个答案。

标签: .net networking sspi


【解决方案1】:

我们的 .Net SSL 客户端应用程序存在类似问题,该应用程序使用 TLS1.0 和 TLS1.2 连接到多个服务器。

问题是 Windows SChannel 中的 TLS1.2 不支持一些弱密码套件,但是对于使用 TLS1.0 的连接,这些密码套件是允许的。

.Net 4.6.1 改变了 Windows 系统的行为;在此版本之前,首选协议是 TLS1.0,更新到版本 >=4.6.1 之后,所有 .Net 客户端都会自动设置为 TLS 1.2。此外,一些 KB 安全更新可能会影响行为。

第一种方法是修改应用程序以严格使用TLS1.0(从安全角度来看这是不正确的):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls

第二种方法是使用免费工具 IISCrypto,它可以帮助您禁用/启用您的协议和密码套件: https://www.nartac.com/Products/IISCrypto IISCrypto-Ciphers-Selection

请注意,这些设置存储在 Windows 注册表中,并且对所有协议都是通用的,您可能需要“玩”配置以找到最适合您正在使用的所有连接的配置。

【讨论】:

    【解决方案2】:

    好的,既然您在 ServerHello 中看到了密码套件,我们可以得出结论,客户端和服务器都支持该密码套件,因此问题不在于密码套件。

    当您在密码套件中使用 ECDHE 或 DHE 时,我怀疑问题出在您的 512 位证书上。如果我没记错的话,Windows 10 需要 1024 位(有效)或更高的密钥交换。由于您没有使用 ECDHE 或 DHE 进行密钥交换,它使用的是 RSA,并且您的证书是 512 位的,因此它尝试使用 512 位 RSA 进行密钥交换部分。您的新服务器没有因 512 位证书而失败,因为它使用的是 EC Diffie-Hellman。

    您可以通过以下方式之一进行测试

    • 禁用新测试服务器上使用 DHE 或 ECDHE 的所有密码套件。
    • 在“旧”服务器上启用 DHE/ECDHE 密码套件。
    • 在“旧”服务器上使用 1024 位证书(我还是建议这样做,因为 512 位非常弱)。

    【讨论】:

    • 我无法访问“旧”服务器。我刚刚创建了一个简单的 TCP 客户端应用程序和 TCP 服务器应用程序,它们使用 SSL 来尝试复制问题。如果我禁用此测试系统上使用 DHE 或 ECDHE 的所有密码套件,则服务器应用程序在收到 ClientHello 后会引发异常 - “客户端和服务器无法通信,因为它们不具备通用算法”。这看起来很奇怪,因为客户端和服务器在同一台机器上。
    • 另外,您对我的测试客户端/服务器工作的解释是有道理的,因为 ECDHE 被用于密钥交换。我的理解是否正确,当 Diffie-Hellman 用于密钥交换时,根本不使用证书公钥?
    猜你喜欢
    • 2015-10-20
    • 2021-01-23
    • 2019-02-16
    • 2017-09-19
    • 1970-01-01
    • 2017-02-17
    • 2018-09-02
    • 1970-01-01
    • 2019-08-15
    相关资源
    最近更新 更多