endel / NativeWebSocket

🔌 WebSocket client for Unity - with no external dependencies (WebGL, Native, Android, iOS, UWP)
Other
1.13k stars 155 forks source link

wss protocol does not work when build on UWP #1

Open salinhard opened 4 years ago

salinhard commented 4 years ago

I'm using your great library for implement websockets on Hololens. If I use a ws protocol, it works on Unity Editor and Hololens. If I use wss, it works on Unity Editor but does not work on Hololens.

Seems a certificate error, because I get this error on the Hololens log: Curl error 51: Cert verify failed: UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED

Here the errors I got:

A call to SSPI failed, see inner exception.

Mono.Security.Interface.TlsException: Handshake failed - error code: UNITYTLS_INTERNAL_ERROR, verify result: UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED at Mono.Unity.Debug.CheckAndThrow (Mono.Unity.UnityTls+unitytls_errorstate errorState, Mono.Unity.UnityTls+unitytls_x509verify_result verifyResult, System.String context, Mono.Security.Interface.AlertDescription defaultAlert) [0x00036] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 at Mono.Unity.UnityTlsContext.ProcessHandshake () [0x00082] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status) [0x0003e] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 at (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus) at Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) [0x00006] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 at Mono.Net.Security.AsyncProtocolRequest+d24.MoveNext () [0x000ff] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 at Mono.Net.Security.AsyncProtocolRequest+d23.MoveNext () [0x0008b] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0

at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at Mono.Net.Security.MobileAuthenticatedStream+d47.MoveNext () [0x00254] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 at System.Net.WebSockets.WebSocketHandle+d24.MoveNext () [0x00199] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0

System.Security.Authentication.AuthenticationException

at System.Net.WebSockets.WebSocketHandle+d24.MoveNext () [0x00391] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in :0 at System.Net.WebSockets.ClientWebSocket+d16.MoveNext () [0x000d1] in <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in :0 at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in :0 at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in :0 at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in :0 at NativeWebSocket.WebSocket+d__19.MoveNext () [0x0005a] in C:\Users\manuel\development\unityProjects\NativeWebsocket\Assets\Scripts\WebSocket.cs:306

endel commented 4 years ago

Hi @salinhard, could it be a certificate issue? Can you confirm on this SSL reports if yours is valid? https://www.ssllabs.com/ssltest/

A recurring SSL configuration issue I see (and do myself sometimes) is not using the fullchain.pem certificate in the server-side. (If you're using only cert.pem, you should consider using fullchain.pem instead!)

Cheers

salinhard commented 4 years ago

Hi @endel I checked on https://www.ssllabs.com/ssltest/ and my certificate seems valid, I'm also trying to connect to wss://echo.websocket.org and does not work.

Did you try some wss that is working?

wivanw commented 4 years ago

Hello. I have a similar error. The certificate is verified and working. TlsException: Handshake failed - error code: UNITYTLS_INTERNAL_ERROR, verify result: UNITYTLS_X509VERIFY_FLAG_NOT_TRUSTED Mono.Unity.Debug.CheckAndThrow (Mono.Unity.UnityTls+unitytls_errorstate errorState, Mono.Unity.UnityTls+unitytls_x509verify_result verifyResult, System.String context, Mono.Security.Interface.AlertDescription defaultAlert) (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) Mono.Unity.UnityTlsContext.ProcessHandshake () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status) (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus) Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) Mono.Net.Security.AsyncProtocolRequest+d24.MoveNext () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) --- End of stack trace from previous location where exception was thrown --- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () (at :0) Mono.Net.Security.AsyncProtocolRequest+d23.MoveNext () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) Rethrow as AuthenticationException: A call to SSPI failed, see inner exception. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) Mono.Net.Security.MobileAuthenticatedStream+d47.MoveNext () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) --- End of stack trace from previous location where exception was thrown --- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () (at :0) System.Net.WebSockets.WebSocketHandle+d24.MoveNext () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) Rethrow as WebSocketException: Unable to connect to the remote server System.Net.WebSockets.WebSocketHandle+d24.MoveNext () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) --- End of stack trace from previous location where exception was thrown --- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () (at :0) System.Net.WebSockets.ClientWebSocket+d16.MoveNext () (at <0d3e94ab2a1c4d2a8582ccee7031f5c6>:0) --- End of stack trace from previous location where exception was thrown --- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.GetResult () (at :0) NativeWebSocket.WebSocket+d19.MoveNext () (at Assets/Scripts/Network/WebSocket.cs:297) --- End of stack trace from previous location where exception was thrown --- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) (at :0) System.Runtime.CompilerServices.TaskAwaiter.GetResult () (at :0) Network.Core.SocketClient+d7.MoveNext () (at Assets/Scripts/Network/SocketClient.cs:67) --- End of stack trace from previous location where exception was thrown --- System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () (at :0) System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__6_0 (System.Object state) (at :0) UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke () (at /Users/builduser/buildslave/unity/build/Runtime/Export/UnitySynchronizationContext.cs:115) UnityEngine.UnitySynchronizationContext:ExecuteTasks()

endel commented 4 years ago

Hi @wivanw are you also using UWP? On which platform are you getting this error?

wivanw commented 4 years ago

The problem was incorrect protocol settings: webSocketServer.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Ssl3; WebGL platform. Sorry for your time.

wivanw commented 4 years ago

In fact, the error was deeper. The solution is described: https://issuetracker.unity3d.com/issues/error-of-tlsexception-when-system-dot-net-dot-http-dot-dll-is-used-for-http-in-the-editor Only now my WebSockets have worked correctly.

endel commented 4 years ago

Thanks for the details @wivanw, this is probably going to be helpful for more people having this issue!

wivanw commented 4 years ago

I’ll supplement it. Check if you generated the certificate correctly. Although this stub works on some platforms, it does not work in WebGL. The error was precisely in the fact that the certificate was generated at the wrong level of the domain address. Here is the code that will make it easier for you to find certificate errors:

        ServicePointManager.ServerCertificateValidationCallback =
            (sender, certificate, chain, sslPolicyErrors) =>
            {
                bool isOk = true;
                // If there are errors in the certificate chain, look at each error to determine the cause.
                if (sslPolicyErrors != SslPolicyErrors.None)
                {
                    for (int i = 0; i < chain.ChainStatus.Length; i++)
                    {
                        if (chain.ChainStatus[i].Status != X509ChainStatusFlags.RevocationStatusUnknown)
                        {
                            chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
                            chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
                            chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                            chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
                            bool chainIsValid = chain.Build((X509Certificate2) certificate);
                            Debug.Log($"ChainIsValid: {chainIsValid}");
                            if (!chainIsValid)
                            {
                                isOk = false;
                            }
                        }
                    }
                }

                return isOk;
            };
        ServicePointManager.CertificatePolicy = new StubCertificatePolicy();
    private enum CertificateProblem : uint
    {
        None = 0x00000000,
        CertExpired = 0x800B0101,
        CertValidityPeriodNesting = 0x800B0102,
        CertRole = 0x800B0103,
        CertPathLenConst = 0x800B0104,
        CertCritical = 0x800B0105,
        CertPurpose = 0x800B0106,
        CertIssuerChaining = 0x800B0107,
        CertMalformed = 0x800B0108,
        CertUntrustedRoot = 0x800B0109,
        CertChaining = 0x800B010A,
        CertRevoked = 0x800B010C,
        CertUntrustedTestRoot = 0x800B010D,
        CertRevocationFailure = 0x800B010E,
        CertCnNoMatch = 0x800B010F,
        CertWrongUsage = 0x800B0110,
        CertUntrustedCa = 0x800B0112,

        //https://docs.microsoft.com/ru-ru/office/troubleshoot/error-messages/generic-trust-failure-(0x800b010b)-error
        GeneralFailureOfTrust = 0x800B010B
    };

    private class StubCertificatePolicy : ICertificatePolicy
    {
        private const bool DefaultValidate = true;

        public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request,
            int certificateProblem)
        {
            if ((CertificateProblem) certificateProblem != CertificateProblem.None)
            {
                Debug.Log($"Certificate Problem with accessing {request?.RequestUri}");
                Debug.Log($"Problem code 0x{certificateProblem:X8},");
                Debug.LogError(GetProblemMessage((CertificateProblem) certificateProblem));
                return true;
            }

            return DefaultValidate;
        }

        private static string GetProblemMessage(CertificateProblem problem)
        {
            var problemMessage = string.Empty;
            var problemCodeName = Enum.GetName(typeof(CertificateProblem), problem);
            problemMessage = !string.IsNullOrEmpty(problemCodeName)
                ? $"{problemMessage} Certificate problem:{problem}  code:{problemCodeName}"
                : "Unknown Certificate Problem";

            return problemMessage;
        }
    }
Roar1827 commented 4 years ago

Hey @wivanw @endel - thank you for your work in exploring this issue.

I believe I have hit the same problem. When we run our app through unity, or side loaded onto the Oculus Rift it works properly utilizing the NativeWebSocket library. When we build and upload to Oculus and install that way, the Websocket is no longer able to connect.

@wivanw - where did you apply that code in your most recent reply?

Thank you!

wivanw commented 4 years ago

Hey @wivanw @endel - thank you for your work in exploring this issue.

I believe I have hit the same problem. When we run our app through unity, or side loaded onto the Oculus Rift it works properly utilizing the NativeWebSocket library. When we build and upload to Oculus and install that way, the Websocket is no longer able to connect.

@wivanw - where did you apply that code in your most recent reply?

Thank you!

It took a long time until we realized that this library is based on another 4 years ago. It is very unstable and unsuitable for product release. We use Best HTTP2 which works like a watch. You can also use the libraries of both the server and the client pulled from Photone engyne assets.

Roar1827 commented 4 years ago

Thank you for the reply @wivanw - I appreciate you taking the time.

grilledalready commented 1 month ago

The problem was incorrect protocol settings: webSocketServer.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Ssl3; WebGL platform. Sorry for your time.

Hi How were you able to add this to code?