简体   繁体   中英

Using LXD REST API, ClientWebSocket throws 'AuthenticationException' on .Net Core, but on .Net Framework, it works well

I'm porting LXD.NET to .Net Standard 2.0. REST APIs via HTTPS works well with .Net Core and .Net Framework.
But using WebSocket APIs (eg 1.0/containers/<name>/exec ), ClientWebSocket throws Authentication Exception on only .Net Core. ( On .Net Framework, it doesn't throw and works well. )

LXD is running on Ubuntu 18.04. I tested in two clients, one is running on Windows 10, the other is running on Linux (the same linux comupter runnning LXD).

All source code is Here ( https://github.com/GnicoJP/lxd-dotnet-websocket-test ).

Step to reproduce(Server side)

LXD setting

$ sudo apt install lxc lxd  
$ sudo lxd init  

I configured LXD to be available over the network.

$ sudo lxc launch images:alpine/3.8 &lt;container_name&gt;  

I launched an image.

SSL Key/Certificates generating

$ 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

Bring client.p12 to Client PCs.

I Registered SSL Certificate

$ sudo lxc config trust add client.key

Source Codes

Entry Point is Here . I'm calling exec API.(wait-for-websocket is true)
Parsing Exec API's result is Here . I think WebSocket's URI is not wrong.
Opening ClientWebSocket is Here . On .Net Framework, WebSocket works well with/without certificates.

Thrown Exceptions

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)

I'm begginer in StackOverflow. Please tell me if my question or my English is not good.

.Net Framework doesn't checks whether the certificate used in WebSocket is trusted, but .Net Core does. I was unable to get how to solve from Exception, so I investigated by using PerfView .

How to Solve

I installed LXD's Server Certificates. Bring server.crt file(/var/lxd/server.crt) to Client PCs, then install as trusted root Certificate.
Please read how to install: Windows , Linux

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM