单声道HTTPS错误 - “写入标题时出错”

时间:2016-05-04 13:27:17

标签: c# .net linux ssl mono

范围:

我正在尝试与外部集中式Logging service提供程序集成,使用HTTPS请求将日志发布到该提供程序。

我们在C#之上运行Mono,使用Ubuntu 14.04 LTS作为操作系统。

我们已经使用mono已经多年了,所以我们对它的行为和潜在的缺陷/问题有所了解。

以前的设置

当你谷歌这个问题时,你基本上找到了两个解决方案,对于这种情况,它们都没有对我有用。这是我到目前为止所做的事情

Basic Mono-Complete Setup + ca-certificates-mono(可能会解决与HTTPS相关的问题)。

除此之外,我知道mono默认情况下不信任任何证书,拥有自己的证书链,并且我们必须将它们导入到它。为此,我运行mozroots --import --sync --ask-remove并打印出“已下载并安装了140个证书”。

另外,我们使用这个讨厌的单行程序覆盖CertificateValidationCallback:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };

以上都没有解决我们的问题。

错误,错误和更多错误:

Note that all of the codes below do work on Windows.

到目前为止,我们已经尝试过:

  • 使用Native .NET WebClient异步调用(PostAsync)。

结果,我们收到诸如Cant find file system.net.http.dll之类的错误,一旦我们实际将这个错误从我们的Windows系统复制到它,我们就会收到另一个错误Task Exception(不记得那里的确切消息)。

显然,在Xamarin程序上使用此客户端倾向于解决人们遇到的问题,但我们仍然使用HttpClient中的标准.NET类来获得上面列出的相同错误

  • 编写我们自己的WebRequests Wrapper

这是我们与实际解决方案最接近的,在Mono上运行时会导致Error Writing Headers

小代码示例:

using (WebRequests webClient = new WebRequests ())
{
                // Client Configuration
                webClient.BufferSize       = 32 * 1024;
                webClient.Accept           = "application/json";
                webClient.ContentType      = "application/json; charset=" + Encoding.UTF8.HeaderName;
                webClient.Timeout          = 60000;
                webClient.ReadWriteTimeout = 60000;
                webClient.Encoding         = Encoding.UTF8.WebName;

                // Dummy Logz Payload - One Json Per Line
                string LogzPayload = "{id:'1', value='1'}\n{id:'2', value='2'}";

                // Request to Logz
                webClient.Post ("https://listener-4.logz.io:8071/?token=OUR_TOKEN&type=json", LogzPayload);
}

更新1:

尝试运行以下命令并立即获得异常:

certmgr --ssl https://listener-4.logz.io:8071/?token=OUR_TOKEN&type=json --machine

例外:

Unhandled Exception:
System.IO.IOException: The authentication or decryption has failed. --->     System.IO.IOException: The authentication or decryption has failed. --->  Mono.Security.Protocol.Tls.TlsException: The authentication or decryption has failed.
  at Mono.Security.Protocol.Tls.RecordProtocol.EndReceiveRecord  (IAsyncResult asyncResult) <0x4192e470 + 0x00132> in <filename unknown>:0
  at Mono.Security.Protocol.Tls.SslClientStream.SafeEndReceiveRecord  (IAsyncResult ar, Boolean ignoreEmpty) <0x4192e3a0 + 0x00031> in <filename  unknown>:0
  at Mono.Security.Protocol.Tls.SslClientStream.NegotiateAsyncWorker (IAsyncResult result) <0x4192abb0 + 0x00225> in <filename unknown>:0
  --- End of inner exception stack trace ---

2 个答案:

答案 0 :(得分:1)

我对Mono不是很熟悉,但我知道他们使用自己的TLS堆栈,而.NET使用来自操作系统的TLS堆栈。如果我的正确性比CipherSuiteFactory.cs中定义的可用密码套件更正确,这表明没有可用的ECDHE和DHE密码。但从我所看到的,服务器仅支持ECDHE和DHE密码,因此将不会有共享密码,并且TLS握手将失败。服务器支持的密码是:

ECDHE-RSA-AES256-GCM-SHA384
ECDHE-RSA-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
ECDHE-RSA-AES256-SHA384
ECDHE-RSA-AES256-SHA
DHE-RSA-AES256-SHA256
DHE-RSA-AES256-SHA

其中大多数是密码需要TLS 1.2,而Mono根本不支持这些密码(参见State of TLS in Mono)。但即使是剩下的只有DHE或ECDHE,Mono似乎并不支持。他们正在积极研究new TLS stack,但看起来还没有完成。

如果您有权访问服务器,则可能尝试配置密码AES256-SHA,这可能是Mono当前支持的最佳密码。

答案 1 :(得分:0)

我建议您切换到Ubuntu 16.04,因为它带来了默认情况下同步证书的Mono软件包版本,因此您不需要运行mozroots,并且您更有可能没有问题在这个区域附近。