单一 HTTPS 错误 - "Error Writing Headers"
Mono HTTPS Error - "Error Writing Headers"
范围:
我正在尝试与外部集中式 Logging service 提供商集成,使用 HTTPS
请求 post 日志。
我们在 Mono
之上 运行 C#
,使用 Ubuntu 14.04 LTS 作为 OS。
我们多年来一直在使用单声道,所以我们以某种方式熟悉它的行为和潜在的缺陷/问题。
以前的设置
当您 google 这个问题时,您会发现基本上有两种解决方案,对于这种情况,其中 none 对我有用。这是我到目前为止所做的
Basic Mono-Complete Setup + ca-certificates-mono(可能会解决与 HTTPS 相关的问题)。
除此之外,我知道 mono 默认不信任任何证书,它有自己的证书链,我们必须将它们导入它。为此,我 运行 mozroots --import --sync --ask-remove
并打印出“已下载并安装 140 个证书”。
另外,我们使用这个讨厌的单行覆盖了 CertificateValidationCallback:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };
None 以上解决了我们的问题。
错误、错误和更多错误:
Note that all of the codes below do work on Windows.
到目前为止我们已经尝试过:
- 使用本机 .NET WebClient 异步调用(
PostAsync
)。
结果,我们得到了诸如 Cant find file system.net.http.dll
之类的错误,而一旦我们实际将 windows 系统中的那个复制到它,我们就会得到另一个错误 Task Exception
(可以'我不记得那里的确切信息了)。
显然,在 Xamarin 程序上使用此客户端往往会解决人们遇到的问题,但我们仍然会遇到上面列出的相同错误,使用来自 .NET
的标准 HttpClient
class
- 编写我们自己的 WebRequests 包装器
这是我们最接近实际的解决方案,在 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 ---
我对 Mono 不是很熟悉,但我知道它们使用自己的 TLS 堆栈,而 .NET 使用 OS 中的 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). But even the rest is DHE or ECDHE only which Mono does not seem to support. They are actively working on a new TLS stack 但看起来还没有完成。
如果您可以访问服务器,您可以尝试配置密码 AES256-SHA,这可能是 Mono 目前支持的最好的密码。
我建议你切换到 Ubuntu 16.04,因为它带来了一个默认同步证书的 Mono 包版本,因此你不需要 运行 mozroots,而且你更有可能在这方面没有问题。
范围:
我正在尝试与外部集中式 Logging service 提供商集成,使用 HTTPS
请求 post 日志。
我们在 Mono
之上 运行 C#
,使用 Ubuntu 14.04 LTS 作为 OS。
我们多年来一直在使用单声道,所以我们以某种方式熟悉它的行为和潜在的缺陷/问题。
以前的设置
当您 google 这个问题时,您会发现基本上有两种解决方案,对于这种情况,其中 none 对我有用。这是我到目前为止所做的
Basic Mono-Complete Setup + ca-certificates-mono(可能会解决与 HTTPS 相关的问题)。
除此之外,我知道 mono 默认不信任任何证书,它有自己的证书链,我们必须将它们导入它。为此,我 运行 mozroots --import --sync --ask-remove
并打印出“已下载并安装 140 个证书”。
另外,我们使用这个讨厌的单行覆盖了 CertificateValidationCallback:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };
None 以上解决了我们的问题。
错误、错误和更多错误:
Note that all of the codes below do work on Windows.
到目前为止我们已经尝试过:
- 使用本机 .NET WebClient 异步调用(
PostAsync
)。
结果,我们得到了诸如 Cant find file system.net.http.dll
之类的错误,而一旦我们实际将 windows 系统中的那个复制到它,我们就会得到另一个错误 Task Exception
(可以'我不记得那里的确切信息了)。
显然,在 Xamarin 程序上使用此客户端往往会解决人们遇到的问题,但我们仍然会遇到上面列出的相同错误,使用来自 .NET
的标准 HttpClient
class
- 编写我们自己的 WebRequests 包装器
这是我们最接近实际的解决方案,在 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 ---
我对 Mono 不是很熟悉,但我知道它们使用自己的 TLS 堆栈,而 .NET 使用 OS 中的 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). But even the rest is DHE or ECDHE only which Mono does not seem to support. They are actively working on a new TLS stack 但看起来还没有完成。
如果您可以访问服务器,您可以尝试配置密码 AES256-SHA,这可能是 Mono 目前支持的最好的密码。
我建议你切换到 Ubuntu 16.04,因为它带来了一个默认同步证书的 Mono 包版本,因此你不需要 运行 mozroots,而且你更有可能在这方面没有问题。