Linux上的ClientWebSocket抛出AuthenticationException(SSL)

sen*_*enz 6 c# linux websocket .net-core

我在Windows上运行以下websocket客户端代码,一切正常 - 就像预期的那样.但如果代码发布linux-arm并复制到RaspberryPi3(在Raspian下运行),它将最终出现在AuthenticationException.

csproj文件内容:

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
    <PackageReference Include="System.Net.WebSockets.Client" Version="4.3.1" />
  </ItemGroup>
Run Code Online (Sandbox Code Playgroud)

连接尝试:(抛出异常的点)

private readonly ClientWebSocket _socket;

public ApiConnection()
{
    _socket = new ClientWebSocket();
}

public async Task Connect()
{
    // the uri is like: wss://example.com/ws
    await _socket.ConnectAsync(new Uri(_settings.WebSocketUrl), CancellationToken.None);

    if (_socket.State == WebSocketState.Open)
        Console.WriteLine("connected.");
}
Run Code Online (Sandbox Code Playgroud)

异常堆栈:

System.Net.WebSockets.WebSocketException (0x80004005): Unable to connect to the remote server ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
         at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
         at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
         at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
         at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
         at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
         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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
         at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
         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.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
         at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
         at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
         at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
         at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
         at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
         at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
         at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at System.Net.WebSockets.WebSocketHandle.<ConnectAsyncCore>d__24.MoveNext()
         at System.Net.WebSockets.WebSocketHandle.<ConnectAsyncCore>d__24.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at System.Net.WebSockets.ClientWebSocket.<ConnectAsyncCore>d__16.MoveNext()
      --- End of stack trace from previous location where exception was thrown ---
         at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
         at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
         at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Run Code Online (Sandbox Code Playgroud)

目标websocket服务器在Ubuntu上的nginx代理后面运行.我认为问题依赖于客户端,因为如果代码在Windows上执行,一切正常.

我还尝试将CA证书导入Raspians"证书库".没有运气.

更新:
http连接(ws://)也适用于linux.看来,WebSocketClient我不相信我的LetsEncrypt证书?

War*_*War 1

当浏览器/客户端不信任服务器向其发送的 SSL 证书时,就会发生这种情况。

\n\n

要进行测试,请在浏览器中加载同一站点上的相同 url / url,您应该会收到警告。

\n\n

证书问题解决后,警告就会消失。

\n\n

解决 SSL 证书问题的确切过程取决于很多因素,例如......

\n\n

操作系统、网络服务器、证书颁发机构、证书提供商门户,因此这里的任何人几乎不可能向您提供有关修复证书问题的具体信息,但这就是说......

\n\n

然而,SE 网络上对此有一些通用建议......

\n\n

https://unix.stackexchange.com/questions/90450/adding-a-self-signed-certificate-to-the-trusted-list

\n\n

https://unix.stackexchange.com/questions/17748/trust-a-self-signed-pem-certificate

\n\n

就你而言,由于 rasbian 是基于 debian 的,一些标准的 debian 建议可能会有所帮助......

\n\n

在 Debian 中,证书存储位于 /etc/ssl/certs/ 中。默认情况下,此目录包含一系列符号链接,这些符号链接指向 ca-certificates 包安装的证书(包括 c_rehash(1) 生成的所需符号链接)和 ca-certificates.crt(它是所有这些证书的串联)。一切由 update-ca-certificates(8) 命令管理,该命令负责更新符号链接和 ca-certificates.crt 文件。

\n\n

将新的 (CA) 证书添加到存储中非常容易,因为 update-ca-certificates(8) 也在 /usr/local/share/ca-certificates/ 中查找文件,管理员只需将新证书放入此目录中的 PEM 格式(带有 .crt 扩展名)并以 root 身份运行 update-ca-certificates(8)。系统上的所有应用程序(wget、\xe2\x80\xa6)现在应该信任它。

\n\n

另一种可能的解决方案可能是“我相信我的代码不会请求错误的网址,因此我将忽略 SSL 证书错误”,您可以这样做......

\n\n

C# 忽略证书错误?

\n\n

...但这并不理想,至少它为您提供了一种解决方法,直到您可以解决问题,最坏的情况您仍然可以检查,但通过编写自己的检查而不只是一揽子返回 true。

\n\n

最后一点:

\n\n

我经常发现,无论操作系统是什么,在测试/检查之间做一些简单的事情,例如重新启动或两次,就可以清除您通常不会认为是问题的问题。

\n