使用 LXD REST API,ClientWebSocket 在 .Net Core 上抛出 'AuthenticationException',但在 .Net Framework 上运行良好
Using LXD REST API, ClientWebSocket throws 'AuthenticationException' on .Net Core, but on .Net Framework, it works well
我正在将 LXD.NET 移植到 .Net Standard 2.0。通过 HTTPS 的 REST APIs 适用于 .Net Core 和 .Net Framework。
但是使用 WebSocket APIs(例如 1.0/containers/<name>/exec ), ClientWebSocket 仅在 .Net Core 上抛出身份验证异常。(在 .Net Framework 上,它不会抛出并且运行良好。 )
LXD 在 Ubuntu 18.04 运行。我在两个客户端上进行了测试,一个是 运行 on Windows 10,另一个是 运行 on Linux(同样的 linux comupter runnning LXD)。
所有源代码都是Here ( https://github.com/GnicoJP/lxd-dotnet-websocket-test)。
重现步骤(服务器端)
LXD 设置
$ sudo apt install lxc lxd
$ sudo lxd init
我将 LXD 配置为可通过网络使用。
$ sudo lxc launch images:alpine/3.8 <container_name>
我启动了一张图片。
SSL Key/Certificates 生成
$ openssl genrsa 2048 > client.key
$ openssl req -new -key client.key > client.csr
$ openssl x509 -days 3650 -req -signkey client.key < client.csr > client.crt
$ openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12
将 client.p12 带到客户端 PC。
我注册了 SSL 证书
$ sudo lxc config trust add client.key
源代码
入口点是 Here。我正在调用 exec API。(wait-for-websocket 为真)
解析 Exec API 的结果是 Here。我觉得WebSocket的URI没有错
打开ClientWebSocket是Here。在 .Net Framework 上,WebSocket 运行良好 with/without 证书。
抛出异常
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred. (Unable to connect to the remote server)
Source=System.Private.CoreLib
Stack Trace:
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) in Task.cs:line 2840
at System.Threading.Tasks.Task.Wait() in Task.cs:line 2706
at lxd_dotnet_websocket_test.Program.Main(String[] args) in lxd-dotnet-websocket-test\Program.cs:line 20
Inner Exception 1:
System.Net.WebSockets.WebSocketException: Unable to connect to the remote server
HResult=-2147467259
Stack Trace:
at System.Net.WebSockets.WebSocketHandle.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
at System.Net.WebSockets.ClientWebSocket.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken)
at LXD.ClientWebSocketExtensions.CreateAndConnectAsync(String url, API API) in .\libs\LXD\Util\ClientWebSocketExtensions.cs:line 19
at LXD.Domain.Container.ContainerExecResult.ContainerExecResultWithWebSockets.TestCreate(API API, ContainerExec exec, JToken response, String operationUrl) in .\libs\LXD\Domain\Container.cs:line 228
Inner Exception 2:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
HResult=-2146233087
Stack Trace:
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.WebSockets.WebSocketHandle.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
Inner Exception 3:
AuthenticationException: The remote certificate is invalid according to the validation procedure.
HResult=-2146233087
Stack Trace:
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.Net.Security.SslState.ThrowIfExceptional()
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.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
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.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
我是 Whosebug 的初学者。如果我的问题或我的英语不好请告诉我。
.Net Framework 不检查 WebSocket 中使用的证书是否可信,
但是 .Net Core 可以。我无法从异常中得到解决方法,所以我调查了 by using PerfView.
如何解决
我安装了 LXD 的服务器证书。
将 server.crt 文件(/var/lxd/server.crt)带到客户端 PC,然后安装为受信任的根证书。
请阅读如何安装:Windows,
我正在将 LXD.NET 移植到 .Net Standard 2.0。通过 HTTPS 的 REST APIs 适用于 .Net Core 和 .Net Framework。
但是使用 WebSocket APIs(例如 1.0/containers/<name>/exec ), ClientWebSocket 仅在 .Net Core 上抛出身份验证异常。(在 .Net Framework 上,它不会抛出并且运行良好。 )
LXD 在 Ubuntu 18.04 运行。我在两个客户端上进行了测试,一个是 运行 on Windows 10,另一个是 运行 on Linux(同样的 linux comupter runnning LXD)。
所有源代码都是Here ( https://github.com/GnicoJP/lxd-dotnet-websocket-test)。
重现步骤(服务器端)
LXD 设置
$ sudo apt install lxc lxd
$ sudo lxd init
我将 LXD 配置为可通过网络使用。
$ sudo lxc launch images:alpine/3.8 <container_name>
我启动了一张图片。
SSL Key/Certificates 生成
$ openssl genrsa 2048 > client.key
$ openssl req -new -key client.key > client.csr
$ openssl x509 -days 3650 -req -signkey client.key < client.csr > client.crt
$ openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12
将 client.p12 带到客户端 PC。
我注册了 SSL 证书
$ sudo lxc config trust add client.key
源代码
入口点是 Here。我正在调用 exec API。(wait-for-websocket 为真)
解析 Exec API 的结果是 Here。我觉得WebSocket的URI没有错
打开ClientWebSocket是Here。在 .Net Framework 上,WebSocket 运行良好 with/without 证书。
抛出异常
System.AggregateException
HResult=0x80131500
Message=One or more errors occurred. (Unable to connect to the remote server)
Source=System.Private.CoreLib
Stack Trace:
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) in Task.cs:line 2840
at System.Threading.Tasks.Task.Wait() in Task.cs:line 2706
at lxd_dotnet_websocket_test.Program.Main(String[] args) in lxd-dotnet-websocket-test\Program.cs:line 20
Inner Exception 1:
System.Net.WebSockets.WebSocketException: Unable to connect to the remote server
HResult=-2147467259
Stack Trace:
at System.Net.WebSockets.WebSocketHandle.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
at System.Net.WebSockets.ClientWebSocket.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken)
at LXD.ClientWebSocketExtensions.CreateAndConnectAsync(String url, API API) in .\libs\LXD\Util\ClientWebSocketExtensions.cs:line 19
at LXD.Domain.Container.ContainerExecResult.ContainerExecResultWithWebSockets.TestCreate(API API, ContainerExec exec, JToken response, String operationUrl) in .\libs\LXD\Domain\Container.cs:line 228
Inner Exception 2:
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
HResult=-2146233087
Stack Trace:
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.WebSockets.WebSocketHandle.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
Inner Exception 3:
AuthenticationException: The remote certificate is invalid according to the validation procedure.
HResult=-2146233087
Stack Trace:
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.Net.Security.SslState.ThrowIfExceptional()
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.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
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.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
我是 Whosebug 的初学者。如果我的问题或我的英语不好请告诉我。
.Net Framework 不检查 WebSocket 中使用的证书是否可信, 但是 .Net Core 可以。我无法从异常中得到解决方法,所以我调查了 by using PerfView.
如何解决
我安装了 LXD 的服务器证书。
将 server.crt 文件(/var/lxd/server.crt)带到客户端 PC,然后安装为受信任的根证书。
请阅读如何安装:Windows,