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. 管理 -> リスナー に移動します。

  2. defaultという名前のSSLリスナーをクリックし、リスナー編集ページを開きます。

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

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

    • Force Verify Peer Certificate:Verify 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はクライアントの早期データ送信(0-RTT)をサポートしていません。クライアントはTLSハンドシェイク完了後にMQTTデータを送信する必要があります。

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

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

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

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

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

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

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

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

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

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

    • OCSP Staplingの有効化:デフォルトは無効。証明書失効状態をOCSPで確認する場合に有効化。詳細はOCSP Staplingを参照。

    • CRLチェックの有効化:デフォルトは無効。証明書失効リスト(CRL)による検証を行う場合に有効化。詳細はCRLチェックを参照。

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

設定ファイルでの有効化 ​

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

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

  2. 設定ファイルbase.hocon(インストール方法により./etcまたは/etc/emqx/etcにあります)を開きます。

  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:EMQXがクライアント証明書を検証するか制御。
        • 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 Peerを有効にし、Force Verify Peer Certificateをtrueに設定して双方向認証を強制できます。

設定ファイルの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