# マルチプロトコルゲートウェイ

EMQX マルチプロトコルゲートウェイは、MQTT以外のすべてのプロトコル接続、認証、およびメッセージの送受信を処理する機能を提供します。さまざまなプロトコルに対して統一された概念モデルを提供します。

EMQX 5.0以前は、MQTT以外のプロトコルアクセスは個別のプロトコルプラグインによって実装されていました。これらのプラグインは設計や実装が異なり、利用が困難でした。

5.0以降、EMQXはマルチプロトコルゲートウェイを提供し、統一された概念および運用モデルを定義することで、より使いやすくなっています。

マルチプロトコルゲートウェイは、MQTT-SN、STOMP、CoAP、LwM2Mなどのプロトコルをサポートします。Dashboardで直接有効化および設定できるほか、REST APIや`base.hocon`を使って管理可能です。これらのゲートウェイの有効化方法やビジネスニーズに合わせたカスタマイズ方法の詳細は、以下のリンクをご参照ください。

::: warning 重要なお知らせ
ExProtoゲートウェイはEMQX 6.2.0で非推奨となり、EMQX 6.3.0で削除されました。
:::

- [MQTT-SN](./mqttsn.md)
- [STOMP](./stomp.md)
- [CoAP](./coap.md)
- [LwM2M](./lwm2m.md)

- [OCPP](./ocpp.md)
- [GB/T 32960](./gbt32960.md)
- [JT/T 808](./jt808.md)
- [NATS](./nats.md)

## マルチプロトコルゲートウェイの仕組み

EMQX マルチプロトコルゲートウェイは、リスナー、接続／セッション、パブリッシュ／サブスクライブ、認証、認可などの主要コンポーネントに対して統一された概念および運用モデルを定義しています。

<img src="./assets/gateway_struct.png" alt="gateway_struct" style="zoom:50%;" />

各コンポーネントの概要は以下の通りです。

- **リスナー**：TCP、SSL、UDP、DTLSのリスナータイプをサポートします。各ゲートウェイは複数のリスナーを作成可能です。
- **接続／セッション**：ゲートウェイは受け入れたクライアント接続ごとにセッションを作成し、サブスクリプションリスト、配信／受信キュー、クライアントメッセージの再送制御を管理します。
- **パブリッシュ／サブスクライブ**：各ゲートウェイタイプは、MQTTプロトコルのPUB/SUBメッセージモデルに適応する方法を定義します。PUB/SUBを持たないプロトコルはメッセージのトピックやペイロードを設定する必要があり、ゲートウェイタイプごとに異なるメッセージフォーマットを使用する場合があります。
- **認証**：各ゲートウェイは認証機構を設定でき、クライアント情報を用いたログイン認可が可能です。

## ゲートウェイリスナー

各ゲートウェイは複数のリスナーを有効化でき、異なるプロトコルゲートウェイは以下のリスナータイプをサポートします。

|            | TCP  | UDP  | SSL  | DTLS | Websocket | Websocket over TLS |
| ---------- | ---- | ---- | ---- | ---- | --------- | ------------------ |
| MQTT-SN    |      | ✔︎    |      | ✔︎    |           |                    |
| STOMP      | ✔︎    |      | ✔︎    |      |           |                    |
| CoAP       |      | ✔︎    |      | ✔︎    |           |                    |
| LwM2M      |      | ✔︎    |      | ✔︎    |           |                    |
| OCPP       |      |      |      |      | ✔︎         | ✔︎                  |
| GB/T 32960 | ✔︎    |      | ✔︎    |      |           |                    |
| JT/T 808   | ✔︎    |      |      | ✔︎    |           |                    |
| NATS       | ✔︎    |      | ✔︎    |      | ✔︎         | ✔︎                  |

EMQX 6.3.1以降、新規作成されるゲートウェイリスナーの名前は1〜64バイトの長さで、ASCIIの英数字で始まり、ASCIIの英数字、ハイフン（`-`）、アンダースコア（`_`）のみを含む必要があります。この要件を満たさない場合、REST APIはHTTP `400`レスポンスと`BAD_REQUEST`エラーコードを返します。アップグレード前に存在した64バイトを超える名前のリスナーは、設定の更新や削除は可能ですが、名前の変更はできません。

### バインドアドレス

ゲートウェイリスナーの`bind`設定は、クライアントトラフィックを受け取るローカルのアドレスとポートを指定します。明示的なIPアドレスとポート、またはポートのみを受け付けます。

EMQX 6.3.0以降、`bind`がポートのみを指定する場合は、ノードレベル設定の`node.default_listener_address`がデフォルトのバインドアドレスとして使用されます。`bind`に明示的なIPアドレスとポートがある場合はそちらが優先されます。この設定がない場合、`legacy`および`hardened`セキュリティプロファイルの両方で、ポートのみのバインドはすべてのネットワークインターフェースでリスンします。

ポートのみのバインドで使用するアドレスを変更するには、各ノードの`emqx.conf`または`EMQX_NODE__DEFAULT_LISTENER_ADDRESS`で設定し、変更後にノードを再起動してください。この設定はMQTTリスナーやDashboardのHTTPリスナーのポートのみバインドにも影響します。対応する値や公式Dockerイメージのデフォルトは[Default Listener Address](../../guides/access-control/security-profile.md#default-listener-address)をご覧ください。

### リスナーアドレス情報の確認

ゲートウェイリスナーのアドレスを確認するには、`GET /api/v5/gateways/:name/listeners`を使用します。`:name`はゲートウェイ名（例：`stomp`）に置き換えてください。EMQX 6.3.0以降、各リスナーの`node_status[].status`には`resolved_address`と`resolved_address_from`が含まれます。各`node_status`エントリは対応するノードの値を報告し、クラスター全体の`status`にはこれらのノードローカルフィールドは含まれません。

各`node_status`エントリでは、`status.running`と`status.resolved_address`を合わせて確認し、そのノードでリスナーが稼働しているか判断してください。空の`resolved_address`の解釈については[リスナーアドレス情報の確認](../../guides/configuration/listener.md#view-listener-address-information)をご参照ください。ゲートウェイリストエンドポイントを使用し、MQTTの`emqx ctl listeners`コマンドやゲートウェイの単一リスナー設定エンドポイントは使用しないでください。

## メッセージフォーマット

PUB/SUBメッセージモデルとの互換性を確保するため、各ゲートウェイタイプは基盤となるプロトコルにPUB/SUB概念があるか否かに適応する必要があります。

[MQTT-SN](./mqttsn.md)や[STOMP](./stomp.md)のようにPUB/SUB概念を持つプロトコルでは、クライアントが送信するトピックとペイロードを使用し、メッセージフォーマットの変換は不要です。

[CoAP](./coap.md)や[LwM2M](./lwm2m.md)のようにPUB/SUB概念を持たないプロトコルでは、トピックやパブリッシュ、サブスクライブの定義がありません。この場合、ゲートウェイがメッセージ内容のフォーマットを設計し、各タイプで異なるフォーマットを使用する可能性があります。

- **CoAP**：CoAPゲートウェイは[Publish-Subscribe Broker for the CoAP](https://datatracker.ietf.org/doc/html/draft-ietf-core-coap-pubsub-09)標準で定義されたURIパスとメソッドを使用します。詳細は[メッセージパブリッシュ](./coap.md#message-publish)、[トピックサブスクライブ](./coap.md#topic-subscribe)、[トピックサブスクライブ解除](./coap.md#topic-unsubscribe)をご覧ください。
- **LwM2M**：LwM2Mプロトコルのメッセージモデルは[Resources Model and Operations](https://technical.openmobilealliance.org/OMNA/LwM2M/LwM2MRegistry.html)に基づいており、MQTTのパブリッシュ／サブスクライブモデルとは全く異なります。詳細は[LwM2Mゲートウェイ - メッセージフォーマット](./lwm2m.md#message-format)をご覧ください。

## 認証

認証は、システムに接続しようとするクライアントの身元を検証するプロセスです。バージョン5.0以降、ゲートウェイはログイン認可のための認証機構をサポートしています。

ゲートウェイによってサポートされる認証機構は異なりますが、すべてのゲートウェイはHTTPベースの認証をサポートしています。[HTTPベース認証](../../guides/access-control/authn/http.md)。以下の表はサポートされる認証タイプの一覧です。

|            | HTTPサーバー | 組み込みデータベース | MySQL | MongoDB | PostgreSQL | Redis | JWT  | LDAP |
| ---------- | ----------- | ----------------- | ----- | ------- | ---------- | ----- | ---- | ---- |
| MQTT-SN    | ✔︎           |                   |       |         |            |       |      |      |
| STOMP      | ✔︎           | ✔︎                 | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| CoAP       | ✔︎           | ✔︎                 | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| LwM2M      | ✔︎           |                   |       |         |            |       |      |      |
| OCPP       | ✔︎           | ✔︎                 | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |
| GB/T 32960 | ✔︎           |                   |       |         |            |       |      |      |
| JT/T 808   | N/A         | N/A               | N/A   | N/A     | N/A        | N/A   | N/A  |      |
| NATS       | ✔︎           | ✔︎                 | ✔︎     | ✔︎       | ✔︎          | ✔︎     | ✔︎    | ✔︎    |

### ゲートウェイにおける認証の仕組み

EMQX マルチプロトコルゲートウェイは、クライアント認証のために接続ごとに`ClientInfo`を作成します。`ClientInfo`には、認証で一般的に使用される`Username`や`Password`などの汎用フィールドが含まれます。各ゲートウェイは、LwM2Mの`Endpoint Name`など、プロトコル固有のフィールドを追加して認証に利用できます。

認証機構が設定されている場合、ゲートウェイは`ClientInfo`を用いて設定された認証方式とバックエンドに基づきクライアントを検証します。データベースベースのパスワード認証では、認証機構がクライアントの`Username`と`Password`をデータベース内の資格情報と照合します。資格情報が一致すればクライアントは認証され、ゲートウェイへのアクセスが許可されます。認証機構が設定されていない場合は、すべてのクライアントがログイン可能です。

EMQX 6.3.1以降、ゲートウェイ認証結果は以下のように適用されます。

- ゲートウェイプロトコルは常にプロトコルによって決定されたクライアントIDを使用します。これにより、認証結果によるクライアントの識別子の変更が防止され、接続ライフサイクルを通じて識別子が一貫します。認証機構が`clientid_override`を返した場合、EMQXはこのフィールドを無視し、`gateway_authn_clientid_override_not_supported`の警告をログに記録します。
- 認証成功後、EMQXはゲートウェイおよびリスナーレベルのマウントポイントテンプレートを、クライアント情報と認証結果の組み合わせで評価します。マウントポイントテンプレートは認証機構が返すクライアント属性を参照可能で、例えば`${client_attrs.tenant}/`のように使用できます。

::: tip クライアントIDとセッションの挙動

クライアントIDは異なるゲートウェイ間で重複可能です。同一ゲートウェイ内で重複するクライアントIDで接続した場合、既存の同一クライアントIDに紐づくセッションは切断されます。

:::

## 外部システムとの連携

外部システムとの連携を強化するため、ゲートウェイはEMQXで定義されたフックもサポートしています。

ゲートウェイ間で意味論の異質性があるため、コアフックの一部のみ利用可能です。

クライアント接続関連のフックの対応状況は以下の通りです。

外部システムとの相互運用性向上のため、ゲートウェイはEMQXで定義されたフックをサポートする設計となっています。

しかし、各ゲートウェイ間の意味論の違いにより、利用可能なコアフックは一部に限られます。以下の表はクライアント接続関連のサポートされるフックです。

| 名前                   | 必須かどうか | 説明                                                            | 対応プロトコル       |
| ---------------------- | ------------ | --------------------------------------------------------------- | -------------------- |
| `client.connect`       | 任意         | クライアント接続要求の回数（成功・失敗を含む）                   | すべてのゲートウェイ |
| `client.connack`       | 任意         | クライアントが受信した`CONNACK`メッセージの回数                  | すべてのゲートウェイ |
| `client.authenticate`  | 必須         | 認証されたクライアントの回数                                     |                      |
| `client.connected`     | 必須         | 正常に接続したクライアントの回数                                 | すべてのゲートウェイ |
| `client.disconnected`  | 必須         | 切断したクライアントの回数（正常・異常切断を含む）               | すべてのゲートウェイ |
| `client.authorize`     | 必須         | 認可されたクライアントのパブリッシュ／サブスクライブ要求の回数    | すべてのゲートウェイ |
| `client.subscribe`     | 任意         | クライアントのトピックサブスクライブ試行回数                     | MQTT-SN<br />STOMP   |
| `client.unsubscribe`   | 任意         | クライアントのトピックサブスクライブ解除試行回数                 | MQTT-SN<br/>STOMP    |

セッションおよびメッセージ関連のフックはプロトコル間の異質性がないため、各ゲートウェイタイプで完全にサポートされています。

フックの詳細については[フック](../../guides/extensions/hooks.md)をご覧ください。
