リスナー設定
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設定は、"0.0.0.0:1883"のような明示的なIPアドレスとポート、または1883のようなポートのみを指定できます。EMQX 6.3.0以降、ノードレベルのnode.default_listener_address設定が、ポートのみを指定したリスナーのアドレス選択を制御します。
EMQXは以下の順序でアドレスを選択します。
bindにIPアドレスが含まれている場合、そのアドレスを使用します。node.default_listener_addressやセキュリティプロファイルはこれを上書きしません。bindがポートのみで、かつnode.default_listener_addressが設定されている場合、その設定で選択されたアドレスを使用します。- それ以外の場合、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の同時接続を許可する設定は以下の通りです。
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の同時接続を許可する設定は以下の通りです。
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の同時接続を許可する設定は以下の通りです。
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の同時接続を許可する設定は以下の通りです。
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ノード名のホスト部分を使用する場合は以下のようにします。
ダッシュボードでTCPリスナーの
bindを1883に設定するか、各ノードのetc/base.hoconに以下を設定します。hoconlisteners.tcp.default.bind = 1883もし優先度の高い設定ソースで既に明示的な
bindアドレスが設定されている場合は、その設定ソースを更新してください。詳細はConfig Override Rulesを参照してください。各ノードの
emqx.confに以下を追加します。hoconnode.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はノード名の
@以降のホスト部分を使用し、ノード起動時にホスト名を解決します。解決できないホスト名はノード起動を妨げるため、各ノードで利用可能なアドレスに解決されることを確認してください。各ノードを再起動して
node.default_listener_addressを適用します。この設定はポートのみ指定のMQTTリスナー、ゲートウェイリスナー、ダッシュボードHTTPリスナーに影響します。明示的なIPアドレス指定は変更されません。
ノードの環境変数にEMQX_NODE__DEFAULT_LISTENER_ADDRESSを設定することも可能で、環境変数はemqx.confより優先されます。
リスナーアドレス情報の確認
EMQX 6.3.0以降、リスナーの設定されたbindを変更せずに解決済みアドレスとその情報源を確認できます。CLIまたはREST APIでノードに問い合わせます。
CLIでノードを問い合わせる
対象ノードで以下のコマンドを実行します。
emqx ctl listenerslisten_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以降、両オプションのデフォルトは空文字列""です。空の場合、EMQXは対応する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ヘッダーに追記(append)するだけで上書きや削除をしない場合(多くのプロキシのデフォルト動作、例:NGINXの$proxy_add_x_forwarded_for)、EMQXが読み取る左端のエントリは依然としてクライアントが供給したものであり、送信元IPの偽装が可能です。プロキシを設定してヘッダーを観測したアドレスで上書きするか、PROXYプロトコルを使用するか、オプションを空文字列に設定してください。 - 未使用のヘッダー名を指定してこの機能を無効化しようとしないでください。クライアントは任意の名前のヘッダーを送信可能であり、空文字列だけがクライアントが絶対に送信できない値です。
リスナーでproxy_protocol = trueが設定されている場合、クライアントアドレスはPROXYプロトコルのハンドシェイクから取得され、これらのヘッダーは参照されません。
リスナーを設定ゾーンにリンクする
EMQXの各リスナーはゾーンに関連付けられており、デフォルトでは論理ゾーンdefaultに設定されています。
リスナーが特定のゾーンにリンクされると、そのリスナーに接続するMQTTクライアントはそのゾーンの設定を継承します。
詳細は設定ドキュメントのZone Overrideセクションを参照してください。
マウントポイント
各リスナーはmountpointを設定できます。これは、リスナー経由で接続するクライアントが使用するトピックにEMQXが付加するトピックプレフィックスです。PUBLISHパケット、SUBSCRIBEおよびUNSUBSCRIBEリクエスト、Willメッセージのトピックにプレフィックスが追加され、クライアントに配信されるメッセージのトピックからはプレフィックスが除去されます。マウントポイントはクライアントに透過的であり、マルチテナント環境などでクライアントグループ間のトピック空間を分離するために一般的に使用されます。
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 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トピックに対して名前空間プレフィックスとして解析します。
共有サブスクリプション($share/{group}/)および排他サブスクリプション($exclusive/)は例外で、マウントポイントと共に動作します。EMQXはこれらのサブスクリプションプレフィックスをマウントポイント適用前に解析するため、マウントポイントは内部のトピックフィルターにのみ追加されます。例えば、マウントポイントmp/のリスナー経由で$share/g/tをサブスクライブすると、トピックmp/tの共有サブスクリプショングループgに参加します。