mysqldockerunity-game-enginessl-certificate

“CryptographicException: Chain instance is empty.” error when connecting a Unity server in a Docker container to a MySQL server on a Linux VM


I have a Linux Virtual Machine that I rent. On that Linux VM I have installed a MySQL server with two users, besides the root one, "unity@127.0.0.1" and "unity2@localhost". I also have Docker installed on that Linux VM.

I am going to use Docker containers as servers for my multiplayer game. I have already successfully deployed a Unity server in a Docker container and sent data to a client on my PC.

Now my last step is to connect that Unity server in a Docker container directly to the MySQL server that runs on the same Linux VM. To do so I have installed MySQL through NuGet for Unity. Screenshot of MySQL through NuGet for Unity

Here is my code that I use to connect to the MySQL server. I use Debug.Log() to see where exactly my code errors, which is number 3, meaning "dbcon.Open();" fails.

using System;
using System.Data;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MySql.Data.MySqlClient;
using Unity.Netcode;

public class MySQLScript : MonoBehaviour
{
    
    void Start()
    {
          MySQLFunction();
    }

    [Rpc(SendTo.Server)]
    public void MySQLFunction()
    {
        Debug.Log("MySQL Function START");
        string connectionString =
           "Server=127.0.0.1;" +
           "Database=unity_data;" +
           "UserID=unity;" +
           "Password=<not gonna type my pass in public>;" +
           "Pooling=false";
           Debug.Log("1");

        IDbConnection dbcon;
        Debug.Log("2");
        dbcon = new MySqlConnection(connectionString);
        Debug.Log("3");
        dbcon.Open();
        Debug.Log("4");
        IDbCommand dbcmd = dbcon.CreateCommand();
        Debug.Log("5");

        string sql =
            "SELECT userid, username " +
            "FROM unity_table";
        Debug.Log("6");
        dbcmd.CommandText = sql;
        Debug.Log("7");
        IDataReader reader = dbcmd.ExecuteReader();
        Debug.Log("8");

        while (reader.Read())
        {
            Debug.Log("READ Start");
            string UserId = (string)reader["userid"];
            string UserName = (string)reader["username"];
            Debug.Log("userid: " + UserId + "username: " + UserName);
            Debug.Log("READ End");
        }

        Debug.Log("9");
        reader.Close();
        Debug.Log("10");
        reader = null;
        Debug.Log("11");
        dbcmd.Dispose();
        Debug.Log("12");
        dbcmd = null;
        Debug.Log("13");
        dbcon.Close();
        Debug.Log("14");
        dbcon = null;
        Debug.Log("MySQL Function END");
    }
}

Code is taken from the following site: https://www.mono-project.com/docs/database-access/providers/mysql/ I tried code from the official website: https://www.nuget.org/packages/mysql.data/ But I have the same error.

I also tried to change the user from "unity" to "unity2" and server address that I use from "127.0.0.1" to "localhost" but both of them give the same error.

I use this command to start my Docker container with the Unity server build inside:

docker run --network host -p 7777:7777/udp private_repository_name:tag_name

I use "--network host" because as I understand this makes the container run as a localhost, which is what I think need. The port is 7777 as this is the udp port that the Unity Transport has in the Unity server build.

Here are the error logs from the Linux VM after I start the docker container with my Unity server that tries to connect to the MySQL server:

CryptographicException: Chain instance is empty.
  at Mono.Unity.UnityTlsContext.ProcessHandshake () [0x00047] in <6297cf863591482c869f99d22a768126>:0
  at Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake (Mono.Net.Security.AsyncOperationStatus status, System.Boolean renegotiate) [0x000da] in <6297cf863591482c869f99d22a768126>:0
  at (wrapper remoting-invoke-with-check) Mono.Net.Security.MobileAuthenticatedStream.ProcessHandshake(Mono.Net.Security.AsyncOperationStatus,bool)
  at Mono.Net.Security.AsyncHandshakeRequest.Run (Mono.Net.Security.AsyncOperationStatus status) [0x00006] in <6297cf863591482c869f99d22a768126>:0
  at Mono.Net.Security.AsyncProtocolRequest.ProcessOperation (System.Threading.CancellationToken cancellationToken) [0x000fc] in <6297cf863591482c869f99d22a768126>:0
Rethrow as AuthenticationException: Authentication failed, see inner exception.
  at Mono.Net.Security.MobileAuthenticatedStream.ProcessAuthentication (System.Boolean runSynchronously, Mono.Net.Security.MonoSslAuthenticationOptions options, System.Threading.CancellationToken cancellationToken) [0x00262] in <6297cf863591482c869f99d22a768126>:0
  at MySql.Data.Common.Ssl.StartSSLAsync (System.IO.Stream baseStream, System.Text.Encoding encoding, System.String connectionString, System.Threading.CancellationToken cancellationToken, System.Boolean execAsync) [0x003c2] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySql.Data.MySqlClient.NativeDriver.OpenAsync (System.Boolean execAsync, System.Threading.CancellationToken cancellationToken) [0x006c7] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySql.Data.MySqlClient.Driver.OpenAsync (System.Boolean execAsync, System.Threading.CancellationToken cancellationToken) [0x00092] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySql.Data.MySqlClient.Driver.CreateAsync (MySql.Data.MySqlClient.MySqlConnectionStringBuilder settings, System.Boolean execAsync, System.Threading.CancellationToken cancellationToken) [0x00152] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySql.Data.MySqlClient.Driver.CreateAsync (MySql.Data.MySqlClient.MySqlConnectionStringBuilder settings, System.Boolean execAsync, System.Threading.CancellationToken cancellationToken) [0x0020b] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySql.Data.MySqlClient.MySqlConnection.OpenAsync (System.Boolean execAsync, System.Threading.CancellationToken cancellationToken) [0x00592] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySql.Data.MySqlClient.MySqlConnection.Open () [0x00012] in <e5b4169d41fc4f35b3d1470d22ebf230>:0
  at MySQLScript.MySQLFunction () [0x0003a] in C:----\Assets\MySQL\MySQLScript.cs:46
  at MySQLScript.Start () [0x00001] in C:----\Assets\MySQL\MySQLScript.cs:19

I have already double checked if my mysql 3306 port is included in the ufw firewall and tried updating my certificates on the Linux VM by doing this:

update-ca-certificates
apt-get install -y ca-certificates
certmgr -list -c Trust
cp -R /usr/share/.mono/certs/Trust/* ~/.config/.mono/certs/Trust/

I am not that good with Sys Admin stuff and the Unity Engine, so I don't know where to go from here. Would appreciate any help or general directions where I should look to figure this out.

Edit:

My Dockerfile:

FROM ubuntu:latest
WORKDIR /app
COPY . .
EXPOSE 7777
CMD ["./Build_exp1.x86_64"]

Solution

  • I got it working. I decided to just disable SSL for the MySQL connection. Not going to lie, didn't know how to do that myself so I asked AI. It gave me a code that disables SSL in the MySQL connection string. It also switched to MySql Connector from MySql.Data since it is better. When running the docker container it suggested using "--add-host=host.docker.internal:host-gateway" and using "host.docker.internal" DNS as the address in the connection string.

    Surprisingly it worked really well and also cleared up some confusion I had about how Docker, Linux VMs and MySQL servers work. The error wasn't really solved but this workaround is easy to do and it works in my specific case since my Unity server and MySQL server are on the same VM. I have finally everything set up to start working on the actual game :)