Version: 2019.3
言語: 日本語
NetworkServerSimple
UnityWebRequest

Multiplayer 暗号化プラグイン

Unity Multiplayer は暗号化プラグインを使用できるため、ネットワーク経由で送信するすべてのデータは、送信される前に暗号化プラグインを通過します。これにより、 パケットの不正操作や専用ゲームサーバーへの攻撃からゲームを保護することができます。

Unity Multiplayer には暗号化プラグインがビルトインていないため、 暗号化アルゴリズムを実装する独自のプラグインを用意する必要があります。プラグインは、以下にリストされている必須機能を実装します。

以下の図は、Unity Multiplayer が暗号化プラグインが用意されている場合、それを使用する方法を示しています。

Unity Multiplayer で暗号化プラグインを使用する場合のデータフロー
Unity Multiplayer で暗号化プラグインを使用する場合のデータフロー

暗号化プラグインの使用方法

暗号化プラグインを使用するようにゲームやアプリケーションに指示するには、 UnityEngine.Networking.NetworkTransport.LoadEncryptionLibrary(path) を呼び出す必要があります。この path はコンパイルされたプラグインへのパスです。通常、Windows では、string.Format("{0}/Plugins/UnetEncryption.dll", Application.dataPath) です。

この関数を呼び出しと 、Unity はファイルが存在するか、それがすべての必須の関数 (リスト後述) を実装しているかをチェックします。これらは Unity のマルチプレイヤーシステム自体が呼び出す関数です。独自の暗号化プラグインを作成する場合は、C# コードから呼び出し関数を追加する必要があります。例えば、アルゴリズムを初期化したり、プラグインにキーバリューを提供したりします。これは、C# から呼び出し可能な ネイティブプラグインの通常の方法 で行うことができます。

ノート: ビルドされたバージョンのゲームでのプラグインの場所は、必ずしも Assets フォルダーと同じであるとは限りません。また、 ターゲットプラットフォームによって異なる場合があります。現在のランタイム 環境を検出し、それに基づいて正しいパスを選択するコードを作成する必要があるかもしれません。

Unity の GitHub から、サンプルの 暗号化プラグインとそれを使用したサンプル Unity プロジェクトを取得できます。これは、独自のプラグインを実装するための開始点を示すために提供されています。

必須の関数

作成または使用する暗号化プラグインは、以下の機能を提供する必要があります。Unity がプラグインを定義していない場合、プラグインの読み込みに失敗します。これらは Unity ランタイム自体によって呼び出される関数です。プラグインは通常、例えばキーを登録するために、ユーザーの C# コードから呼び出される 追加 の関数を提供します。

データの暗号化

int UNetEncryptionLib_Encrypt(
    void * payload,
    int payload_len,
    void * dest,
    int & dest_len,
    int connection_id,
    bool isConnect);

この関数は暗号化を実行します。これは、 パケットがネットワーク経由で送信されるときに Unity のネットワークによって呼び出されます。

パラメーター

  • payload は暗号化されるデータです。
  • payload_len は、payload バッファの長さ (バイト) です。
  • dest は、プラグインが暗号化されたデータを書き込むバッファです。
  • dest_len は、dest バッファの容量 (バイト) です。プラグインは、この値を実際に dest に書き込まれたバイト数に置き換える必要があります。
  • connection_id は接続のローカル識別子です。
  • isConnect は、このパケットが接続リクエストである場合に true を返します。これが true の場合、使用するキーは事前に (ゲームコードによって) プラグインに通知されている必要があります。これが false の場合、プラグインはこの値から使用するキーへのマッピングをすでにされていると想定されます。実装についてはサンプルプラグインを参照してください。

戻り値

Encrypt は成功すると 0 を返さなければなりません。その他の戻り値の場合、ランタイムはパケットを送信しません。

データを復号化するには

int UNetEncryptionLib_Decrypt(
    void * payload,
    int payload_len,
    void * dest,
    int & dest_len,
    int & key_id);

この関数は暗号解読を実行します。ネットワークからパケットを受信すると Unity ネットワークから呼び出されます。

パラメーター

  • payload は受信パケットです。
  • payload_len は、ペイロードバッファのバイト単位の長さです。
  • dest は、プラグインが復号化されたデータを書き込むバッファです。
  • dest_len は、dest バッファの容量 (バイト) です。プラグインは、この値を実際に dest に書き込まれたバイト数に置き換える必要があります。
  • key_id は整数の識別子です。プラグインは、使用する暗号解読 キーを一意に識別する値を書き込む必要があります。サーバーでは、新しい接続が受け入れられると、この値は ConnectionIdAssigned に渡されます。

戻り値

Decrypt は成功すると 0 を返す必要があります。その他の戻り値の場合、パケットはそれ以上処理されません。

SafeMaxPacketSize

unsigned short UNetEncryptionLib_SafeMaxPacketSize(
    unsigned short mtu);

NetworkTransport.AddHost を呼び出す前に、上の関数をゲームから呼び出し、ConnectionConfig.PacketSize (最大伝送ユニット 、または MTU) を変更する必要があります。

例えば、ゲームで通常 1000 バイトの MTU を使用するとします。NetworkTransport.AddHost (via HostConfig.DefaultConfig) に渡す前にConnectionConfig.PacketSize が 1000 バイトに設定されている場合、NetworkTransport レイヤーは 1 つのパケットで 1000 バイト以下の平文を送信します。

暗号化プラグインは通常、ペイロードの前に置かれるヘッダー情報のため、 オーバーヘッドがいくらか加わります。同様に、ペイロードの暗号化ブロックサイズへの切り上げも発生します。例えば、18 バイトの平文を送信し、プラグインが 49 バイトのヘッダーを追加し、AES を使用してブロックサイズが 16 バイトのデータを暗号化する必要がある場合、アルゴリズムは 81 バイトのパケット (18 バイト数の平文は 32 バイトの暗号文に切り上げられ、さらに 49 バイトのヘッダー) を作成します。

Unity はこの関数を呼び出して、ネットワーク MTU と暗号化アルゴリズムの暗号文の拡張とパディングを考慮して、送信しようとしているパケットが送信可能な制限を超えないようにします。

パラメーター

  • mtu は最大転送単位です。プラグインが生成する最大パケットサイズです。

戻り値

プラグインが MTU 以下のパケットを生成するために、Encrypt への 1 回の呼び出しに提供される平文の最大量です。

接続設定で最大パケットサイズを設定して、暗号化の要件に合うように Unity Multiplayer にデータを分割する必要があります。一部のメッセージがネットワーク上で正常に送信されない場合は、最大パケットサイズを超えたために中止された可能性があります。

ConnectionIdAssigned

void UNetEncryptionLib_ConnectionIdAssigned(
    int key_id,
    unsigned short connection_id);

新しい接続が受け入れられ ID が割り当てられる際に、上記がサーバー上で呼び出されます。

パラメーター

  • key_id - このパケットの Decryptへの対応する以前の呼び出しによって書き込まれたキー識別子。
  • connection_id - これ以降使用される接続 ID。特に、クライアントにパケットを送信するときに、後続の Encrypt 呼び出しのパラメーターとして使用されます。
NetworkServerSimple
UnityWebRequest