【问题标题】:"Could not create SSL/TLS secure channel" Azure Storage .NET API error since POODLE“无法创建 SSL/TLS 安全通道”自 POODLE 以来的 Azure Storage .NET API 错误
【发布时间】:2014-12-11 03:40:54
【问题描述】:

读取工作,但在将 .NET Azure 存储 API 库用于 blob 和 azure 队列(也基于存储构建)时,创建/删除/更新不会。这是在 ASP.NET MVC 5.2 网站 .NET 4.5.1 中运行的,所有库都已完全更新到最新版本。这个问题在昨天(10 月 14 日)晚上突然出现,显然是因为 POODLE 漏洞利用已广为人知。多年来一直使用这个 API 项目,没有出现这个问题,并且部署的版本一直在工作。

令人沮丧的是,在我的开发/本地机器上,问题没有出现。

在错误显示之前有很长的延迟,可能是由于重试尝试或其他原因。

请求被中止:无法创建 SSL/TLS 安全通道。

System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext)   at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext)

这就是例外的全部。

【问题讨论】:

    标签: azure ssl azure-storage


    【解决方案1】:

    我遇到了完全相同的问题:昨天许多公司在服务器上禁用了 SSLv3,因此客户端在连接到安全端点时必须协商使用 TLS。

    在我的开发盒上运行时,一切都像以前一样。但是在我所有的生产服务器上,当连接到某些服务器时,我都会遇到同样的异常(不是全部——例如 graph.facebook.com、mandrillapp.com 和其他一些服务器都显示了这个问题)。

    有趣的是,重新启动应用程序解决了大约一个小时的问题。然后错误再次出现。

    经过一番谷歌搜索,我找到了这条线

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
    

    提供一些帮助。问题是,这似乎是一个全局设置,为我解决了一些但不是全部的连接问题。 Facebook API 再次工作,但 mandrill 例如停止工作并在几个小时后再次显示异常。

    问题似乎是,.NET HttpWebRequest 类(以及 WebClient 类)或底层 https 实现在协商通信协议时存在问题。

    我已经读到,TLS 是 .NET 中的标准协议已经有几年了,而 SSLv3 只是用作备用,但仍然存在例外。

    【讨论】:

    • 谢谢 Jan,我实际上只是在另一个 SO 线程上发布了一个相关问题的非常解决方案。当这里粗鲁的人决定对我投反对票时,我只是把它当作有用的东西来提供帮助,我删除了它。反正我已经有这一套了。你是对的,它解决了一个问题,但它并没有解决我的主要问题,即 Azure 存储连接本身不起作用。很好奇,你是说你找到了最终解决你所有问题的东西吗?而且,您自己是否遇到过 Azure 存储问题(“无法创建 SSL/TLS 安全通道”)?
    • @NicholasPetersen 不,我根本不使用 Azure 存储。使用 https 时,我只是遇到了 HttpWebRequest 类的问题(这似乎也是你的问题)。我找到了我的应用程序在某个时间点失败的原因:我使用的组件调用了 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3。因此,当该组件被调用时,它会强制整个过程只使用导致我的问题的 SSLv3。
    • @Jan - 我想我欠你最后一条评论的啤酒。这导致我在我们的代码中搜索设置了SecurityProtocol 的其他地方,果然它被重置为Ssl。谢谢!
    • @CodeNaked - 哈,我想你可以想象当我发现那行代码时我的脸是什么样子的……只是偶然,我在整个解决方案中搜索了那个神秘的 ServicePointManager .谁写的?因为大约几年前是我自己和我:)
    【解决方案2】:

    我认为我们发现了主要问题:Azure 存储,至少在与 Azure 云服务(但在可用的最新 Windows 平台上)进行通信时,似乎

    无法处理 Tls 1.2 安全协议。

    所以设置:

    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; // FAILS!
    

    你必须设置:

    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; // or Tls11 ?
    

    它也可能无法处理 Tls 1.1。我可以检查一下,但我厌倦了这个项目不能再次工作,哪怕是一秒钟。

    --- 更新 --- Azure 支持人员指出,在 .NET 4.5(4.0 和更早版本)之前,此枚举上唯一可用的 Tls 值只是 .Tls(没有 Tls11、Tls12)。

    msdn docs

    我打赌 Azure 存储中的接收端(在他们自己处理请求的内部堆栈上)没有使用 .NET 4.5(有根据的猜测)。

    ---结束更新---

    虽然在本地机器上没有问题。这让我想知道客户端(托管在 azure 中的云服务虚拟机)本身是否就是这里所缺少的。

    到目前为止,这似乎是有效的。

    对于通过远程访问实例获得的详细日志信息,这里有一些明显相关的日志,这可能有助于一些人希望在未来解决这个问题。在每种情况下,潜在的异常是:

    System.Security.Authentication.AuthenticationException // (of type: `System.ComponentModel.Win32Exception)`
    

    主要的错误信息是:

    客户端和服务器无法通信,因为它们不具备 通用算法

    显然,在这种情况下,其中一个(我认为云服务客户端?)无法处理 Tls1.2?

    日志sn-p:

        DetailID = 6
        Count:    4
        Type:     System.Security.Authentication.AuthenticationException
        Message:  A call to SSPI failed, see inner exception.
            Type:     System.ComponentModel.Win32Exception
            Message:  The client and server cannot communicate, because they do not possess a common algorithm
        Stack:    
            [HelperMethodFrame]
            System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest)
            [HelperMethodFrame]
            System.Net.Security.SslState.StartSendAuthResetSignal(System.Net.Security.ProtocolToken, System.Net.AsyncProtocolRequest, System.Exception)
            System.Net.Security.SslState.StartSendBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ProcessReceivedBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.StartReceiveBlob(Byte[], System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.StartSendBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ProcessAuthentication(System.Net.LazyAsyncResult)
            System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
            System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
            System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
            System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult)
            System.Net.TlsStream.Write(Byte[], Int32, Int32)
            System.Net.ConnectStream.WriteHeaders(Boolean)
            System.Net.HttpWebRequest.EndSubmitRequest()
            System.Net.Connection.CompleteConnection(Boolean, System.Net.HttpWebRequest)
            System.Net.Connection.CompleteStartConnection(Boolean, System.Net.HttpWebRequest)
            System.Net.Connection.CompleteStartRequest(Boolean, System.Net.HttpWebRequest, System.Net.TriState)
            System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest, Boolean)
            System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)
            System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)
            System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
            System.Net.HttpWebRequest.GetRequestStream()
            Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[[System.__Canon, mscorlib]](Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1<System.__Canon>, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamHelper(System.IO.Stream, System.Nullable`1<Int64>, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromByteArray(Byte[], Int32, Int32, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadText(System.String, System.Text.Encoding, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            ... my own project's calls begin here ...
    
            DetailID = 7
        Count:    4
        Type:     System.Security.Authentication.AuthenticationException
        Message:  A call to SSPI failed, see inner exception.
            Type:     System.ComponentModel.Win32Exception
            Message:  The client and server cannot communicate, because they do not possess a common algorithm
        Stack:    
            [HelperMethodFrame]
            System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult)
            [HelperMethodFrame]
            System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest)
            [HelperMethodFrame]
            System.Net.Security.SslState.StartSendAuthResetSignal(System.Net.Security.ProtocolToken, System.Net.AsyncProtocolRequest, System.Exception)
            System.Net.Security.SslState.StartSendBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ProcessReceivedBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.StartReceiveBlob(Byte[], System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.StartSendBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ProcessAuthentication(System.Net.LazyAsyncResult)
            System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
            System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
            System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
            System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult)
            System.Net.TlsStream.Write(Byte[], Int32, Int32)
            System.Net.ConnectStream.WriteHeaders(Boolean)
            System.Net.HttpWebRequest.EndSubmitRequest()
            System.Net.Connection.CompleteConnection(Boolean, System.Net.HttpWebRequest)
            System.Net.Connection.CompleteStartConnection(Boolean, System.Net.HttpWebRequest)
            System.Net.Connection.CompleteStartRequest(Boolean, System.Net.HttpWebRequest, System.Net.TriState)
            System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest, Boolean)
            System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)
            System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)
            System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
            System.Net.HttpWebRequest.GetRequestStream()
            Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[[System.__Canon, mscorlib]](Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1<System.__Canon>, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamHelper(System.IO.Stream, System.Nullable`1<Int64>, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromByteArray(Byte[], Int32, Int32, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadText(System.String, System.Text.Encoding, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            ... my own project's calls begin here ...
    
        DetailID = 8
        Count:    4
        Type:     System.Security.Authentication.AuthenticationException
        Message:  A call to SSPI failed, see inner exception.
            Type:     System.ComponentModel.Win32Exception
            Message:  The client and server cannot communicate, because they do not possess a common algorithm
        Stack:    
            [HelperMethodFrame]
            System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult)
            [HelperMethodFrame]
            System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult)
            [HelperMethodFrame]
            System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest)
            [HelperMethodFrame]
            System.Net.Security.SslState.StartSendAuthResetSignal(System.Net.Security.ProtocolToken, System.Net.AsyncProtocolRequest, System.Exception)
            System.Net.Security.SslState.StartSendBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ProcessReceivedBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.StartReceiveBlob(Byte[], System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.StartSendBlob(Byte[], Int32, System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ForceAuthentication(Boolean, Byte[], System.Net.AsyncProtocolRequest)
            System.Net.Security.SslState.ProcessAuthentication(System.Net.LazyAsyncResult)
            System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
            System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
            System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
            System.Net.TlsStream.ProcessAuthentication(System.Net.LazyAsyncResult)
            System.Net.TlsStream.Write(Byte[], Int32, Int32)
            System.Net.ConnectStream.WriteHeaders(Boolean)
            System.Net.HttpWebRequest.EndSubmitRequest()
            System.Net.Connection.CompleteConnection(Boolean, System.Net.HttpWebRequest)
            System.Net.Connection.CompleteStartConnection(Boolean, System.Net.HttpWebRequest)
            System.Net.Connection.CompleteStartRequest(Boolean, System.Net.HttpWebRequest, System.Net.TriState)
            System.Net.Connection.SubmitRequest(System.Net.HttpWebRequest, Boolean)
            System.Net.ServicePoint.SubmitRequest(System.Net.HttpWebRequest, System.String)
            System.Net.HttpWebRequest.SubmitRequest(System.Net.ServicePoint)
            System.Net.HttpWebRequest.GetRequestStream(System.Net.TransportContext ByRef)
            System.Net.HttpWebRequest.GetRequestStream()
            Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[[System.__Canon, mscorlib]](Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1<System.__Canon>, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamHelper(System.IO.Stream, System.Nullable`1<Int64>, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromByteArray(Byte[], Int32, Int32, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadText(System.String, System.Text.Encoding, Microsoft.WindowsAzure.Storage.AccessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions, Microsoft.WindowsAzure.Storage.OperationContext)
            ... my own project's calls begin here ...
    

    Jan 的回答最终在技术上给出了正确的解决方案,但它并没有给出 真正的原因,这是真正的问题(正如我所说在 cmets 中,我已经设置了这个,只是我 碰巧 设置了一个更高的值,改为 Tls12)。因此,虽然我总是宁愿不给出自己的答案而不是别人的答案,但我认为这对于其他在同样问题上苦苦挣扎的人来说更可取和更有帮助(事实上,当我看到他的答案时,它甚至没有向我注册为甚至与我所做的不同)。不过感谢 Jan 的帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-06
      • 2015-08-11
      • 2019-08-12
      • 2017-05-25
      • 2018-08-12
      • 1970-01-01
      • 1970-01-01
      • 2016-11-18
      相关资源
      最近更新 更多