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 6.3.1以降、新規作成されるMQTTリスナーの名前は以下の要件を満たす必要があります。

  • 名前は1〜64バイトの長さであること。
  • 名前はASCIIの英字または数字で始まること。
  • 名前はASCIIの英字、数字、ハイフン(-)、アンダースコア(_)のみを含むこと。

これらの要件を満たさない名前でのリスナー作成リクエストはEMQXによって拒否されます。アップグレード前に存在し、64バイトを超える名前のMQTTリスナーについては、設定の更新や削除は可能ですが、名前の変更はできません。

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

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

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

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

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

設定されたbind値は変更されません。例えば、bind = 1883は、リスナーが実行時に特定のIPアドレスを使用していてもポートのみの値として保持されます。

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

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

TCPリスナーの設定 ​

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

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ファイル。証明書がルートCAから直接発行されていない場合、中間CA証明書をリスナー証明書の後に連結してチェーンを形成します。
    • keyfile: SSL/TLS証明書に対応する秘密鍵を含むPEMファイル。

ノードごとに異なるアドレスを使用する ​

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

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

  1. ダッシュボードでTCPリスナーのbindを1883に設定するか、各ノードの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.confの値より優先されます。

    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は設定されたbindを、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_addressとresolved_address_fromは読み取り専用情報です。これらのレスポンスフィールドを編集してもアドレスは変更されません。アドレスを変更するにはbindやnode.default_listener_addressを変更してください。

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

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

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

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

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

設定されたヘッダーがWebSocketアップグレードリクエストに存在する場合、EMQXはヘッダー値の最初(左端)のエントリをクライアントの送信元IPアドレス(またはポート)として使用します。これにより、IPベースの認可ルール、禁止クライアント、フラッピング検出、監査・トレースログがクライアントの送信元IPとして認識するアドレスが決まります。設定されたヘッダー名は大文字小文字を区別せずにマッチします。

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

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

  • リスナーがクライアントに直接到達可能(プロキシなし)の場合は、proxy_address_headerとproxy_port_headerを空のままにし、EMQXが常に実際の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は認可ルールをリスナーのマウントポイントを付加しないトピックに対して評価します。マウントポイントは認可チェック後に追加されます。これはパブリッシュやサブスクライブ操作、Willメッセージに適用されます。

マウントポイント付きリスナーの場合、認可ルールはマウントされていないトピックに対して記述してください。例えばdepartment-a/secret/#に対する拒否ルールは、そのリスナー経由でsecret/#にパブリッシュやサブスクライブするクライアントにはマッチしません。

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

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

互換性の制限

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

機能トピックプレフィックス
Delayed Publish$delayed/
File Transfer$file/, $file-async/, $file-response/
Message Queue$queue/
MQTT Streams$stream/
Cluster Linking$LINK/
Dynamic Keep Alive Adjustment$SETOPTS/
A2A over MQTT$a2a/

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

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