デバイス接続のための mTLS ベストプラクティス
相互 TLS(mTLS)は、クライアントとサーバーの双方が相手の証明書を認証する仕組みであり、有効な証明書を持たないデバイスの接続を根本的に防止します。暗号化ポートでのパスワード認証を無効化することで、デバイスはユーザー名やパスワードを提供せずに接続でき、認証はTLSクライアント証明書のみに依存します。
完全な構成は以下の3ステップで行います。
- クライアント証明書の発行:各デバイスに固有のクライアント証明書を発行し、証明書のCNフィールドにデバイスの固有識別子を記載します。
- EMQX CloudでのmTLS設定:サーバー証明書とクライアントCAをアップロードし、双方向認証を有効化、証明書のCNフィールドをUsernameまたはClientIDにマッピングします。
- 暗号化ポートでのパスワード認証の無効化:暗号化ポートでパスワード認証を無効化すると、デバイスはクライアント証明書のみで接続します。
証明書フィールドのマッピング
EMQX Cloudはクライアント証明書の特定フィールドをMQTT接続のUsernameまたはClientIDに自動マッピングできます。有効化すると、デバイスは接続時に認証情報を提供する必要がなくなり、EMQXが証明書から直接値を読み取ります。マッピングされた値はACLルールの基準として利用可能です。
対応フィールドはCN、DN、CRTであり、デプロイ設定で選択可能です。本ガイドではCN(Common Name)フィールドを例に説明します。CNにはデバイスのシリアル番号、MACアドレス、UUIDなどを使用することを推奨します。各デバイスのCNはグローバルに一意でなければならず、同一証明書を複数デバイスで共有してはいけません。
証明書の準備
mTLSには以下の2種類の証明書が必要です。
- サーバー証明書:EMQX Cloudにアップロードし、クライアントがサーバーの正当性を検証できるようにします。生成手順はサーバー側CA証明書の生成を参照してください。
- クライアント証明書:各デバイスに配布し、サーバーがデバイスの正当性を検証できるようにします。生成手順は以下に記載します。
クライアント証明書の発行
クライアントCAの生成
クライアントCAは各デバイスのクライアント証明書発行に使用し、一度だけ生成すれば十分です。事前にOpenSSLがインストールされていることを確認してください。
openssl req \
-new \
-newkey rsa:2048 \
-days 3650 \
-nodes \
-x509 \
-subj "/C=CN/O=EMQX Technologies Co., Ltd/CN=EMQ CA" \
-keyout client-ca.key \
-out client-ca.crt生成された client-ca.crt は後ほどEMQX Cloudにアップロードします。
各デバイスの証明書発行
以下の手順をデバイスごとに繰り返し、device-001 を実際のデバイス識別子に置き換えてください。
デバイスの秘密鍵を生成します。
bashopenssl genrsa -out device-001.key 2048CNフィールドにデバイス固有識別子を入れた証明書署名要求(CSR)を生成します。
bashopenssl req -new -key device-001.key -out device-001.csr \ -subj "/CN=device-001"クライアントCAで署名し、デバイス証明書を生成します。
bashopenssl x509 -req -days 3650 -sha256 \ -in device-001.csr \ -CA client-ca.crt \ -CAkey client-ca.key \ -CAcreateserial \ -out device-001.crt証明書を検証します。
bashopenssl verify -CAfile client-ca.crt device-001.crt
EMQX CloudでのmTLS設定
双方向TLSの有効化
デプロイのTLS/SSL設定パネルにサーバー証明書、秘密鍵、クライアントCA証明書をアップロードします。詳細手順は専用環境でのTLS/SSL設定を参照してください。
CNをUsernameにマッピング
CNフィールドをMQTT接続のUsernameにマッピングします。これによりACLルールをUsernameに基づいて適用可能です。
注意
この機能はDedicated v5およびDedicated Flexのデプロイメントでのみ利用可能です。設定項目が見当たらない場合は、チケットを提出してアップグレードをご相談ください。
- デプロイ詳細画面で左メニューのDeployment Settingsをクリックし、MQTT Settingsタブを選択します。
- Use Peer Certificate as Usernameのドロップダウンから
cnを選択します。 - Saveをクリックします。
CNをClientIDにマッピング
システムでClientIDによるデバイス管理が必要な場合、CNをClientIDにマッピングすることも可能です。
注意
この機能はDedicated v5およびDedicated Flexのデプロイメントでのみ利用可能です。設定項目が見当たらない場合は、チケットを提出してアップグレードをご相談ください。
- デプロイ詳細画面で左メニューのDeployment Settingsをクリックし、MQTT Settingsタブを選択します。
- Use Peer Certificate as ClientIDのドロップダウンから
cnを選択します。 - Saveをクリックします。
注意
CNをClientIDにマッピングする場合、すべてのデバイスのCNがグローバルに一意である必要があります。同じCNを複数のデバイスが共有すると、ClientIDの競合により接続が相互に切断されます。
暗号化ポートでのパスワード認証の無効化
上記設定完了後、暗号化ポートでのパスワード認証を無効化できます。これにより、デバイスはユーザー名やパスワードを提供せずクライアント証明書のみで接続可能になります。
注意
パスワード認証を無効化する前に、すべてのクライアントが有効なクライアント証明書を持ち、エンドツーエンドの接続テストが成功していることを必ず確認してください。稼働中のデバイス接続に影響を与えないためです。また、平文ポート(1883)は閉じ、暗号化ポート(8883 / 8084)のみを公開することを推奨します。
V5 Dedicatedデプロイメントではコンソール上で直接操作可能です。手順はポート管理 - 暗号化ポートのクライアント認証管理を参照してください。
その他のデプロイタイプの場合は、サポートへチケットを提出してください。SREチームがデプロイメントのポート8883および8084でのクライアント認証無効化を支援します。
クライアント接続例
MQTTXの例
MQTTXを使ったmTLS接続テスト手順:
新しい接続を作成し、接続名を入力します。Client IDはランダム生成可能です。
ホストを選択し、デプロイメントの接続アドレスとポートを入力します。
- TLS接続:
mqtts://を選択し、ポートは8883。 - TLS上のWebSocket:
wss://を選択し、ポートは8084。
- TLS接続:
パスワード認証が無効化されている場合、UsernameとPasswordは空欄のままにします。
SSL/TLSを有効化し、Self signedを選択します。
以下の証明書ファイルを指定します。
- CA File:サーバーCA証明書(
server-ca.crt)。 - Client Certificate File:デバイスのクライアント証明書(
device-001.crt)。 - Client Key File:デバイスのクライアント秘密鍵(
device-001.key)。
- CA File:サーバーCA証明書(
右上のConnectをクリックします。
FAQ
ClientID競合によるデバイス切断が発生する場合
症状: 2台のデバイスが同じClientIDまたは同じクライアント証明書を使用している。後から接続したデバイスが先に接続していたデバイスを切断する。
原因: MQTTプロトコルでは、同一ClientIDの接続はブローカー内で同時に1つしか存在できません。
対処法: 各デバイスに一意の証明書とCNを持たせてください。CNをUsernameにマッピングすることでClientID競合のリスクをさらに低減できます。
証明書が漏洩した場合の対応
- CN-to-Usernameマッピングを有効にしている場合、漏洩したデバイスのCNに対応するUsernameをブラックリストに即時追加し、再接続を防止します。
- 対象デバイスに新しい証明書を発行し、デバイス側の証明書設定を更新します。
- ブラックリストのエントリが期限切れまたは手動削除されるまで、漏洩した証明書は接続に使用できません。
パスワード認証無効化後も追加認証は必要ですか?
暗号化ポートでパスワード認証を無効化すると、認証はTLSクライアント証明書のみに依存し、ユーザー名/パスワード認証より強固なセキュリティを提供します。クライアント証明書を一時的に使用できないデバイスがある場合は、移行期間中はパスワード認証を有効にしておき、すべてのデバイスが証明書認証に移行後に無効化することを推奨します。