通过


.NET Framework 中的传输层安全性 (TLS) 最佳做法

注意

本页包含 .NET Framework TLS 信息。 如果你要查找 .NET TLS 信息,请参阅:TLS /SSL 最佳做法

.NET Framework 支持使用传输层安全性 (TLS) 协议来保护网络通信。

什么是传输层安全性 (TLS)?

警告

RFC8996 已弃用 TLS 1.0 和 1.1。 本文档仅涵盖 TLS 1.2 和 TLS 1.3。

传输层安全性 (TLS) 协议是最新版本的行业标准,旨在帮助保护通过 Internet 传输的信息的私密性。 TLS 1.3 标准与以前版本相比在安全性方面有了很多提升。 文本介绍了如何保护使用 TLS 协议的 .NET Framework 应用程序安全的建议。

谁可以从本文档中受益?

.NET Framework 中的 TLS 支持

由于 .NET Framework 依赖于 Windows 上的 Schannel,因此可以协商哪些版本以及要使用哪个版本将取决于操作系统。

下面是更新的示例表,其中显示了操作系统版本和 .NET Framework 目标版本的不同组合所支持的最高 TLS 版本:

.NET Framework 目标版本 Windows 10操作系统 Windows 11
3.5 TLS 1.2 TLS 1.2
4.6.2 TLS 1.2 TLS 1.3
4.7 TLS 1.2 TLS 1.3
4.7.1 TLS 1.2 TLS 1.3
4.7.2 TLS 1.2 TLS 1.3
4.8 TLS 1.2 TLS 1.3
4.8.1 TLS 1.2 TLS 1.3

有关详细信息,请参阅 Schannel 中的 TLS 协议版本支持

建议

  • 对于 TLS 1.3,面向 .NET Framework 4.8 或更高版本。 查看审核代码部分,了解如何验证你的 target framework
  • 不要显式指定 TLS 版本,即不要使用带有显式 SslStream 参数的 SslProtocols 方法重载。
    • 这样,你的代码将让操作系统决定 TLS 版本。
    • 如果必须设置 ServicePointManager.SecurityProtocol,则将其设置为 SecurityProtocolType.SystemDefault。 这也将使用操作系统默认值。
    • 必须使用具有显式SslStream参数的SslProtocols方法重载时,请将SslProtocols.SystemDefault作为参数传递。 这也将使用操作系统默认值。
  • 执行全面的代码审核,以验证你是否未显式指定 TLS 或 SSL 版本。

警告

请勿使用 SslProtocols.Default,因为它将 TLS 版本设置为已过时的 SSL3 和 TLS 1.0。

当你的应用让操作系统来选择 TLS 版本时:

  • 它将会自动利用将来添加的新 TLS 协议。
  • OS 会阻止发现不安全的协议(例如 SSL3 和 TLS 1.0)。

本文说明了如何启用可用于应用所面向并在其上运行的 .NET Framework 版本的最强安全性。 当应用显式设置安全协议和版本时,它将选择退出任何其他替代项,并选择退出 .NET Framework 和操作系统默认行为。 如果你希望应用能够协商 TLS 1.3 连接,请显式设置为较低的 TLS 版本,以阻止 TLS 1.3 连接。

如果你不得不显式指定协议版本,我们强烈建议指定 TLS 1.2 或 TLS 1.3(这些是 currently considered secure)。 有关标识和删除 TLS 1.0 依赖项的指南,请下载解决 TLS 1.0 问题白皮书。

WCF 支持使用 TLS 1.2 作为 .NET Framework 4.7 中的默认设置。 从 .NET Framework 4.7.1 开始,WCF 默认为操作系统配置的版本。 如果某个应用程序使用 SslProtocols.None 显式配置,则在使用 NetTcp 传输时,WCF 将使用操作系统默认设置。

你可以在 GitHub 问题 .NET Framework 中的传输层安全性 (TLS) 最佳做法中提问有关此文档的问题。

审核代码并对代码进行更改

对于 ASP.NET 应用程序,请检查 web.config 的 <system.web><httpRuntime targetFramework> 元素,以验证你使用的是否为 .NET Framework 的目标版本

有关 Windows 窗体和其他应用程序,请参阅如何:定位到 .NET Framework 的特定版本

使用以下部分验证你未使用特定 TLS 或 SSL 版本。

显式设置安全协议

如果必须显式设置安全协议而不是让 .NET 或操作系统选择安全协议,请选择以下协议:

  • 对于 .NET Framework 3.5:TLS 1.2
  • 对于 .NET Framework 4.6.2 或更高版本:TLS 1.3

如果在 enum 中找不到指定的协议,可以将其添加为扩展文件。 请参见下图:

SslProtocolExtensions.cs

namespace System.Security.Authentication
{
    public static class SslProtocolsExtensions
    {
        // For .NET Framework 3.5
        public const SslProtocols Tls12 = (SslProtocols)3072;
        // For .NET Framework 4.6.2 and later
        public const SslProtocols Tls13 = (SslProtocols)12288;
    }
}

SecurityProtocolExtensions.cs

using System.Security.Authentication;

namespace System.Net
{
    public static class SecurityProtocolTypeExtensions
    {
        // For .NET Framework 3.5
        public const SecurityProtocolType Tls12 = (SecurityProtocolType)SslProtocolsExtensions.Tls12;
        // For .NET Framework 4.6.2 and later
        public const SecurityProtocolType Tls13 = (SecurityProtocolType)SslProtocolsExtensions.Tls13;
    }
}

有关详细信息,请参阅在 Windows 8.1 和 Windows Server 2012 R2 上的 .NET Framework 3.5 中包含对 TLS 系统默认版本的支持

对于 System.Net API(HttpClient、SslStream)

以下部分演示如何将应用程序配置为在面向 .NET Framework 4.7 或更高版本时使用 TLS(即 TLS 1.2 和 TLS 1.3)的“当前已考虑的安全版本”。

对于 HttpClient 和 HttpWebRequest

ServicePointManager 使用 OS 中配置的默认安全协议。 若要获取默认操作系统选择,如有可能,请不要设置 ServicePointManager.SecurityProtocol 属性的值,该值默认为 SecurityProtocolType.SystemDefault

由于该 SecurityProtocolType.SystemDefault 设置导致 ServicePointManager 使用操作系统配置的默认安全协议,因此应用程序可能会根据运行它的操作系统以不同的方式运行。 例如,Windows 10 使用 TLS 1.2,而 Windows 11 使用 TLS 1.3。

对于 SslStream

SslStream 默认为 OS 选择的安全协议和版本。 若要获取默认操作系统最佳选择,如有可能,请不要使用采取显式 SslStream 参数的 SslProtocols 的方法重载。 否则传递 SslProtocols.None。 建议不要使用 Default;设置 SslProtocols.Default 会强制使用 SSL 3.0 /TLS 1.0,而不使用 TLS 1.2。

不要设置 SecurityProtocol 属性的值(针对 HTTP 网络)。

不要使用涉及显式 SslStream 参数的 SslProtocols 方法重载(用于 TCP 套接字网络)。 当你将应用重定向到 .NET Framework 4.7 或更高版本时,将遵循最佳做法建议。

对于 WCF 应用

以下部分演示如何将应用程序配置为使用 TLS(即 TLS 1.2 和 TLS 1.3)的“当前已考虑的安全版本”。

使用具有证书凭据的传输安全性的 TCP 传输

WCF 使用与 .NET Framework 的其余部分相同的网络堆栈。

如果你的目标为 4.7.1,则 WCF 默认地配置为由操作系统选择最佳安全协议,除非另有显式配置。

  • 在你的应用程序配置文件中。
  • 或者,在你的源代码中的应用程序中。

默认情况下,.NET Framework 4.7 和更高版本将配置为使用 TLS 1.2,并允许使用 TLS 1.1 或 TLS 1.0 进行连接。 通过将你的绑定配置为使用 SslProtocols.None 来配置 WCF,以允许操作系统选择最佳安全协议。 你可以对此 SslProtocols进行设置。 SslProtocols.None 可以从 Transport 中进行访问。 NetTcpSecurity.Transport 可以从 Security 中进行访问。

如果你使用自定义绑定:

  • 通过将 SslProtocols 设置为使用 SslProtocols.None 来配置 WCF,以允许操作系统选择最佳安全协议。
  • 或者,配置在配置路径 中使用的协议。

如果您使用自定义绑定,并通过配置来设置 WCF 绑定,请在配置路径中设置所使用的协议。

使用具有证书凭据的消息安全性

默认情况下,.NET Framework 4.7 和更高版本使用 SecurityProtocol 属性中指定的协议。 当 AppContextSwitchSwitch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols 设置为 true 时,WCF 将选择最佳协议(最高至 TLS 1.0)。

通过 AppContext 开关配置安全性

如果应用面向或运行 .NET Framework 4.6.2 或更高版本,则本部分中介绍的 AppContext 开关相关。 无论是默认设置还是显式设置,如果可能,开关应设为 false。 如果要通过一个或两个交换机配置安全性,请不要在代码中指定安全协议值;这样做会覆盖开关。

无论你使用 HTTP 网络 (ServicePointManager) 还是使用 TCP 套接字网络 (SslStream),开关都具有相同的效果。

Switch.System.Net.DontEnableSchUseStrongCrypto

false 的值为 Switch.System.Net.DontEnableSchUseStrongCrypto 将导致你的应用使用强加密。 当 false 的值为 DontEnableSchUseStrongCrypto 时,将使用更安全的网络协议(TLS 1.2 和 TLS 1.1),并阻止不安全的协议的使用。 有关详细信息,请参阅 SCH_USE_STRONG_CRYPTO 标志。 值为 true 会停用应用程序的强加密功能。 此交换机仅影响应用程序中的客户端(传出)连接。

如果你的应用面向 .NET Framework 4.6.2 或更高版本,则此开关默认为 false。 这是我们建议使用的安全默认值。 如果你的应用在 .NET Framework 4.6.2 上运行,但面向更低版本,则开关默认为 true。 在这种情况下,应显式将其设置为 false

如果需要连接到不支持强加密且无法升级的旧服务,则 DontEnableSchUseStrongCrypto 的值只能为 true

Switch.System.Net.DontEnableSystemDefaultTlsVersions

false 的值为 Switch.System.Net.DontEnableSystemDefaultTlsVersions 将导致你的应用允许操作系统选择协议。 值为 true 将导致你的应用使用由 .NET Framework 选取的协议。

如果你的应用面向 .NET Framework 4.7 或更高版本,则此开关默认为 false。 这是我们建议使用的安全默认值。 如果你的应用在 .NET Framework 4.7 或更高版本上运行,但面向较早版本,则开关默认为 true。 在这种情况下,应显式将其设置为 false

在 Windows 注册表中配置 Schannel 协议

可以使用注册表对客户端或服务器应用协商的协议进行精细控制。 你的应用的网络将遍历 Schannel(它是安全通道的另一个名称)。 通过配置 Schannel,可以配置你的应用的行为。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols 注册表项开始。 在该注册表项下,您可以在集合 TLS 1.2TLS 1.3 中创建任何子项。 在每个子项下,可以创建子项 Client 和/或 Server。 在 ClientServer 下,可创建 DWORD 值 DisabledByDefault(0 或 1)和 Enabled(0 或 1)。

有关详细信息,请参阅:TLS 注册表设置 - Schannel

SCH_USE_STRONG_CRYPTO 标志

启用时(默认情况下或者通过AppContext开关启用),当应用启动与服务器的 TLS 连接时,.NET Framework 会使用SCH_USE_STRONG_CRYPTO标志。 .NET Framework 将标志传递到 Schannel,以指示它禁用已知弱加密算法、密码套件和 TLS/SSL 协议版本(否则,可能会启用该协议以获得更好的互操作性)。 有关详细信息,请参见:

在显式使用 SCH_USE_STRONG_CRYPTOSchannelTls11Tls12 枚举值时,SecurityProtocolType 标志还会传递到客户端(传出)连接的 SslProtocols。 标志 SCH_USE_STRONG_CRYPTO 仅用于应用程序在其中充当客户端角色的连接。 当应用程序通过配置计算机范围的 Schannel 注册表设置来充当服务器角色时,你可以禁用弱协议和算法。