Unity Unable to Conect to Realtime server via TSL12

Hello!

I am having a problem connecting to my Realtime GameLift Fleet via Unity.

I can connect to GameLift and run my Unity application when I create a fleet that does not generate a certificate. However, if I try to connect to a fleet that does generate a certificate, I get two errors:

System.Exception: RemoteCertificateNameMismatch
Stack Stace according to Unity logs:
System.Exception: RemoteCertificateNameMismatch
UnityEngine.Debug:Log(Object)
ASL.GameLiftManager:OnConnectionErrorEvent(Object, ErrorEventArgs) (at Assets/ASL/ASL_Scripts/GameLift/GameLiftManager.cs:144)
Aws.GameLift.Realtime.ClientEvents:OnError(Exception)
Aws.GameLift.Realtime.Client:OnConnectionError(Object, ErrorEventArgs)
Aws.GameLift.Realtime.Network.NetworkEvents:OnError(Exception)
Aws.GameLift.Realtime.Network.WebSocket4NetWsConnection:websocket_Error(Object, ErrorEventArgs)
WebSocket4Net.WebSocket:OnError(ErrorEventArgs)
WebSocket4Net.WebSocket:client_Error(Object, ErrorEventArgs)
SuperSocket.ClientEngine.ClientSession:OnError(Exception)
SuperSocket.ClientEngine.SslStreamTcpSession:ValidateRemoteCertificate(Object, X509Certificate, X509Chain, SslPolicyErrors)
Mono.Net.Security.Private.<>c__DisplayClass0_0:<PublicToMono>b__0(String, X509Certificate, X509Chain, MonoSslPolicyErrors)
Mono.Net.Security.Private.<>c__DisplayClass5_0:<MonoToPublic>b__0(Object, X509Certificate, X509Chain, SslPolicyErrors)
System.Net.ServerCertValidationCallback:Invoke(Object, X509Certificate, X509Chain, SslPolicyErrors)
Mono.Net.Security.ChainValidationHelper:ValidateChain(String, Boolean, X509Certificate, X509Chain&, X509CertificateCollection, SslPolicyErrors)
Mono.Net.Security.ChainValidationHelper:ValidateChain(String, Boolean, X509Certificate, X509Chain, X509CertificateCollection, SslPolicyErrors)
Mono.Net.Security.ChainValidationHelper:ValidateCertificate(String, Boolean, X509CertificateCollection)
Mono.Net.Security.MobileTlsContext:ValidateCertificate(X509CertificateCollection)
Mono.Unity.UnityTlsContext:VerifyCallback(unitytls_x509list_ref, unitytls_errorstate*)
Mono.Unity.UnityTlsContext:VerifyCallback(Void*, unitytls_x509list_ref, unitytls_errorstate*)
System.Object:wrapper_native_00007FF6CB18D840(unitytls_tlsctx*, unitytls_errorstate*)
Mono.Unity.UnityTlsContext:ProcessHandshake()
Mono.Net.Security.MobileAuthenticatedStream:ProcessHandshake(AsyncOperationStatus)
Mono.Net.Security.AsyncHandshakeRequest:Run(AsyncOperationStatus)
Mono.Net.Security.<ProcessOperation>d__24:MoveNext()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(Nullable`1)
Mono.Net.Security.<InnerRead>d__25:MoveNext()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(Int32)
Mono.Net.Security.<InnerRead>d__66:MoveNext()
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

and

System.Security.Authentication.AuthenticationException: 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
Stack Stace according to Unity logs:
System.Security.Authentication.AuthenticationException: 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 <ae22a4e8f83c41d69684ae7f557133d9>:0 
at Mono.Unity.UnityTlsContext.ProcessHandshake () [0x00082] in <ae22a4e8f83c41d69684ae7f557133d9>:0 
at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status) [0x0003e] in <ae22a4e8f83c41d69684ae7f557133d9>: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 <ae22a4e8f83c41d69684ae7f557133d9>:0 
at Mono.Net.Security.AsyncProtocolRequest+<ProcessOperation>d__24.MoveNext () [0x000ff] in <ae22a4e8f83c41d69684ae7f557133d9>:0 
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 
at Mono.Net.Security.AsyncProtocolRequest+<StartOperation>d__23.MoveNext () [0x0008b] in <ae22a4e8f83c41d69684ae7f557133d9>:0 
   --- End of inner exception stack trace ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 
at Mono.Net.Security.MobileAuthenticatedStream+<ProcessAuthentication>d__47.MoveNext () [0x00254] in <ae22a4e8f83c41d69684ae7f557133d9>:0 
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x0003e] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x00028] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x00008] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <437ba245d8404784b9fbab9b439ac908>:0 
at System.Threading.Tasks.TaskToApm.End (System.IAsyncResult asyncResult) [0x00029] in <437ba245d8404784b9fbab9b439ac908>:0 
at Mono.Net.Security.MobileAuthenticatedStream.EndAuthenticateAsClient (System.IAsyncResult asyncResult) [0x00000] in <ae22a4e8f83c41d69684ae7f557133d9>:0 
at System.Net.Security.SslStream.EndAuthenticateAsClient (System.IAsyncResult asyncResult) [0x00006] in <ae22a4e8f83c41d69684ae7f557133d9>:0 
at SuperSocket.ClientEngine.SslStreamTcpSession.OnAuthenticated (System.IAsyncResult result) [0x00028] in <d48c73b87c95425b91162817ccffec2d>:0 
UnityEngine.Debug:Log(Object)
 ASL.GameLiftManager:OnConnectionErrorEvent(Object, ErrorEventArgs) (at Assets/ASL/ASL_Scripts/GameLift/GameLiftManager.cs:144)
Aws.GameLift.Realtime.ClientEvents:OnError(Exception)
Aws.GameLift.Realtime.Client:OnConnectionError(Object, ErrorEventArgs)
Aws.GameLift.Realtime.Network.NetworkEvents:OnError(Exception)
Aws.GameLift.Realtime.Network.WebSocket4NetWsConnection:websocket_Error(Object, ErrorEventArgs)
WebSocket4Net.WebSocket:OnError(ErrorEventArgs)
WebSocket4Net.WebSocket:client_Error(Object, ErrorEventArgs)
SuperSocket.ClientEngine.ClientSession:OnError(Exception)
SuperSocket.ClientEngine.SslStreamTcpSession:OnAuthenticated(IAsyncResult)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:SetException(Exception)
Mono.Net.Security.<ProcessAuthentication>d__47:MoveNext()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(AsyncProtocolResult)
Mono.Net.Security.<StartOperation>d__23:MoveNext()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:SetException(Exception)
Mono.Net.Security.<ProcessOperation>d__24:MoveNext()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(Nullable`1)
Mono.Net.Security.<InnerRead>d__25:MoveNext()
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1:SetResult(Int32)
Mono.Net.Security.<InnerRead>d__66:MoveNext()
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

I code I am using to connect to my GameLift fleet is here:

My Connection Code
private IEnumerator ConnectToServer(string _ipAddr, int _port, string _tokenUID, string _gameName)
        {
#if (ASL_DEBUG)
            ClientLogger.LogHandler = (x) => Debug.Log(x);
#endif
            ConnectionToken token = new ConnectionToken(_tokenUID, null);
            ClientConfiguration clientConfiguration = new ClientConfiguration();

            clientConfiguration.ConnectionType = ConnectionType.RT_OVER_WSS_DTLS_TLS12;
        
            GetInstance().m_Client = new Client(clientConfiguration);
            GetInstance().m_Client.ConnectionOpen += new EventHandler(GetInstance().OnOpenEvent);
            GetInstance().m_Client.ConnectionClose += new EventHandler(GetInstance().OnCloseEvent);
            GetInstance().m_Client.DataReceived += new EventHandler<DataReceivedEventArgs>(GetInstance().OnDataReceived);
            GetInstance().m_Client.ConnectionError += new EventHandler<Aws.GameLift.Realtime.Event.ErrorEventArgs>(GetInstance().OnConnectionErrorEvent);

#if UNITY_ANDROID
            int UDPListenPort = 33400;
#else
            int UDPListenPort = FindAvailableUDPPort(DEFAULT_UDP_PORT, DEFAULT_UDP_PORT + 100); //33400 - 33500 - Function does not work on Android.
#endif
            
            if (UDPListenPort == -1)
            {
#if ASL_DEBUG
                Debug.Log("Unable to find an open UDP listen port");
#endif
                GetInstance().QForMainThread(AddErrorText, "Unable to find an open UDP listen port");
                yield break;
            }
            else
            {
#if ASL_DEBUG
                Debug.Log($"UDP listening on port: {UDPListenPort}");
#endif
            }
#if ASL_DEBUG
            Debug.Log($"[client] Attempting to connect to server IP: {_ipAddr} TCP port: {_port} Player Session ID: {_tokenUID}");
#endif
            GetInstance().m_Client.Connect(_ipAddr, _port, UDPListenPort, token);

            while (true)
            {
                if (GetInstance().m_Client.ConnectedAndReady)
                {
#if ASL_DEBUG
                    Debug.Log("[client] Connected to server");
#endif
                    GetInstance().QForMainThread(SetGameName, _gameName);
                    GetInstance().QForMainThread(SetCorrectUIPanel, CurrentLoginStage.LobbyScreen);
                    GetInstance().QForMainThread(UpdateOtherUsers);
                    break;
                }
                yield return null;
            }
        }

As you can see, I’m using ConnectionType.RT_OVER_WSS_DTLS_TLS12; so I am attempting to connect via TLS12.

I also get these log messages before I get an error message:

[INFO] Creating reliable connection client based on ConnectionType in ClientConfiguration: RT_OVER_WSS_DTLS_TLS12
[INFO] Using Websocket connection secured by TLS 1.2
[INFO] Initializing websocket. Uri: wss://34.211.169.15:1900/websocket

I am using Unity 2019.3.3f1 and these dlls

  • AWSSDK.CognitoIdentity.dll
  • AWSSDK.Core.dll
  • AWSSDK.Lambda.dll
  • AWSSDK.SecurityToken.dll
  • GameLiftRealtimeClientSdkNet45.dll
  • Google.Protobuf.dll
  • libsqlite3.so
  • log4net.dll
  • SuperSocket.ClientEngine.dll
  • WebSocket4Net.dll

The fleet I am using:

Region: us-west-2
FleetId: fleet-3cb2a88d-2f78-4ac8-b298-2c03e0145255

In case it’s not clear what I am trying to accomplish, what I want to do is use GameLift’s realtime servers over TCP and not UDP. Which is why I created a realtime server with generated certificates and setup my Unity connection type to use ‘ConnectionType.RT_OVER_WSS_DTLS_TLS12’. If I should be accomplishing a TCP connection another way than what I am currently doing, then please explain how I should do that as I haven’t found any documentation.

It should be noted that I have also experimented with adding this line to my project right before the connection is attempted:

ServicePointManager.ServerCertificateValidationCallback = delegate {return true;};

Which tells Unity to accept anything - thus removing the errors at the top of this post, but doing so then forces GameLift to use UDP over DTLS 1.2, which is not what I want (I want TCP) and even if it was what I wanted, doing it this way no longer allows me to recieve packets from the server - they just don’t show up anymore. So, adding that line of code, at least in its current state, is not an option for me. Hopefully knowing that helps you out on your end. If not… Then hopefully I didn’t confuse you more.

Thank you for your help!

I have found the solution to the error messages I was receiving, however, I am still having some issues.

First, to fix the error messages, I found hidden away in the documentation, that when using TLS12 you need to connect with DNS and not the IpAddress. I fixed that in my connection and it started working. So yay! But, like I mentioned earlier, not everything is working.

While a connection occurs, I can no longer intercept or send packets in my realtime script via the function

onMessage(gameMessage) 
{ 
     //my code...
}

I see via the Unity debugger logs that show I am successfully sending packets out, but I am not receiving any from the server. I need to intercept and see packets in the realtime script. I haven’t seen anything in the documentation stating that this can’t be done when using TLS12, so I assuming it can be. Lastly, I know its not my script giving an error because the exact same script works on a fleet that does not generate a certificate and is thus not connect to by TLS12.

Any reason why I’m not getting anything back from the realtime script (or its not receiving any of my packets)?

Thanks for the help! Let me know if you need more information on this one. I would give you an error code if I was receiving anything, but I’m not.

Sorry that you are having problems with Realtime and TLS

You may want to limit your instance to a single process. Folks in this thread are reporting that multi-process may have a bug currently: Timeout trying to connect to RealTime server with certificate generation enabled

May be worth keeping an eye on that thread.

I would also sanity check:

  • Ensure that your ports all line up and are open on the fleet (this should be configured automatically for real time. But confirm the port the player session ison, and check the logs to ensure the server is actually listening on that port)
  • If you can run on a different network (ie VPN, different wifi network) as your network provider/router may be blocking ports (check windows firewall settings as well)
    • But you seem to indicate players connect successfully so unless theres an odd MTU packet size issue, its probably not this.
  • Scan the server logs for errors as there may be some hidden information there.

If you’re still having issues and this is an urgent request, please cut a ticket to GameLift via AWS support or provide a fleet id + region and I can see if someone from the service team can shed some light on your issues.

Thank you for the reply and sorry the extreme delay. Its been decided that for now we will continue without TLS. Until this issue is resolved Timeout trying to connect to RealTime server with certificate generation enabled it is not a viable option for us and therefore has been put on the back burner for now.