[英]TLS1.2 negotiation fails within a 4.5.1 application when .net Framework 4.7.2 is installed
我们目前遇到基于网络的应用程序的问题。 它在任何操作系统win2k12 R2和IIS上都运行良好。 该应用程序是针对.net Framework 4.5.1编译的。 虽然我们知道更新的.NET Framework版本,但由于几个不方便的第三方依赖性,我们很难进行更新。
最近,微软发布了隐式安装.NET Framework 4.7.2的KB。 安装了这些更新的客户现在面临一个重大问题。
以下代码虽然过于简单,但包含所有必要的信息。
private HttpWebResponse GetResponse(HttpWebRequest httpWebRequest)
{
lock (Statics._lockObject)
{
HttpWebResponse httpResponse = null;
SecurityProtocolType tempProtocol = ServicePointManager.SecurityProtocol;
//ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // Magic Number equals SecurityProtocolType.Tls1.2
ServicePointManager.ServerCertificateValidationCallback = CheckSSL;
try
{
httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
}
finally
{
ServicePointManager.SecurityProtocol = tempProtocol;
ServicePointManager.ServerCertificateValidationCallback = null;
}
return httpResponse;
}
}
在安装了.NET Framework 4.7.2的系统上执行此操作时,我们在GetResponse()
调用中收到以下错误:
“基础连接已关闭:发送时发生意外错误。”
at System.Net.HttpWebRequest.GetResponse()
和内在的例外:
“身份验证失败,因为远程方已关闭传输流。”
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result) at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size) at System.Net.ConnectStream.WriteHeaders(Boolean async)
卸载前面提到的KB,因此,.NET Framework 4.7.2确实有帮助,但对我们的客户群来说是不可取的。
到目前为止,我们尝试的其他选项是:
设置注册表项如下: [HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\.NETFramework\\v4.0.30319] "SystemDefaultTlsVersions"=dword:00000001 "SchUseStrongCrypto"=dword:00000001
同时在ServicePointManager.SecurityProtocol属性中注释掉tls 1.2的显式设置(来源: https : //docs.microsoft.com/en-us/dotnet/framework/network-programming/tls#schusestrongcrypto )
设置appcontextswitches:
Switch.System.ServiceModel.DontEnableSystemDefaultTlsVersions Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols
(来源: https : //docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element )
到目前为止,我们无法对抛出的异常进行任何更改。 有人能指出我们正确的方向吗?
非常感谢你提前!
更新:
由于评论中的建议,我们制作了一些wirehark痕迹。
如果没有安装Framework 4.7.2,我们的应用程序会协商 - 就像我们的代码示例所示 - 使用服务器应用程序成功完成1.2:
之后,我们将代码更改为专门设置tls 1.1,以确认设置ServicePointManager.SecurityProtocol产生了影响我们看到,毫不奇怪,应用程序无法协商tls 1.1:
现在,对于有趣的部分,我们再次安装了.NET Framework 4.7.2,重新设置了代码
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
并再次追踪了这个电话。 现在,令我们惊讶的是,该应用尝试协商tls 1.0,当然失败了:
之后,我们通过以下方式专门禁用了操作系统上的tls 1.0:
`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client
"Enabled"=dword:0000000
"DisabledByDefault"=dword:00000001 `
再次查看Wireshark,该应用程序试图协商ssl3.0。 回到注册表并特别禁用那个,在Wireshark中没有显示ClientHello,并且异常说,没有找到可以连接到服务器的相互算法。
尝试设置这些注册表设置:
Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319
Value: SchUseStrongCrypto
Data: 1
Key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server
Value: Enabled
Data: 0
Value: DisabledByDefault
Data: 1
之后,在使您的HTTPWebRequest包含ServicePointManager更改之前:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
这应该会强制您的应用程序到TLS 1.2。 我没有看到任何说你曾经尝试过以上所有内容的事情,这样做对我们有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.