logo

【Unity】MagicOnionサーバを立ち上げて自己証明書でSSL通信してみる

投稿日2022-02-22

更新日2024-05-17

Picture of the logo
目次(タップして移動)

NGINXを介した接続やSSL化に少々手こずったので備忘録も兼ね書き残す事にしました。(2022年2月時点)

実証環境&バージョン

一部バージョンに依存して動かない事もあるそうなので今回実際に使用したものを書き残しておきます。

今回動作を確認した環境

  • windows10
  • unity 2020.3.26f
  • Visual Studio 2022
  • docker v20.10.12
  • nginx v1.21.6

バージョン

サーバーサイド

  • .Net Core 5
  • MagicOnion 4.4.0
  • MagicOnion.MSBuild.Tasks 4.4.0
  • MagicOnion.Shared 4.4.0
  • MessagePack.MSBuild.Tasks 2.3.85
  • MessagePack.UnityShims 2.3.85

クライアントサイド

  • MagicOnion.Client.Unity.unitypackage 4.4.0
  • grpc_unity_package.2.40.0

ManicOnionのダウンロードとインストール

まずは公式githubのreadmeやコチラのサイトなどを参考にすればwebサーバー(NGINX等)を通さない単純なHTTP接続ならすぐ出来るでしょう。

.net5を選択しよう

dockerでNGINXを立ち上げる

docker-composeで下記のようにdocker-compose.ymlファイルを作りdocker-compose up -dで起動する

version: '3'
services:
    web:
        image: nginx:latest
        container_name: nginx
        ports: 
            - "8080:8080"
        
        volumes: 
            - ./var/run/docker.sock:/tmp/docker.sock:ro
            - ./nginx:/etc/nginx/conf.d     #必須ではないがvolume化しておくと弄るのが楽になる
            - ./ssl:/ssl

        # dockerコンテナ内からhost.docker.internalするのに必要
        extra_hosts:
            - "host.docker.internal:host-gateway"

起動されたらconf.d配下に下記のconfファイルを作る。一見長いように見えるけどほぼこちらのコピペです。若干追記してます。

# dockerを使う場合localhost:5000では機能しない
upstream grpc-app {
    server host.docker.internal:5000;
}

server {
  
  listen 8080 ssl http2 default_server;
  listen [::]:8080 ssl http2 default_server; 

  ssl_certificate     /ssl/localhost.crt;   #ディレクトリやファイル名は
  ssl_certificate_key /ssl/localhost.key;   #適宜自分のものに書き換える
  
  ssl_session_timeout 1d;
  ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
  ssl_session_tickets off;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;
  
  # HSTS (ngx_http_headers_module is required) (63072000 seconds)
    add_header Strict-Transport-Security "max-age=63072000" always;
  
  # オレオレ証明書では機能しないのでコメントアウト
  # OCSP stapling
  # ssl_stapling on;
  # ssl_stapling_verify on;

  # verify chain of trust of OCSP response using Root CA and Intermediate certs

  # replace with the IP address of your resolver
  resolver 127.0.0.1;

  location / {
    grpc_pass grpc://grpc-app;
  }
}

confファイルの追加と後述の証明書ファイルの作成が済んだらnginx -s reloadで再起動する。

upstream内のhost.docker.internal:5000はNGINXがdockerコンテナ内にある場合の記述です。dockerコンテナ内のnginxからはlocalhost:5000```では繋がりません。

オレオレ証明書の作成

こちらのサイトを参考にlocalhost宛ての証明書を作成し、/ssl/ディレクトリに保存しました。nginxコンテナ内のconfファイルと、volumeを介してホスト側のunityクライアントでも参照出来るようにしました。

接続テスト

ここまでの作業でManicOnion-ServerとNGINX、サーバーのSSL化が完了しました。最後に残るのはunity側のSSL対応です。これは公式githubのasyncsumを呼び出すサンプルプログラムを下記のように書き変える。

最初にまずAssets配下のディレクトリに、

  • ルート証明書(localCA.crt)
  • サーバー証明書(localhost.crt)
  • サーバー鍵(localhost.key)

Assets配下に証明書を用意

この3つのファイルをコピーしておく。そしてそれらのファイルを元にキーペアを作り channel = GrpcChannel.ForAddress("https://localhost:5001");となっている部分をchannel = new Channel(host, port, new SslCredentials(cacert, keyCertificatePair));と書き換える。

using UnityEngine;
using Grpc.Core;

using MagicOnion.Client;
using MyApp.Shared.Services;
using System.IO;

public class controller : MonoBehaviour
{
    private Channel channel;
    void Start()
    {
        CallTest();
    }
    public async void CallTest()
    {
        // webサーバー(この場合はnginx)のIPと待ち受けport
        string host = "localhost";
        int port = 8080;

        // この辺で証明書関係の設定をする
        string cacert = File.ReadAllText("Assets/localCA.crt");
        string clientcert = File.ReadAllText("Assets/localhost.crt");
        string clientkey = File.ReadAllText("Assets/localhost.key");
        KeyCertificatePair keyCertificatePair = new KeyCertificatePair(
                clientcert,
                clientkey);


        channel = new Channel(host, port, new SslCredentials(cacert, keyCertificatePair));

        var client = MagicOnionClient.Create<IMyFirstService>(channel);

        var result = await client.SumAsync(100, 23);
        Debug.Log($"Result: {result}");

    }
    async void OnDestroy()
    {
        await this.channel.ShutdownAsync();
    }
}

SumAsyncメソッドの中身は公式サンプルのままです。MagicOnionサーバー、webサーバー(NGINX)を立ち上げてからunity上で実行してみると、実行結果の123が表示されるはずです。

実行結果

さいごに

onDestroy対応はきちんとしておきましょう。オレオレ証明書はあくまでもお試し用です。






このサイトをシェアする