EMQX / Mosquittoを用いたmTLS認証対応セキュアMQTTブローカー構築とAWS接続ハンズオン
はじめに
こんにちは、NKKTech Global 技術チームです。
IoTシステムのセキュリティにおいて、「通信の暗号化」だけでなく**「接続元のハードウェアが正規の端末であることの証明」**が極めて重要です。
ID/パスワード認証は、デバイス内のファームウェアから認証情報が抽出された場合に全台への不正アクセスやクローン機器の乱立を招きます。
これを根本から解決するのが mTLS(Mutual TLS / 双方向TLS認証) です。
- サーバー(ブローカー)側の証明: 偽装サーバーへの誤接続を防止
- クライアント(端末)側の証明: 秘密鍵を持つ正規デバイス以外からの接続をプロトコルレベルで遮断
本記事では、プライベート認証局(CA)の構築から、Mosquitto / EMQX の設定、そしてオンプレミス環境のブローカーから AWS IoT Core へデータを安全に中継するブリッジ構成までを解説します。
1. 全体アーキテクチャ図
現場のエッジ端末からローカルブローカーへmTLSで接続し、集約したデータをさらにmTLSブリッジ経由でAWS IoT Coreへ転送する2段階のセキュアパイプラインです。
2. OpenSSLによるプライベートPKI(証明書)の作成
mTLSでは、Root CA(ルート認証局)、サーバー証明書、クライアント証明書の3階層を生成します。
mkdir -p certs && cd certs
# 1. プライベートRoot CAの作成
openssl req -new -x509 -days 3650 -extensions v3_ca \
-keyout ca.key -out ca.crt \
-subj "/C=JP/O=NKKTech Global/CN=NKKTech Root CA" -nodes
# 2. ブローカー用(サーバー)鍵とCSRの作成 (SANを指定)
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
-subj "/C=JP/O=NKKTech Global/CN=mqtt.nkktech.local"
# サーバー証明書の発行 (SAN: IP/DNSを含める)
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 730 -sha256 \
-extfile <(echo "subjectAltName=DNS:mqtt.nkktech.local,IP:192.168.1.100,IP:127.0.0.1")
# 3. デバイス用(クライアント)鍵とCSRの作成
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr \
-subj "/C=JP/O=NKKTech Global/CN=edge-device-001"
# クライアント証明書の発行
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 365 -sha256
3. MQTTブローカーのmTLS設定
パターンA:Eclipse Mosquitto の設定 (mosquitto.conf)
リソース制約の厳しいエッジゲートウェイや小型Linuxに最適です。
# 8883ポートでTLSリスナーを起動
listener 8883
allow_anonymous false
# 証明書パスの指定
cafile /mosquitto/config/certs/ca.crt
certfile /mosquitto/config/certs/server.crt
keyfile /mosquitto/config/certs/server.key
# mTLS (クライアント証明書を必須化)
require_certificate true
use_identity_as_username true
tls_version tlsv1.3
パターンB:EMQX の設定 (emqx.conf)
数百万台の大規模デバイス接続やクラスタリング、GUI管理が必要なエンタープライズ基盤に最適です。
## EMQX v5.x TLS Listener 設定
listeners.ssl.default {
bind = "0.0.0.0:8883"
ssl_options {
cacertfile = "/etc/emqx/certs/ca.crt"
certfile = "/etc/emqx/certs/server.crt"
keyfile = "/etc/emqx/certs/server.key"
verify = verify_peer
fail_if_no_peer_cert = true
}
}
4. オンプレミスMosquittoからAWS IoT Coreへのブリッジ設定
ローカル工場で収集したデータを、AWS IoT Coreへ安全に中継・転送(Bridge)する構成です。
① AWS IoT Coreで証明書を取得
- AWS IoT Core コンソールで「モノ(Thing)」を作成。
- デバイス証明書(
aws-client.pem.crt)、秘密鍵(aws-private.pem.key)、Amazon Root CA(AmazonRootCA1.pem)をダウンロード。 - ポリシーで
iot:Connect,iot:Publishを許可。
② Mosquittoブリッジ設定の追記 (mosquitto.conf)
# --- AWS IoT Core Bridge 設定 ---
connection aws-iot-bridge
address XXXXXXXXXXXXXX-ats.iot.ap-northeast-1.amazonaws.com:8883
# 転送するトピック (ローカルの factory/# を AWSの factory/osaka/# へ転送)
topic # out 1 factory/ factory/osaka/
# ブリッジ用クレデンシャル
bridge_cafile /mosquitto/config/certs/AmazonRootCA1.pem
bridge_certfile /mosquitto/config/certs/aws-client.pem.crt
bridge_keyfile /mosquitto/config/certs/aws-private.pem.key
cleansession true
notifications false
try_private false
bridge_attempt_unsubscribe false
5. PythonによるmTLS接続検証スクリプト
クライアント側から正規の証明書を提示して接続し、テレメトリデータをPublishする検証コードです。
import ssl
import json
import time
import paho.mqtt.client as mqtt
BROKER_HOST = "127.0.0.1" # または mqtt.nkktech.local
BROKER_PORT = 8883
TOPIC = "factory/line1/telemetry"
def on_connect(client, userdata, flags, rc):
if rc == 0:
print(">> [SUCCESS] mTLS Handshake completed. Connected to Broker.")
payload = json.dumps({
"device_id": "edge-device-001",
"temperature": 28.4,
"timestamp": int(time.time())
})
client.publish(TOPIC, payload, qos=1)
print(f">> [PUBLISH] Sent: {payload}")
else:
print(f">> [ERROR] Connection failed with code {rc}")
client = mqtt.Client(client_id="edge-device-001")
# mTLS設定
client.tls_set(
ca_certs="./certs/ca.crt",
certfile="./certs/client.crt",
keyfile="./certs/client.key",
tls_version=ssl.PROTOCOL_TLSv1_3
)
# 開発環境で自己署名CAのホスト名不一致を許容する場合のみ (本番ではTrue)
client.tls_insecure_set(False)
client.on_connect = on_connect
client.connect(BROKER_HOST, BROKER_PORT, keepalive=60)
client.loop_start()
time.sleep(2)
client.loop_stop()
不正端末接続時の挙動検証
-
証明書なしで接続した場合: TLSハンドシェイク段階でサーバーから即座に
ECONNRESETが返され、TCPセッションが破棄されます。 -
失効・未認証のCAで接続した場合:
SSL: CERTIFICATE_VERIFY_FAILEDとなり、MQTTパケットが1バイトもブローカーへ到達しません。
6. 本番運用のセキュリティ考慮点
-
CRL(証明書失効リスト)とOCSPの導入:
物理デバイスが盗難・紛失された際、Root CAを再作成することなく対象のクライアント証明書のみを無効化できるよう、CRL(Certificate Revocation List)の定期更新パイプラインを構築します。 -
ハードウェアセキュアエレメント(TPM / ATECC608A)の活用:
エッジデバイスのファイルシステム上に平文でclient.keyを保存せず、TPM(Trusted Platform Module)やセキュアエレメント内に秘密鍵を格納し、外部抽出を物理的に遮断します。 -
証明書の有効期限と自動ローテーション(EST / SCEP):
証明書の期限切れによる工場のライン停止を防ぐため、EST(Enrollment over Secure Transport)等のプロトコルを用いた自動更新エージェントを組み込みます。
まとめ:mTLSこそがIoTの「ゼロトラスト」の起点
IoTシステムにおいて、ネットワークの境界(境界型防御)だけに依存したセキュリティは限界を迎えています。
- mTLSによる暗号化とハードウェア証明で、なりすまし・改ざんを物理遮断する。
- 軽量なMosquitto / スケーラブルなEMQXを用途に応じて使い分ける。
- AWS IoT Coreへのセキュアブリッジにより、オンプレミスとクラウドのハイブリッド運用を実現する。
NKKTech Globalでは、産業用エッジデバイスのファームウェア設計から、高可用性MQTTブローカークラスタの構築、AWS/GCPクラウドインフラ統合までを包括的にサポートしています。
お問い合わせ先
セキュアIoT基盤の構築、mTLS導入、MQTTブローカーのスケーリングやクラウド連携に関するご相談は、下記よりお気軽にお問い合わせください。
- Webサイト: https://nkktech.com/
- メール: contact@nkk.com.vn
- LinkedIn: https://www.linkedin.com/company/nkktech
著者:NKKTech Global 技術チーム
私たちは、強固な組み込みセキュリティと最新のクラウドエンジニアリングで、産業界の安心・安全なDXを支援します。
