Skip to content

リスナー設定

EMQXでは、リスナーはMQTTクライアントからのリクエストを受け取るために設定されます。EMQXは以下のメッセージ転送プロトコルをサポートしています。

  • TCP: ポート 1883
  • SSL: ポート 8883
  • WebSocketリスナー: 8083
  • セキュアWebSocketリスナー: 8084

TIP

リスナーはダッシュボードの左側ナビゲーションメニューの Management -> Listeners からも設定可能です。
設定ファイルからリスナーを設定する場合は、emqx.confではなくbase.hoconの使用を推奨します。
これは、emqx.confで設定した場合、ダッシュボードからの変更は一時的なものとなり、EMQX再起動時に失われるためです。

TIP

EMQXはカスタマイズニーズに対応するため、より多くの設定項目を提供しています。詳細はEMQX Enterprise Configuration Manualをご参照ください。

EMQXがリスナーアドレスを決定する方法

リスナーアドレスは、EMQXがクライアント接続を受け付けるローカルのネットワークインターフェースとポートを決定します。

リスナーのbind設定は、"0.0.0.0:1883"のような明示的なIPアドレスとポート、または1883のようなポートのみを受け入れます。EMQX 6.3.0以降では、ノードレベルのnode.default_listener_address設定が、ポートのみを指定したリスナーのアドレス決定を制御します。

EMQXは以下の順序でアドレスを選択します。

  1. bindにIPアドレスが含まれている場合、EMQXはそのアドレスを使用します。node.default_listener_addressやセキュリティプロファイルはこれを上書きしません。
  2. bindがポートのみでnode.default_listener_addressが設定されている場合、EMQXはその設定で選択されたローカルノードのアドレスを使用します。
  3. それ以外の場合、MQTTリスナーはセキュリティプロファイルのデフォルトを使用します。legacyでは全ネットワークインターフェース、hardenedではループバックアドレスです。ループバックアドレスはローカルホストからのみアクセス可能です。

設定されたbind値は変更されません。例えば、bind = 1883は実行時に特定のIPアドレスが使われてもポートのみの値のままです。

以下のTCP、SSL、WebSocketの設定例は明示的なIPアドレスを使用しているため、デフォルトリスナーアドレス設定の影響を受けません。

サポートされる値や起動時の挙動についてはDefault Listener Addressを参照してください。公式Dockerイメージは独自のデフォルトを設定しているため、Listener Addresses in Dockerもご確認ください。

TCPリスナーの設定

TCPリスナーは特定のネットワークポートでのTCP接続を待ち受けるネットワークサービスです。クライアントとEMQX間のTCP/IPネットワーク上の接続確立と管理に重要な役割を果たします。

EMQXでTCPリスナーを設定するには、EMQXインストールディレクトリのetcフォルダ内のbase.hoconファイルにlisteners.tcpの設定項目を追加します。

例えば、ポート1883でTCPリスナーを有効化し、リスナーが許可する最大同時接続数を1,024,000に設定する場合、以下のように記述します。

bash
listeners.tcp.default {
  bind = "0.0.0.0:1883"
  max_connections = 1024000
}

ここで、

  • listeners.tcp.defaultはリスナーを有効化する設定で、defaultはリスナー名です。任意の名前に変更可能です。
  • bindはリスナーのIPアドレスとポートを設定し、ここでは任意のIPアドレスからのポート1883への全ての着信トラフィックを待ち受けます。
  • max_connectionsはリスナーが許可する最大同時接続数を設定します。デフォルトはinfinityです。

SSLリスナーの設定

SSLリスナーはSSL(Secure Sockets Layer)接続を待ち受けるネットワークサービスです。EMQXではクライアントとEMQX間の通信を暗号化して保護するために使用されます。

EMQXでSSLリスナーを設定するには、etcフォルダ内のbase.hoconファイルにlisteners.sslの設定項目を追加します。

例えば、ポート8883でSSLリスナーを有効化し、最大同時接続数を1,024,000に設定する場合は以下のようにします。

bash
listeners.ssl.default {
  bind = "0.0.0.0:8883"
  max_connections = 1024000
  ssl_options {
    cacertfile = "etc/certs/cacert.pem"
    certfile = "etc/certs/cert.pem"
    keyfile = "etc/certs/key.pem"
    verify = verify_none
    fail_if_no_peer_cert = false
  }
}

ここで、

  • listeners.ssl.defaultはリスナーを有効化します。
  • bindはリスナーのIPアドレスとポートで、任意のIPアドレスからのポート8883への全ての着信トラフィックを待ち受けます。
  • max_connectionsは最大同時接続数で、デフォルトはinfinityです。
  • ssl_optionsはリスナーのSSL/TLS設定で、以下のプロパティがあります。
    • cacertfile: クライアント証明書の真正性を検証するために使用する信頼されたCA(認証局)証明書を含むPEMファイル。
    • certfile: リスナー用のSSL/TLS証明書チェーンを含むPEMファイル。証明書がルートCAから直接発行されていない場合、中間CA証明書をリスナー証明書の後に連結してチェーンを形成します。
    • keyfile: SSL/TLS証明書に対応する秘密鍵を含むPEMファイル。
    • verify: クライアント証明書の真正性を検証する場合はverify_peer、しない場合はverify_noneを設定します。
    • fail_if_no_peer_cert: trueの場合、クライアントが証明書を送信しない(空の証明書を送る)とサーバーは接続を拒否します。falseの場合は無効な証明書を送信した場合のみ拒否し、空の証明書は有効とみなします。

WebSocketリスナーの設定

WebSocketリスナーはWebSocketを介してメッセージを受信・処理するネットワークサービスです。EMQXのWebSocketサポートにより、クライアントはWebSocketプロトコルを使ってEMQXに接続し、リアルタイムでデータ交換が可能です。

MQTT over WebSocketの仕組みや典型的な利用シナリオについてはMQTT over WebSocketをご覧ください。

EMQXでWebSocketリスナーを設定するには、etcフォルダ内のbase.hoconファイルにlisteners.wsの設定項目を追加します。

例えば、ポート8083でWebSocketリスナーを有効化し、最大同時接続数を1,024,000に設定する場合は以下のようにします。

bash
listeners.ws.default {
  bind = "0.0.0.0:8083"
  max_connections = 1024000
  websocket.mqtt_path = "/mqtt"
}

ここで、

  • listeners.ws.defaultはリスナーを有効化します。
  • bindはIPアドレスとポートで、任意のIPアドレスからのポート8083への全ての着信トラフィックを待ち受けます。
  • max_connectionsは最大同時接続数で、デフォルトはinfinityです。
  • websocket.mqtt_pathはWebSocketのMQTTプロトコルのパスを設定し、デフォルトは/mqttです。

セキュアWebSocketリスナーの設定

セキュアWebSocketリスナーは、SSLまたはTLSプロトコルを使用してWebSocketクライアントとブローカー間のデータを暗号化するWebSocketリスナーです。EMQXでは、WebSocketクライアントとEMQX間で交換される機密データを保護する重要なセキュリティ対策となっています。

EMQXでセキュアWebSocketリスナーを設定するには、etcフォルダ内のbase.hoconファイルにlisteners.wssの設定項目を追加します。

例えば、ポート8084でセキュアWebSocketリスナーを有効化し、最大同時接続数を1,024,000に設定する場合は以下のようにします。

bash
listeners.wss.default {
  bind = "0.0.0.0:8084"
  max_connections = 1024000
  websocket.mqtt_path = "/mqtt"
  ssl_options {
    cacertfile = "etc/certs/cacert.pem"
    certfile = "etc/certs/cert.pem"
    keyfile = "etc/certs/key.pem"
  }
}

ここで、

  • listeners.wss.defaultはリスナーを有効化します。
  • bindはIPアドレスとポートで、任意のIPアドレスからのポート8084への全ての着信トラフィックを待ち受けます。
  • max_connectionsは最大同時接続数で、デフォルトはinfinityです。
  • websocket.mqtt_pathはWebSocketのMQTTプロトコルのパスを設定し、デフォルトは/mqttです。
  • ssl_optionsはSSL/TLS設定で、以下のプロパティがあります。
    • cacertfile: クライアント証明書の真正性を検証するための信頼されたCA証明書を含むPEMファイル。
    • certfile: リスナー用のSSL/TLS証明書チェーンを含むPEMファイル。
    • keyfile: SSL/TLS証明書に対応する秘密鍵を含むPEMファイル。

各ノードで異なるアドレスを使用する

ダッシュボード、REST API、CLIを通じて行ったリスナー設定の変更はクラスター全体に複製されます。bindに特定ノードのIPアドレスを設定すると、そのIPアドレスが他ノードのローカルネットワークインターフェースに設定されていない限り、他ノードではバインドできません。各ノードで異なるアドレスを使用するには、リスナーのbindをポートのみとし、ノードごとにデフォルトアドレスを別途設定してください。

リスナー設定はbase.hoconで行い、ノードレベルのデフォルトリスナーアドレスはemqx.confまたは環境変数で設定します。例えば、各ノードのErlangノード名のホスト部を使用する場合は以下の手順です。

  1. ダッシュボードでTCPリスナーのbind1883に設定するか、各ノードのetc/base.hoconに以下を設定します。

    hocon
    listeners.tcp.default.bind = 1883

    もし優先度の高い設定ソースで既に明示的なバインドアドレスが設定されている場合は、その設定ソースを更新してください。詳細はConfig Override Rulesを参照してください。

  2. 各ノードのemqx.confに以下を追加します。

    hocon
    node.default_listener_address = "nodename"

    Docker環境の場合は、docker run-e EMQX_NODE__DEFAULT_LISTENER_ADDRESS=nodenameを渡すか、Docker ComposeのenvironmentセクションにEMQX_NODE__DEFAULT_LISTENER_ADDRESS: nodenameを設定してください。これは公式イメージのallデフォルトを上書きします。

    EMQXはノード名の@以降のホスト部を使用し、ノード起動時にホスト名を解決します。ノードで利用可能なアドレスに解決されることを確認してください。解決できないホスト名はノードの起動を妨げます。

  3. 各ノードを再起動してnode.default_listener_addressを適用します。この設定はポートのみのバインドに対してMQTTリスナー、ゲートウェイリスナー、ダッシュボードHTTPリスナーに影響します。明示的なIPアドレスを指定したリスナーのバインドは変更されません。

環境変数EMQX_NODE__DEFAULT_LISTENER_ADDRESSをノードの環境に設定することも可能で、環境変数はemqx.confより優先されます。

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

EMQX 6.3.0以降、リスナーの設定済みbindを変更せずに解決済みアドレスとその情報源を確認できます。CLIまたはREST APIでノードをクエリしてください。

CLIでノードをクエリする

確認したいノード上で以下のコマンドを実行します。

bash
emqx ctl listeners

listen_onは設定されたバインド、resolved_addressは解決済みIP、resolved_address_fromはアドレスの情報源を示します。runningでリスナーが稼働中かも確認可能です。停止中のリスナーでも解決済みアドレスを報告する場合があります。各フィールドの意味はListener Address Informationを参照してください。resolved_addressが空の場合の意味も記載されています。

REST APIでリスナーをクエリする

REST APIでリスナーを確認するには、GET /api/v5/listeners/:idを使用します。例:GET /api/v5/listeners/tcp:default。レスポンスはリクエストを処理したノードのアドレスを報告します。必要に応じてAPI認証を行ってください。

bindフィールドは設定値(ポート含む)を保持し、resolved_addressresolved_address_fromは読み取り専用の情報です。アドレスを変更するにはbindまたはnode.default_listener_addressを変更してください。これらのレスポンスフィールドを編集しても反映されません。

これらのクエリはMQTTリスナーに対応しています。ゲートウェイリスナーはゲートウェイリスナーのクエリを参照してください。

転送元クライアントアドレス(WebSocketリスナー)

WebSocketおよびセキュアWebSocketリスナーは、リスナーがプロキシやロードバランサーの背後にある場合にクライアントの送信元アドレスを決定する方法を制御する2つのオプションを持ちます。

  • websocket.proxy_address_header: クライアントIPアドレスを含むHTTPヘッダー名を指定します。
  • websocket.proxy_port_header: クライアントポートを含むHTTPヘッダー名を指定します。

EMQX 6.3.0以降、両オプションのデフォルトは空文字列""です。空の場合はEMQXは対応するTCPピアアドレスまたはポートを使用します。信頼できるプロキシから値を取得するには、x-forwarded-forx-forwarded-portなどのヘッダー名を明示的に設定してください。

設定されたヘッダーがWebSocketアップグレードリクエストに存在すると、EMQXはヘッダー値の最初(左端)のエントリをクライアントの送信元IPアドレス(またはポート)として使用し、実際のTCPピアのアドレスではなくなります。派生したアドレスはIPベースの認可ルール、禁止クライアント、フラッピング検出、監査・トレースログでクライアントの送信元IPとして扱われます。設定されたヘッダー名は大文字・小文字を区別しません。

信頼できるプロキシの背後でのみ転送元アドレスヘッダーを信用してください

ヘッダー値はEMQXが使用するクライアント送信元IPを決定するため、信頼できるプロキシが設定した場合にのみ尊重すべきです。

  • リスナーがクライアントから直接アクセス可能(プロキシなし)の場合は、proxy_address_headerproxy_port_headerを空にして、常に実際のTCPピアアドレスを使用してください。
  • プロキシが存在しても、受信したX-Forwarded-Forヘッダーに追記する(上書きや削除しない)場合(多くのプロキシのデフォルト動作、例:NGINXの$proxy_add_x_forwarded_for)、EMQXが読み取る左端のエントリはクライアントが送信したもののままであり、送信元IPを偽装される可能性があります。プロキシを設定してヘッダーを観測したアドレスで上書きするか、PROXYプロトコルを使用するか、オプションを空文字列に設定してください。
  • 未使用のヘッダー名を指定してこの仕組みを無効化しようとしないでください。クライアントは任意の名前のヘッダーを送信可能であり、空文字列のみがクライアントが絶対に送信できない値です。

リスナーでproxy_protocol = trueが設定されている場合、クライアントアドレスはPROXYプロトコルのハンドシェイクから取得され、これらのヘッダーは参照されません。

リスナーを設定ゾーンに紐付ける

EMQXの各リスナーはゾーンに紐付けられており、デフォルトではdefaultという論理ゾーンに設定されています。

リスナーが特定のゾーンに紐付けられると、そのリスナーに接続するMQTTクライアントはそのゾーンの設定を継承します。

詳細は設定ドキュメントのZone Overrideセクションを参照してください。

マウントポイント

各リスナーはmountpointを設定できます。これは、リスナー経由で接続するクライアントが使用するトピックにEMQXが追加するトピックプレフィックスです。プレフィックスはPUBLISHパケット、SUBSCRIBEおよびUNSUBSCRIBEリクエスト、Willメッセージのトピックに追加され、クライアントに配信されるメッセージのトピックからは削除されます。マウントポイントはクライアントには透過的であり、マルチテナント環境などでクライアントグループ間のトピック空間を分離するためによく使用されます。

bash
listeners.tcp.demo {
    bind = "0.0.0.0:1883"
    mountpoint = "department-a/"
}

マウントポイントは${clientid}, ${username}, ${zone}, ${client_attrs.NAME}のプレースホルダーをサポートします。例えば、mountpoint = "${username}/"の場合、ユーザー名u1のクライアントがsensors/#をサブスクライブすると、内部的にはu1/sensors/#としてサブスクライブされます。

トピックプレフィックス拡張機能との非互換性

EMQXのいくつかの機能は、特別な$プレフィックスで始まるトピックのパブリッシュやサブスクライブによってトリガーされます。EMQXはマウントポイントのプレフィックスをこれらのプレフィックスのマッチング前に追加します。例えば、マウントポイントmp/のリスナー経由でクライアントが$delayed/10/tにパブリッシュすると、ブローカーはmp/$delayed/10/tとして受け取り、もはや$delayed/で始まらないため機能は無効化されます。EMQXはメッセージを通常のマウントされたリテラルトピックとしてルーティングし、クライアントにエラーは報告されません。

互換性の制限

以下の機能を使用するクライアントが接続するリスナーにはマウントポイントを設定しないでください。

機能トピックプレフィックス
遅延パブリッシュ$delayed/
ファイル転送$file/, $file-async/, $file-response/
メッセージキュー$queue/
MQTT Streams$stream/
クラスターリンク$LINK/
動的キープアライブ調整$SETOPTS/
A2A over MQTT$a2a/

クラスターリンクの場合、リンク先クラスターからの接続を受け入れるリスナーにはマウントポイントを設定してはいけません。A2A over MQTTの場合、ちょうど1トピックレベル(例:acme/)のマウントポイントは動作します。EMQXは$a2aトピックの名前空間プレフィックスとして解析します。

共有サブスクリプション$share/{group}/)および排他サブスクリプション$exclusive/)は例外で、マウントポイントと共に動作します。EMQXはこれらのサブスクリプションプレフィックスをマウントポイント適用前に解析し、マウントポイントは内部のトピックフィルターにのみ追加されます。例えば、マウントポイントmp/のリスナー経由で$share/g/tをサブスクライブすると、共有サブスクリプショングループgはトピックmp/tに参加します。