C# 身份验证失败,因为远程方已关闭传输流。托管在 Azure Function 中的应用
C# Authentication failed because the remote party has closed the transport stream. App hosted in Azure Function
我在生产中遇到了这个奇怪的问题。向 APIM 发出远程 https 请求时,抛出以下错误:
The SSL connection could not be established, see inner exception.
Inner exception: Authentication failed because the remote party has closed the transport stream.
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.StartReadFrame","level":0,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.PartialFrameCallback","level":1,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","level":2,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.ThrowIfExceptional","level":3,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.InternalEndProcessAuthentication","level":4,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.EndProcessAuthentication","level":5,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.EndAuthenticateAsClient","level":6,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream+<>c.<AuthenticateAsClientAsync>b__65_1","level":7,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic","level":8,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","level":9,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":10,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":11,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult","level":12,"line":0}
{"assembly":"System.Net.Http, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Http.ConnectHelper+<EstablishSslConnectionAsyncCore>d__4.MoveNext","level":13,"line":0}
我在代码中将安全协议设置为tls1.2:
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
当我从生产中点击 https://www.howsmyssl.com/a/check 时,我得到以下响应:
{
"given_cipher_suites": [
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
],
"ephemeral_keys_supported": true,
"session_ticket_supported": true,
"tls_compression_supported": false,
"unknown_cipher_suite_supported": false,
"beast_vuln": false,
"able_to_detect_n_minus_one_splitting": false,
"insecure_cipher_suites": {
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA": [ "uses 3DES which is vulnerable to the Sweet32 attack but was not configured as a fallback in the ciphersuite order" ],
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": [ "uses 3DES which is vulnerable to the Sweet32 attack but was not configured as a fallback in the ciphersuite order" ]
},
"tls_version": "TLS 1.2",
"rating": "Bad"
}
相同的功能在 DEV 和 QA 环境中正常工作。所有环境都是使用相同的管道创建的(arm 模板和代码)
问题的根本原因是在私有 DNS 区域中配置了错误的 IP 地址。我们有两个私有 DNS 区域来解析 APIM 的自定义域名,一个指向 QA 的 APIM,另一个指向 PROD 的 APIM。我们一开始就不应该有两个私有 DNS 区域,错误的 IP 地址是一个可怕的错误:(。经验教训
我在生产中遇到了这个奇怪的问题。向 APIM 发出远程 https 请求时,抛出以下错误:
The SSL connection could not be established, see inner exception.
Inner exception: Authentication failed because the remote party has closed the transport stream.
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.StartReadFrame","level":0,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.PartialFrameCallback","level":1,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","level":2,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.ThrowIfExceptional","level":3,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.InternalEndProcessAuthentication","level":4,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.EndProcessAuthentication","level":5,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream.EndAuthenticateAsClient","level":6,"line":0}
{"assembly":"System.Net.Security, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Security.SslStream+<>c.<AuthenticateAsClientAsync>b__65_1","level":7,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic","level":8,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","level":9,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":10,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":11,"line":0}
{"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult","level":12,"line":0}
{"assembly":"System.Net.Http, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","method":"System.Net.Http.ConnectHelper+<EstablishSslConnectionAsyncCore>d__4.MoveNext","level":13,"line":0}
我在代码中将安全协议设置为tls1.2:
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
当我从生产中点击 https://www.howsmyssl.com/a/check 时,我得到以下响应:
{
"given_cipher_suites": [
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_AES_256_GCM_SHA384",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA256",
"TLS_RSA_WITH_AES_128_CBC_SHA256",
"TLS_RSA_WITH_AES_256_CBC_SHA",
"TLS_RSA_WITH_AES_128_CBC_SHA",
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"
],
"ephemeral_keys_supported": true,
"session_ticket_supported": true,
"tls_compression_supported": false,
"unknown_cipher_suite_supported": false,
"beast_vuln": false,
"able_to_detect_n_minus_one_splitting": false,
"insecure_cipher_suites": {
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA": [ "uses 3DES which is vulnerable to the Sweet32 attack but was not configured as a fallback in the ciphersuite order" ],
"TLS_RSA_WITH_3DES_EDE_CBC_SHA": [ "uses 3DES which is vulnerable to the Sweet32 attack but was not configured as a fallback in the ciphersuite order" ]
},
"tls_version": "TLS 1.2",
"rating": "Bad"
}
相同的功能在 DEV 和 QA 环境中正常工作。所有环境都是使用相同的管道创建的(arm 模板和代码)
问题的根本原因是在私有 DNS 区域中配置了错误的 IP 地址。我们有两个私有 DNS 区域来解析 APIM 的自定义域名,一个指向 QA 的 APIM,另一个指向 PROD 的 APIM。我们一开始就不应该有两个私有 DNS 区域,错误的 IP 地址是一个可怕的错误:(。经验教训