Skip to content

SSL/TLS接続の有効化

EMQXは、MQTTクライアントのアクセスを受け入れる際に、SSL/TLSを介して安全な接続を確立できます。SSL/TLS暗号化機能はトランスポート層でネットワーク接続を暗号化し、通信データのセキュリティを強化するとともに、その完全性を保証します。

本ページでは、SSL/TLS接続の機能と利点、およびクライアントとEMQX間でのSSL/TLS接続の確立方法について紹介します。

セキュリティ上の利点

SSL/TLS接続を有効にすることで、以下のセキュリティ上の利点が得られます。

  1. 強力な認証:通信する双方が相手のX.509デジタル証明書を検証して身元を確認します。これらの証明書は通常、信頼された認証局(CA)によって発行されており、偽造できません。
  2. 機密性:各セッションは双方で交渉されたセッションキーを用いて暗号化されます。第三者が通信内容を知ることはできず、仮にセッションキーが漏洩しても他のセッションのセキュリティには影響しません。
  3. 完全性:暗号化通信においてデータが改ざんされる可能性は極めて低くなります。

2つの利用モード

MQTT接続を含むすべての接続に対してSSL/TLS暗号化接続を有効にし、アクセスおよびメッセージ送信のセキュリティを確保できます。クライアントのSSL/TLS接続については、利用シナリオに応じて以下の2つのモードから選択可能です。

利用モード利点欠点
クライアントとEMQX間で直接SSL/TLS接続を確立する。利用が簡単で追加コンポーネントが不要。EMQXのリソース消費が増加し、接続数が膨大な場合はCPUやメモリの消費が高くなる可能性がある。
プロキシまたはロードバランサーでTLS接続を終了させる。EMQXのパフォーマンスに影響を与えず、ロードバランシング機能を提供。TCP SSL/TLS終了をサポートするクラウドベンダーのロードバランサーは限られている。また、ユーザー側でHAProxyなどのソフトウェアを自前でデプロイする必要がある。

プロキシやロードバランサーでTLS接続を終了させる方法については、クラスターのロードバランシングを参照してください。

一方向/双方向認証

EMQXは包括的なSSL/TLS機能をサポートしており、X.509証明書を用いた一方向認証および双方向(相互)認証の両方を実現できます。

認証方式説明検証方法長所と短所
一方向認証クライアントがサーバーの身元を検証するが、サーバーはクライアントの身元を検証しない。クライアントは通常証明書を提供せず、サーバー証明書が信頼されたCAによって発行されていることのみを検証。通信データの機密性と完全性は保証できるが、通信相手の身元は保証できない。
双方向認証サーバーとクライアントがお互いの身元を相互に検証する。各デバイスに証明書を発行し、サーバーがクライアント証明書の正当性を検証。サーバーとクライアント間の相互信頼を確立し、中間者攻撃を防止できる。

SSL/TLS証明書

SSL/TLSを有効にする前に、認証および接続のセキュリティ確保のためにSSL/TLS証明書を準備する必要があります。

EMQXは従来のパスベース証明書と、EMQX 6.1以降で導入された管理証明書の両方をサポートしており、管理証明書は集中管理やリスナー・コネクター間での再利用が可能です。

EMQXでのSSL/TLS証明書の取得、管理、利用に関する完全なガイドはSSL/TLS証明書を参照してください。

一方向認証でのSSL/TLS有効化

デフォルトで、EMQXはポート8883でSSL/TLSリスナーを有効にし、一方向認証(クライアントはサーバー証明書を検証するが、サーバーはクライアント証明書を検証しない)に設定されています。

SSL/TLSリスナーはダッシュボードまたは設定ファイルで構成可能です。いずれの場合も、EMQXは以下の2つの証明書プロビジョニング方法をサポートします。

  • パスベース証明書(従来のPEMファイル):設定でファイルパスを直接参照。
  • 管理証明書(EMQX 6.1以降):再利用可能なリソースとして管理し、名前で参照。

運用モデルやデプロイに最適な方法を選択してください。

ダッシュボードでの有効化

  1. Management -> Listeners に移動します。

  2. SSLリスナーのうち、名前がdefaultのものをクリックしてEdit Listenerページを開きます。

  3. 以下のSSL/TLS設定を行います。

    • Verify Peer:一方向認証ではデフォルトで無効です。無効の場合、EMQXはクライアント証明書を検証しません。

    • Force Verify Peer CertificateVerify Peerが有効な場合にのみ適用されます。一方向認証では無効のままにしてください。

    • Session Tickets:TLS 1.3のセッション再開を有効にします。クライアントはサーバーが発行した暗号化されたセッションチケットを提示することで、再接続時に完全なTLSハンドシェイクを省略でき、レイテンシとCPU使用率を低減します。

      • disabled:セッションチケットを無効化(デフォルト)。接続ごとに完全なTLSハンドシェイクを実施。
      • stateless:ステートレスセッションチケットを有効化。サーバーはセッション状態を保持せず、再接続性能が向上します。証明書情報は再開後利用できないため、証明書ベースの認証や認可が不要な場合に適します。
      • stateless_with_cert:証明書情報を含むステートレスセッションチケットを有効化。再開後も証明書情報が利用可能で、mTLSなど証明書ベース認証に適しますが、ネットワーク帯域の使用量が若干増加します。

      注意

      セッションチケットを生成するには、ノードレベルのオプションnode.tls_stateless_tickets_seedに空でない文字列(例:node.tls_stateless_tickets_seed = "averysecuresecret")を設定する必要があります。リスナーでセッションチケットを有効にしてもこの設定がない場合、チケットは生成されません。

      セッションチケットはTLS 1.3でのみサポートされ、クラスタ環境のスケーラビリティ確保のためステートレスモードのみ対応しています。TLS 1.2のステートフルセッション再開はEMQXでサポートされていません。

      また、EMQXはクライアントの早期データ送信(0-RTT)もサポートしていません。クライアントはTLSハンドシェイク完了までMQTTデータを送信できません。

    • Certificate Source:サーバー証明書の提供方法を選択します。

      • Enter Manually:従来のパスベース証明書を使用。以下の項目を設定します。

        • TLS Cert:サーバー証明書ファイルのパス。
        • TLS Key:秘密鍵ファイルのパス。
      • Select from Managed Certs:管理証明書バンドルを使用(EMQX 6.1以降)。以下の項目を設定します。

        • Namespace:管理証明書バンドルが格納されているネームスペース(デフォルトはglobal)。
        • Managed Cert Bundle Name:既存の管理証明書バンドルを選択。新規作成はCreate Managed Certsをクリック。詳細はダッシュボードから証明書バンドルを作成を参照。
        • SNI(任意):同一リスナーに複数証明書が設定されている場合に証明書を識別するためのServer Name Indication値。

        複数の管理証明書エントリは**+**ボタンで追加可能です。

        複数証明書が設定されている場合、EMQXはクライアントのSNIに基づき証明書を動的に選択し、SNIが一致しない場合はリストの最初の証明書をデフォルトとして使用します。

    • SSL Versions:TLS/DTLSのすべてのバージョンをサポート。デフォルトはtlsv1.3tlsv1.2です。PSK認証でPSK暗号スイートを使用する場合は、tlsv1.2tlsv1.1tlsv1も設定してください。PSK認証の詳細はPSK認証の有効化を参照。

    • Cipher Suites:必要に応じて許可する暗号スイートを指定可能です(任意)。

    • CACert Depth:証明書チェーンの最大深度。デフォルトは10

    • Key File Passphrase:秘密鍵ファイルが暗号化されている場合のパスワード。インラインでなくファイルから読み込む場合はfile://<path-to-file>形式で指定し、ファイルの内容(末尾の空白除去済み)がパスワードとして使用されます。クラスタ環境ではすべてのEMQXノードにファイルが存在する必要があります。詳細はファイルからのシークレット読み込みを参照。

    • Enable OCSP Stapling:デフォルトで無効。証明書失効状態をOCSPで確認する必要がある場合に有効化します。OCSP Staplingを参照。

    • Enable CRL Check:デフォルトで無効。証明書失効リスト(CRL)による検証を行う場合に有効化します。CRL Checkを参照。

  4. 設定完了後、Updateをクリックして変更を適用します。

設定ファイルでの有効化

設定ファイルのlisteners.ssl.default設定グループを編集してSSL/TLS接続を有効にすることも可能です。

  1. 秘密のSSL/TLS証明書ファイルをEMQXのetc/certsディレクトリに配置します。

  2. インストール方法により./etcまたは/etc/emqx/etcディレクトリにある設定ファイルbase.hoconを開きます。

  3. listeners.ssl.default設定グループを編集します。

    • ファイルシステム上の証明書を使用する場合は、証明書ファイルを自分のものに置き換え、一方向認証を有効にするにはverify = verify_noneを追加します。

      hocon
      listeners.ssl.default {
        bind = "0.0.0.0:8883"
        
        ssl_options {
          cacertfile = "etc/certs/rootCAs.pem"
          certfile = "etc/certs/server-cert.pem"
          keyfile = "etc/certs/server-key.pem"
          
          verify = verify_none
          fail_if_no_peer_cert = true
        }
      }

      設定詳細:

      • cacertfile:クライアント証明書検証に使用する信頼済みCA証明書のPEMファイルパス。一方向認証では空ファイルまたはCA証明書なしでも構いません。
      • certfile:サーバーのSSL/TLS証明書チェーンを含むPEMファイルパス。リスナーで使用するサーバー証明書がルートCA直下でない場合は、中間CA証明書をサーバー証明書の後に連結して完全なチェーンを形成してください。
      • keyfile:サーバー証明書に対応する秘密鍵のPEMファイルパス。
      • verify:クライアント証明書の検証方法を制御。
        • verify_none:クライアント証明書を検証しない(一方向認証)。
        • verify_peer:クライアント証明書を検証する(双方向認証/mTLSに必須)。
      • fail_if_no_peer_cert:クライアントが証明書を提示しない場合のハンドシェイク動作。
        • false:クライアント証明書なしでも接続許可。証明書が提示されて無効な場合のみ拒否(一方向認証)。
        • true:クライアント証明書なしは拒否(mTLS必須)。
    • EMQXで集中管理され名前で参照する管理証明書を使用する場合は、以下の例を参照してください。

      管理証明書バンドルは事前にダッシュボードまたはHTTP APIで作成しておく必要があります。リスナー設定は既存の管理証明書を参照するだけです。

      グローバルネームスペースの証明書参照例

      listeners.ssl.default {
        bind = "0.0.0.0:8883"
      
        ssl_options {
          managed_certs = [
            {
              bundle_name = "example-cert-1"
              sni  = "example.com"
            },
            {
              bundle_name = "example-cert-2"
              sni  = "api.example.com"
            }
          ]
      
          verify = verify_none
          fail_if_no_peer_cert = false
        }
      }

      グローバルネームスペースの管理証明書を参照する場合、namespaceフィールドは省略します。デフォルトでグローバルが使用されます。

      非グローバル(テナント)ネームスペースの証明書参照例

      listeners.ssl.default {
        bind = "0.0.0.0:8883"
      
        ssl_options {
          managed_certs = [
            {
              namespace = "tenant-a"
              bundle_name = "mqtt-cert"
              sni       = "mqtt.tenant-a.example.com"
            }
          ]
      
          verify = verify_none
          fail_if_no_peer_cert = false
        }
      }

      非グローバル(テナント)ネームスペースの管理証明書を使用する場合は、namespaceフィールドを明示的に指定してください。

      複数の管理証明書が設定されている場合:

      • EMQXはクライアントのSNIに基づいて証明書を選択します。
      • SNIが一致しない場合は、最初の証明書エントリがデフォルトとして使用されます。
  4. 設定を反映するためにEMQXを再起動します。

SSL/TLS設定完了後、MQTTクライアントでEMQXに接続できます。

一方向認証でのクライアント接続テスト

MQTTX CLIを使ってテスト可能です。一方向認証ではクライアントがCA証明書を提供し、サーバーの身元を検証します。

bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt

サーバー証明書のCommon Name(CN)がクライアント接続時に指定したサーバーアドレスと一致しない場合、以下のエラーが発生します。

bash
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: localhost. is not cert's CN: Server

この場合、クライアント証明書のCNをサーバーアドレスに合わせるか、--insecureオプションで証明書CN検証を無視できます。

bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt \
  --insecure

双方向認証でのSSL/TLS有効化

双方向認証は一方向認証の拡張であり、EMQXがクライアント証明書を検証してクライアントの正当性を保証するように追加設定します。

これに加えて、クライアント用の証明書を発行する必要があります。具体的な手順はクライアント証明書の発行を参照してください。

ダッシュボードでは、Verify PeerEnableにし、Force Verify Peer Certificatetrueに設定することで双方向認証を強制できます。

設定ファイルのlisteners.ssl.default設定グループに以下を追加しても構いません。

bash
listeners.ssl.default {
  ...
  ssl_options {
    ...
    # ピア認証を有効化
    verify = verify_peer
    # 双方向認証を強制。クライアントが証明書を提供できない場合、SSL/TLS接続を拒否。
    fail_if_no_peer_cert = true
  }
}

双方向認証でのクライアント接続テスト

MQTTX CLIを使ってテスト可能です。CA証明書に加え、クライアント自身の証明書も提供する必要があります。

bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt \
  --cert certs/client-0001.crt \
  --key certs/client-0001.key

サーバー証明書のCNがクライアント接続時に指定したサーバーアドレスと一致しない場合、以下のエラーが発生します。

bash
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: localhost. is not cert's CN: Server

この場合、クライアント証明書のCNをサーバーアドレスに合わせるか、--insecureオプションで証明書CN検証を無視できます。

bash
mqttx sub -t 't/1' -h localhost -p 8883 \
  --protocol mqtts \
  --ca certs/rootCA.crt \
  --cert certs/client-0001.crt \
  --key certs/client-0001.key \
  --insecure