.NET 4.5 中的默认安全协议
Default SecurityProtocol in .NET 4.5
与最多支持 TLS 1.2
的服务器通信的默认安全协议是什么?将 .NET
默认情况下,选择服务器端支持的最高安全协议,还是我必须明确添加这行代码:
System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
除了代码更改之外,还有其他方法可以更改此默认设置吗?
最后,.NET 4.0
是否最多只支持TLS 1.0
?即我必须将客户端项目升级到 4.5 以支持 TLS 1.2
.
我的动机是在客户端删除对 SSLv3
的支持,即使服务器支持它(我已经有一个 powershell 脚本来在机器注册表中禁用它)并支持最高的 TLS 协议服务器支持。
更新:
查看 .NET 4.0
中的 ServicePointManager
class 我看不到 TLS 1.0
和 1.1
的枚举值。在这两个 .NET 4.0/4.5
中,默认值为 SecurityProtocolType.Tls|SecurityProtocolType.Ssl3
。希望在注册表中禁用 SSLv3
不会破坏此默认值。
但是,我决定必须将所有应用程序升级到 .NET 4.5
并显式添加 SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
到所有应用程序的所有引导代码。
这将向各种 api 和服务发出出站请求,以不降级到 SSLv3
并且应该 select 最高级别 TLS
。
这种方法听起来合理还是矫枉过正?我有很多应用程序要更新,我想在未来证明它们,因为我听说甚至 TLS 1.0
可能在不久的将来被一些供应商弃用。
作为向 API 发出出站请求的客户端,在注册表中禁用 SSL3 是否会对 .NET 框架产生影响?我看到默认情况下未启用 TLS 1.1 和 1.2,我们是否必须通过注册表启用它?回复 http://support.microsoft.com/kb/245030。
经过一些调查,我相信注册表设置不会有任何影响,因为它们适用于 IIS(服务器子项)和浏览器(客户端子项)。
抱歉,这个 post 变成了多个问题,后面有 "maybe" 个答案。
.NET 4.0/4.5
中的默认 System.Net.ServicePointManager.SecurityProtocol
是 SecurityProtocolType.Tls|SecurityProtocolType.Ssl3
。
.NET 4.0
最多支持 TLS 1.0
而 .NET 4.5
最多支持 TLS 1.2
但是,如果在同一环境中安装了 .NET 4.5
,则面向 .NET 4.0
的应用程序仍可支持最多 TLS 1.2
。 .NET 4.5
安装在 .NET 4.0
之上,取代 System.dll
。
我已通过观察 fiddler4
流量中设置的正确安全协议并在 .NET 4.0
项目中手动设置枚举值来验证这一点:
ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 |
(SecurityProtocolType)768 | (SecurityProtocolType)3072;
参考:
namespace System.Net
{
[System.Flags]
public enum SecurityProtocolType
{
Ssl3 = 48,
Tls = 192,
Tls11 = 768,
Tls12 = 3072,
}
}
如果您尝试在仅安装了 .NET 4.0
的环境中进行破解,您将得到异常:
Unhandled Exception: System.NotSupportedException: The requested security protocol is not supported.
at System.Net.ServicePointManager.set_SecurityProtocol(SecurityProtocolType v
alue)
但是,我不推荐这个 "hack" 因为未来的补丁等可能会破坏它。*
因此,我决定取消对 SSLv3
支持的最佳途径是:
- 将所有应用程序升级到
.NET 4.5
将以下内容添加到自举代码以覆盖默认和未来证明它:
System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
*如果这个 hack 是错误的,请有人纠正我,但初步测试我发现它有效
您可以覆盖以下注册表中的默认行为:
Key : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1
和
Key : HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1
对于密钥:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319
值:SchUseStrongCrypto
您必须将值设置为 1。
经过一番努力,注册表更改机制对我有用。实际上我的应用程序是 运行 作为 32 位。所以我不得不更改路径下的值。
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319
值类型需要是DWORD且值大于0。最好使用1。
创建一个具有 .reg
扩展名和以下内容的文本文件:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
或从以下来源下载:
双击安装...
我发现当我只指定 TLS 1.2 时它仍然会向下协商到 1.1。
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
我已经在我的 .net 4.5 网络应用程序的 Global.asax 启动方法中指定了它。
一些对其他答案发表评论的人指出,将 System.Net.ServicePointManager.SecurityProtocol
设置为特定值意味着您的应用将无法利用未来可能成为默认值的 TLS 版本.NET 的更新。不要指定固定的协议列表,而是执行以下操作:
对于 .NET 4.7 或更高版本,请勿设置 System.Net.ServicePointManager.SecurityProtocol
。默认值 (SecurityProtocolType.SystemDefault
) 将允许操作系统使用它知道并已配置的任何版本,包括在创建应用程序时可能不存在的任何新版本。
对于较早版本的 .NET Framework, 您可以改为打开或关闭您知道和关心的协议,让其他协议保持原样。
要在不影响其他协议的情况下启用 TLS 1.1 和 1.2:
System.Net.ServicePointManager.SecurityProtocol |=
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
注意使用 |=
打开这些标志而不关闭其他标志。
要在不影响其他协议的情况下关闭 SSL3:
System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
硬编码 ServicePointManager.SecurityProtocol
或显式 SchUseStrongCrypto 密钥的替代方法,如上所述:
您可以通过 SystemDefaultTlsVersions 键告诉 .NET 使用默认的 SCHANNEL 设置,
例如:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001
为了完整起见,这里是一个设置上述注册表项的 Powershell 脚本:
new-itemproperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord";
new-itemproperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord"
当我的客户将 TLS 从 1.0 升级到 1.2 时,我遇到了问题。
我的应用程序在服务器上使用 .net Framework 3.5 和 运行。所以我通过这种方式修复它:
- 修复程序
在调用 HttpWebRequest.GetResponse() 之前添加此命令:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolTypeExtensions.Tls11 | SecurityProtocolTypeExtensions.Tls12;
通过添加 2 个新 类 来扩展 2 个 DLL:System.Net 和 System.Security.Authentication
namespace System.Net
{
using System.Security.Authentication;
public static class SecurityProtocolTypeExtensions
{
public const SecurityProtocolType Tls12 = (SecurityProtocolType)SslProtocolsExtensions.Tls12;
public const SecurityProtocolType Tls11 = (SecurityProtocolType)SslProtocolsExtensions.Tls11;
public const SecurityProtocolType SystemDefault = (SecurityProtocolType)0;
}
}
namespace System.Security.Authentication
{
public static class SslProtocolsExtensions
{
public const SslProtocols Tls12 = (SslProtocols)0x00000C00;
public const SslProtocols Tls11 = (SslProtocols)0x00000300;
}
}
- 更新 Microsoft 批次
下载批次:
- 对于 windows 2008 R2:windows6.1-kb3154518-x64.msu
- 对于 windows 2012
R2:windows8.1-kb3154520-x64.msu
有关下载批次和更多详细信息,您可以在此处查看:
这个问题的最佳解决方案似乎是至少升级到 .NET 4.6 或更高版本,它将自动选择强协议和强密码。
如果不能升级到.NET 4.6,建议设置
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
并使用注册表设置:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 – SchUseStrongCrypto = DWORD of 1
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319 – SchUseStrongCrypto = DWORD of 1
导致使用 TLS 1.0 和强密码以外的东西。
在我的测试中,只有 Wow6432Node 中的设置有所不同,即使我的测试应用程序是为 Any CPU.
构建的
以下代码将:
- 打印启用协议
- 打印可用协议
- 如果平台支持,则启用 TLS1.2,如果未启用,则开始于
- 禁用 SSL3(如果启用)
- 打印最终结果
常数:
- 48 是 SSL3
- 192 是 TLS1
- 768 是 TLS1.1
- 3072 是 TLS1.2
其他协议不受影响。这使得它与未来的协议(Tls1.3 等)兼容。
代码
// print initial status
Console.WriteLine("Runtime: " + System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion);
Console.WriteLine("Enabled protocols: " + ServicePointManager.SecurityProtocol);
Console.WriteLine("Available protocols: ");
Boolean platformSupportsTls12 = false;
foreach (SecurityProtocolType protocol in Enum.GetValues(typeof(SecurityProtocolType))) {
Console.WriteLine(protocol.GetHashCode());
if (protocol.GetHashCode() == 3072){
platformSupportsTls12 = true;
}
}
Console.WriteLine("Is Tls12 enabled: " + ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072));
// enable Tls12, if possible
if (!ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072)){
if (platformSupportsTls12){
Console.WriteLine("Platform supports Tls12, but it is not enabled. Enabling it now.");
ServicePointManager.SecurityProtocol |= (SecurityProtocolType)3072;
} else {
Console.WriteLine("Platform does not supports Tls12.");
}
}
// disable ssl3
if (ServicePointManager.SecurityProtocol.HasFlag(SecurityProtocolType.Ssl3)) {
Console.WriteLine("Ssl3SSL3 is enabled. Disabling it now.");
// disable SSL3. Has no negative impact if SSL3 is already disabled. The enclosing "if" if just for illustration.
System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
}
Console.WriteLine("Enabled protocols: " + ServicePointManager.SecurityProtocol);
输出
Runtime: 4.7.2114.0
Enabled protocols: Ssl3, Tls
Available protocols:
0
48
192
768
3072
Is Tls12 enabled: False
Platform supports Tls12, but it is not enabled. Enabling it now.
Ssl3 is enabled. Disabling it now.
Enabled protocols: Tls, Tls12
我 运行 在 .NET 4.5.2 下,我对这些答案中的任何一个都不满意。当我与支持 TLS 1.2 的系统交谈时,看到 SSL3、TLS 1.0 和 TLS 1.1 都已损坏且使用不安全,我不想启用这些协议。在 .NET 4.5.2 下,SSL3 和 TLS 1.0 协议都默认启用,我可以通过检查 ServicePointManager.SecurityProtocol
在代码中看到这一点。在 .NET 4.7 下,有新的 SystemDefault
协议模式,它明确地将协议选择移交给 OS,我认为依靠注册表或其他系统配置设置是合适的。然而,.NET 4.5.2 似乎不支持它。为了编写向前兼容的代码,即使将来 TLS 1.2 不可避免地被破坏,或者当我升级到 .NET 4.7+ 并将选择合适协议的更多责任移交给 OS,我采用了如下代码:
SecurityProtocolType securityProtocols = ServicePointManager.SecurityProtocol;
if (securityProtocols.HasFlag(SecurityProtocolType.Ssl3) || securityProtocols.HasFlag(SecurityProtocolType.Tls) || securityProtocols.HasFlag(SecurityProtocolType.Tls11))
{
securityProtocols &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11);
if (securityProtocols == 0)
{
securityProtocols |= SecurityProtocolType.Tls12;
}
ServicePointManager.SecurityProtocol = securityProtocols;
}
此代码将检测何时启用已知的不安全协议,在这种情况下,我们将删除这些不安全的协议。如果没有其他显式协议,我们将强制启用 TLS 1.2,这是目前 .NET 支持的唯一已知安全协议。这段代码是向前兼容的,因为它将考虑到它不知道将来会添加的新协议类型,而且它也可以很好地适应 .NET 4.7 中的新 SystemDefault
状态,这意味着我赢了以后不必重新访问此代码。我强烈建议采用这样的方法,而不是无条件地对任何特定的安全协议状态进行硬编码,否则您将不得不重新编译并用新版本替换客户端,以便在 TLS 1.2 时升级到新的安全协议不可避免地会被破坏,或者更有可能的是,您将不得不在服务器上启用现有的不安全协议多年,从而使您的组织成为攻击目标。
Microsoft 最近发布了关于此的最佳实践。 https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls
总结
目标 .Net Framework 4.7,删除任何设置 SecurityProtocol 的代码,因此 OS 将确保您使用最安全的解决方案。
注意:您还需要确保 OS.
支持并启用最新版本的 TLS
OS TLS 1.2 support
Windows 10 \_ Supported, and enabled by default.
Windows Server 2016 /
Windows 8.1 \_ Supported, and enabled by default.
Windows Server 2012 R2 /
Windows 8.0 \_ Supported, and enabled by default.
Windows Server 2012 /
Windows 7 SP1 \_ Supported, but not enabled by default*.
Windows Server 2008 R2 SP1 /
Windows Server 2008 - Support for TLS 1.2 and TLS 1.1 requires an update. See Update to add support for TLS 1.1 and TLS 1.2 in Windows Server 2008 SP2.
Windows Vista - Not supported.
* To enable TLS1.2 via the registry see https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-12
Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS1.2\Server
Property: Enabled
Type: REG_DWORD
Value: 1
Property: DisabledByDefault
Type: REG_DWORD
Value: 0
Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS1.2\Client
Property: Enabled
Type: REG_DWORD
Value: 1
Property: DisabledByDefault
Type: REG_DWORD
Value: 0
有关更多信息和旧框架,请参阅 MS link。
根据Transport Layer Security (TLS) best practices with the .NET Framework:
为确保 .NET Framework 应用程序保持安全,TLS 版本应不 进行硬编码。 而是设置注册表项:SystemDefaultTlsVersions
和 SchUseStrongCrypto
:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
如果您可以使用 .NET 4.7.1 或更高版本,它将使用 TLS 1.2 作为基于操作系统功能的最低协议。
根据 Microsoft 的建议:
To ensure .NET Framework applications remain secure, the TLS version should not be hardcoded. .NET Framework applications should use the TLS version the operating system (OS) supports.
有两种可能的情况,
如果您在 .net framework 4.5 或更低版本上应用程序 运行,并且您可以轻松地将新代码部署到生产中,那么您可以使用以下解决方案。
您可以在进行 api 调用之前添加以下代码行,
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5
如果您无法部署新代码并且想使用生产中存在的相同代码来解决,那么您有两个选择。
选项 1 :
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
然后创建一个扩展名为 .reg 的文件并安装。
注意: 此设置将应用于注册表级别,适用于该计算机上存在的所有应用程序,如果您只想限制为单个应用程序,则可以使用 Option 2
选项 2 :这可以通过更改配置文件中的一些配置设置来完成。
您可以在配置文件中添加其中之一。
<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>
</runtime>
或
<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false"
</runtime>
与最多支持 TLS 1.2
的服务器通信的默认安全协议是什么?将 .NET
默认情况下,选择服务器端支持的最高安全协议,还是我必须明确添加这行代码:
System.Net.ServicePointManager.SecurityProtocol =
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
除了代码更改之外,还有其他方法可以更改此默认设置吗?
最后,.NET 4.0
是否最多只支持TLS 1.0
?即我必须将客户端项目升级到 4.5 以支持 TLS 1.2
.
我的动机是在客户端删除对 SSLv3
的支持,即使服务器支持它(我已经有一个 powershell 脚本来在机器注册表中禁用它)并支持最高的 TLS 协议服务器支持。
更新:
查看 .NET 4.0
中的 ServicePointManager
class 我看不到 TLS 1.0
和 1.1
的枚举值。在这两个 .NET 4.0/4.5
中,默认值为 SecurityProtocolType.Tls|SecurityProtocolType.Ssl3
。希望在注册表中禁用 SSLv3
不会破坏此默认值。
但是,我决定必须将所有应用程序升级到 .NET 4.5
并显式添加 SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
到所有应用程序的所有引导代码。
这将向各种 api 和服务发出出站请求,以不降级到 SSLv3
并且应该 select 最高级别 TLS
。
这种方法听起来合理还是矫枉过正?我有很多应用程序要更新,我想在未来证明它们,因为我听说甚至 TLS 1.0
可能在不久的将来被一些供应商弃用。
作为向 API 发出出站请求的客户端,在注册表中禁用 SSL3 是否会对 .NET 框架产生影响?我看到默认情况下未启用 TLS 1.1 和 1.2,我们是否必须通过注册表启用它?回复 http://support.microsoft.com/kb/245030。
经过一些调查,我相信注册表设置不会有任何影响,因为它们适用于 IIS(服务器子项)和浏览器(客户端子项)。
抱歉,这个 post 变成了多个问题,后面有 "maybe" 个答案。
.NET 4.0/4.5
中的默认 System.Net.ServicePointManager.SecurityProtocol
是 SecurityProtocolType.Tls|SecurityProtocolType.Ssl3
。
.NET 4.0
最多支持 TLS 1.0
而 .NET 4.5
最多支持 TLS 1.2
但是,如果在同一环境中安装了 .NET 4.5
,则面向 .NET 4.0
的应用程序仍可支持最多 TLS 1.2
。 .NET 4.5
安装在 .NET 4.0
之上,取代 System.dll
。
我已通过观察 fiddler4
流量中设置的正确安全协议并在 .NET 4.0
项目中手动设置枚举值来验证这一点:
ServicePointManager.SecurityProtocol = (SecurityProtocolType)192 |
(SecurityProtocolType)768 | (SecurityProtocolType)3072;
参考:
namespace System.Net
{
[System.Flags]
public enum SecurityProtocolType
{
Ssl3 = 48,
Tls = 192,
Tls11 = 768,
Tls12 = 3072,
}
}
如果您尝试在仅安装了 .NET 4.0
的环境中进行破解,您将得到异常:
Unhandled Exception: System.NotSupportedException: The requested security protocol is not supported. at System.Net.ServicePointManager.set_SecurityProtocol(SecurityProtocolType v alue)
但是,我不推荐这个 "hack" 因为未来的补丁等可能会破坏它。*
因此,我决定取消对 SSLv3
支持的最佳途径是:
- 将所有应用程序升级到
.NET 4.5
将以下内容添加到自举代码以覆盖默认和未来证明它:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
*如果这个 hack 是错误的,请有人纠正我,但初步测试我发现它有效
您可以覆盖以下注册表中的默认行为:
Key : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1
和
Key : HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Type: REG_DWORD
Data : 1
对于密钥:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 值:SchUseStrongCrypto
您必须将值设置为 1。
经过一番努力,注册表更改机制对我有用。实际上我的应用程序是 运行 作为 32 位。所以我不得不更改路径下的值。
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319
值类型需要是DWORD且值大于0。最好使用1。
创建一个具有 .reg
扩展名和以下内容的文本文件:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
或从以下来源下载:
双击安装...
我发现当我只指定 TLS 1.2 时它仍然会向下协商到 1.1。
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
我已经在我的 .net 4.5 网络应用程序的 Global.asax 启动方法中指定了它。
一些对其他答案发表评论的人指出,将 System.Net.ServicePointManager.SecurityProtocol
设置为特定值意味着您的应用将无法利用未来可能成为默认值的 TLS 版本.NET 的更新。不要指定固定的协议列表,而是执行以下操作:
对于 .NET 4.7 或更高版本,请勿设置 System.Net.ServicePointManager.SecurityProtocol
。默认值 (SecurityProtocolType.SystemDefault
) 将允许操作系统使用它知道并已配置的任何版本,包括在创建应用程序时可能不存在的任何新版本。
对于较早版本的 .NET Framework, 您可以改为打开或关闭您知道和关心的协议,让其他协议保持原样。
要在不影响其他协议的情况下启用 TLS 1.1 和 1.2:
System.Net.ServicePointManager.SecurityProtocol |=
SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
注意使用 |=
打开这些标志而不关闭其他标志。
要在不影响其他协议的情况下关闭 SSL3:
System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
硬编码 ServicePointManager.SecurityProtocol
或显式 SchUseStrongCrypto 密钥的替代方法,如上所述:
您可以通过 SystemDefaultTlsVersions 键告诉 .NET 使用默认的 SCHANNEL 设置,
例如:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001
为了完整起见,这里是一个设置上述注册表项的 Powershell 脚本:
new-itemproperty -path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord";
new-itemproperty -path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name "SchUseStrongCrypto" -Value 1 -PropertyType "DWord"
当我的客户将 TLS 从 1.0 升级到 1.2 时,我遇到了问题。 我的应用程序在服务器上使用 .net Framework 3.5 和 运行。所以我通过这种方式修复它:
- 修复程序
在调用 HttpWebRequest.GetResponse() 之前添加此命令:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolTypeExtensions.Tls11 | SecurityProtocolTypeExtensions.Tls12;
通过添加 2 个新 类 来扩展 2 个 DLL:System.Net 和 System.Security.Authentication
namespace System.Net
{
using System.Security.Authentication;
public static class SecurityProtocolTypeExtensions
{
public const SecurityProtocolType Tls12 = (SecurityProtocolType)SslProtocolsExtensions.Tls12;
public const SecurityProtocolType Tls11 = (SecurityProtocolType)SslProtocolsExtensions.Tls11;
public const SecurityProtocolType SystemDefault = (SecurityProtocolType)0;
}
}
namespace System.Security.Authentication
{
public static class SslProtocolsExtensions
{
public const SslProtocols Tls12 = (SslProtocols)0x00000C00;
public const SslProtocols Tls11 = (SslProtocols)0x00000300;
}
}
- 更新 Microsoft 批次
下载批次:
- 对于 windows 2008 R2:windows6.1-kb3154518-x64.msu
- 对于 windows 2012 R2:windows8.1-kb3154520-x64.msu
有关下载批次和更多详细信息,您可以在此处查看:
这个问题的最佳解决方案似乎是至少升级到 .NET 4.6 或更高版本,它将自动选择强协议和强密码。
如果不能升级到.NET 4.6,建议设置
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
并使用注册表设置:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft.NETFramework\v4.0.30319 – SchUseStrongCrypto = DWORD of 1 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft.NETFramework\v4.0.30319 – SchUseStrongCrypto = DWORD of 1
导致使用 TLS 1.0 和强密码以外的东西。
在我的测试中,只有 Wow6432Node 中的设置有所不同,即使我的测试应用程序是为 Any CPU.
构建的以下代码将:
- 打印启用协议
- 打印可用协议
- 如果平台支持,则启用 TLS1.2,如果未启用,则开始于
- 禁用 SSL3(如果启用)
- 打印最终结果
常数:
- 48 是 SSL3
- 192 是 TLS1
- 768 是 TLS1.1
- 3072 是 TLS1.2
其他协议不受影响。这使得它与未来的协议(Tls1.3 等)兼容。
代码
// print initial status
Console.WriteLine("Runtime: " + System.Diagnostics.FileVersionInfo.GetVersionInfo(typeof(int).Assembly.Location).ProductVersion);
Console.WriteLine("Enabled protocols: " + ServicePointManager.SecurityProtocol);
Console.WriteLine("Available protocols: ");
Boolean platformSupportsTls12 = false;
foreach (SecurityProtocolType protocol in Enum.GetValues(typeof(SecurityProtocolType))) {
Console.WriteLine(protocol.GetHashCode());
if (protocol.GetHashCode() == 3072){
platformSupportsTls12 = true;
}
}
Console.WriteLine("Is Tls12 enabled: " + ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072));
// enable Tls12, if possible
if (!ServicePointManager.SecurityProtocol.HasFlag((SecurityProtocolType)3072)){
if (platformSupportsTls12){
Console.WriteLine("Platform supports Tls12, but it is not enabled. Enabling it now.");
ServicePointManager.SecurityProtocol |= (SecurityProtocolType)3072;
} else {
Console.WriteLine("Platform does not supports Tls12.");
}
}
// disable ssl3
if (ServicePointManager.SecurityProtocol.HasFlag(SecurityProtocolType.Ssl3)) {
Console.WriteLine("Ssl3SSL3 is enabled. Disabling it now.");
// disable SSL3. Has no negative impact if SSL3 is already disabled. The enclosing "if" if just for illustration.
System.Net.ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
}
Console.WriteLine("Enabled protocols: " + ServicePointManager.SecurityProtocol);
输出
Runtime: 4.7.2114.0
Enabled protocols: Ssl3, Tls
Available protocols:
0
48
192
768
3072
Is Tls12 enabled: False
Platform supports Tls12, but it is not enabled. Enabling it now.
Ssl3 is enabled. Disabling it now.
Enabled protocols: Tls, Tls12
我 运行 在 .NET 4.5.2 下,我对这些答案中的任何一个都不满意。当我与支持 TLS 1.2 的系统交谈时,看到 SSL3、TLS 1.0 和 TLS 1.1 都已损坏且使用不安全,我不想启用这些协议。在 .NET 4.5.2 下,SSL3 和 TLS 1.0 协议都默认启用,我可以通过检查 ServicePointManager.SecurityProtocol
在代码中看到这一点。在 .NET 4.7 下,有新的 SystemDefault
协议模式,它明确地将协议选择移交给 OS,我认为依靠注册表或其他系统配置设置是合适的。然而,.NET 4.5.2 似乎不支持它。为了编写向前兼容的代码,即使将来 TLS 1.2 不可避免地被破坏,或者当我升级到 .NET 4.7+ 并将选择合适协议的更多责任移交给 OS,我采用了如下代码:
SecurityProtocolType securityProtocols = ServicePointManager.SecurityProtocol;
if (securityProtocols.HasFlag(SecurityProtocolType.Ssl3) || securityProtocols.HasFlag(SecurityProtocolType.Tls) || securityProtocols.HasFlag(SecurityProtocolType.Tls11))
{
securityProtocols &= ~(SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11);
if (securityProtocols == 0)
{
securityProtocols |= SecurityProtocolType.Tls12;
}
ServicePointManager.SecurityProtocol = securityProtocols;
}
此代码将检测何时启用已知的不安全协议,在这种情况下,我们将删除这些不安全的协议。如果没有其他显式协议,我们将强制启用 TLS 1.2,这是目前 .NET 支持的唯一已知安全协议。这段代码是向前兼容的,因为它将考虑到它不知道将来会添加的新协议类型,而且它也可以很好地适应 .NET 4.7 中的新 SystemDefault
状态,这意味着我赢了以后不必重新访问此代码。我强烈建议采用这样的方法,而不是无条件地对任何特定的安全协议状态进行硬编码,否则您将不得不重新编译并用新版本替换客户端,以便在 TLS 1.2 时升级到新的安全协议不可避免地会被破坏,或者更有可能的是,您将不得不在服务器上启用现有的不安全协议多年,从而使您的组织成为攻击目标。
Microsoft 最近发布了关于此的最佳实践。 https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls
总结
目标 .Net Framework 4.7,删除任何设置 SecurityProtocol 的代码,因此 OS 将确保您使用最安全的解决方案。
注意:您还需要确保 OS.
支持并启用最新版本的 TLSOS TLS 1.2 support
Windows 10 \_ Supported, and enabled by default.
Windows Server 2016 /
Windows 8.1 \_ Supported, and enabled by default.
Windows Server 2012 R2 /
Windows 8.0 \_ Supported, and enabled by default.
Windows Server 2012 /
Windows 7 SP1 \_ Supported, but not enabled by default*.
Windows Server 2008 R2 SP1 /
Windows Server 2008 - Support for TLS 1.2 and TLS 1.1 requires an update. See Update to add support for TLS 1.1 and TLS 1.2 in Windows Server 2008 SP2.
Windows Vista - Not supported.
* To enable TLS1.2 via the registry see https://docs.microsoft.com/en-us/windows-server/security/tls/tls-registry-settings#tls-12
Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS1.2\Server
Property: Enabled
Type: REG_DWORD
Value: 1
Property: DisabledByDefault
Type: REG_DWORD
Value: 0
Path: HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS1.2\Client
Property: Enabled
Type: REG_DWORD
Value: 1
Property: DisabledByDefault
Type: REG_DWORD
Value: 0
有关更多信息和旧框架,请参阅 MS link。
根据Transport Layer Security (TLS) best practices with the .NET Framework:
为确保 .NET Framework 应用程序保持安全,TLS 版本应不 进行硬编码。 而是设置注册表项:SystemDefaultTlsVersions
和 SchUseStrongCrypto
:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SystemDefaultTlsVersions"=dword:00000001
"SchUseStrongCrypto"=dword:00000001
如果您可以使用 .NET 4.7.1 或更高版本,它将使用 TLS 1.2 作为基于操作系统功能的最低协议。 根据 Microsoft 的建议:
To ensure .NET Framework applications remain secure, the TLS version should not be hardcoded. .NET Framework applications should use the TLS version the operating system (OS) supports.
有两种可能的情况,
如果您在 .net framework 4.5 或更低版本上应用程序 运行,并且您可以轻松地将新代码部署到生产中,那么您可以使用以下解决方案。
您可以在进行 api 调用之前添加以下代码行,
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // .NET 4.5
如果您无法部署新代码并且想使用生产中存在的相同代码来解决,那么您有两个选择。
选项 1 :
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
然后创建一个扩展名为 .reg 的文件并安装。
注意: 此设置将应用于注册表级别,适用于该计算机上存在的所有应用程序,如果您只想限制为单个应用程序,则可以使用 Option 2
选项 2 :这可以通过更改配置文件中的一些配置设置来完成。 您可以在配置文件中添加其中之一。
<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>
</runtime>
或
<runtime>
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false"
</runtime>