---
title: "MQTTセキュリティ｜TLS 8883番・証明書認証・トピックACLの設計を実装目線で解説"
url: "https://www.issoh.co.jp/tech/details/16868/"
published: 2026-08-23
updated: 2026-08-23
categories: ["プロトコル"]
publisher: "株式会社一創"
---

# MQTTセキュリティ｜TLS 8883番・証明書認証・トピックACLの設計を実装目線で解説

MQTTブローカーの事故は、暗号化を忘れたから起きるのではなく、暗号化だけで止めたときに起きます。8883番でTLSを張っても、資格情報が1つ漏れれば全トピックの発行と購読が通ってしまうためです。この記事では、TLS・認証・認可の三層それぞれで何を書くのか、Mosquitto 2.1系・EMQX 6系・AWS IoT Coreで権限の粒度がどう違うのか、拒否されたときにどのパケットのどの理由コードを見るのか、そして工場のブローカーを外へ出してよいかの線引きを、仕様と公式ドキュメントの記述に沿って整理しました。

## まとめ｜MQTTセキュリティを決める暗号化・認証・認可の三層と実装の順序

先に結論だけ書きます。MQTTを守る作業は3つに分かれ、抜けやすいのは決まって3つ目です。第1がトランスポートの暗号化（8883番のTLS）、第2が接続してきた相手の識別（資格情報またはクライアント証明書）、第3がトピック単位の認可（誰がどこへ発行し、どこを購読できるか）。

第1と第2は設定ファイルを数行足せば終わります。手間がかかるのは第3で、しかも事故の被害範囲を決めるのはここです。全機器で同じユーザー名を共有し、認可を書かないまま本番へ出すと、1台の解析だけで工場全体のトピックが読み書きできる状態になります。

実装は、TLS→識別→認可の順に足していくのが素直でしょう。ただし設計の順序は逆で、**先にトピックの権限境界を決めてから認証方式を選ぶ**と後戻りが減ります。機器ごとに権限を切りたいなら、資格情報の共有は最初から選択肢から外れ、クライアント証明書か機器単位のユーザーが前提になるからです。以下、前提・TLS・認証・認可・切り分け・公開時の脅威・採用判断の順に根拠を示します。

## 素のMQTTが守らない範囲｜1883番の平文と8883番のTLSで変わる前提

MQTTの仕様は認証のためのフィールドを定めるだけで、暗号化そのものは下の層に任せています。ここを取り違えると、CONNECTにユーザー名とパスワードを入れた時点で守れた気になってしまいます。

### IANA登録の1883番と8883番｜平文のまま流れる資格情報とペイロード

IANAのサービス名レジストリでは、1883番が `mqtt`、8883番が `secure-mqtt` として登録されています。前者は平文、後者はTLSの上でMQTTを話す前提の番号です。

1883番で接続すると、CONNECTパケットに入るユーザー名とパスワードは、そのままバイト列としてネットワークを流れます。パケットキャプチャで読めてしまう形です。検証環境で動かす分には支障がなくても、現場のスイッチや無線区間を通る時点で前提が変わります。プロトコルの制御パケットの並びそのものは[MQTTの仕組みとPub/Subモデルを扱った記事](https://www.issoh.co.jp/tech/details/15819/)で整理しているため、本記事では守る側の実装に絞ります。

### TLSが守る範囲と守らない範囲｜暗号化しても認可を別に要する理由

TLSが担うのは、盗聴の防止と、接続先が名乗り通りかの確認です。担わないのは、接続してきた相手がどのトピックに触れてよいかの判断でしょう。

この差が効くのは、機器が1台盗まれたときです。焼き込まれた資格情報でTLS接続は成立し、暗号化も正常に働きます。そのうえで `#` を購読されれば、ブローカーを通る全メッセージが読めます。暗号化は通信路の問題を解き、権限の問題は解きません。三層に分ける理由はここにあります。

## TLS接続の実装｜サーバー証明書の検証と双方向TLS・443番への集約

TLSを有効にする手順自体は短く、Mosquittoなら 8883番のlistenerにCA証明書・サーバー証明書・秘密鍵の3つを指定するだけで動きます。事故が起きるのはクライアント側です。

### サーバー証明書の検証を切ってしまう実装ミスと、自己署名CAの扱い

接続できないときに検証を無効化した回避策が、そのまま本番へ残る。これが最も多い形です。検証を切ったクライアントは、経路上に割り込んだ別のブローカーへ黙って接続します。TLSを張った意味が消えます。

自己署名のCAを使うなら、無効化ではなくCA証明書をクライアントへ配ってください。Pythonなら `tls_set()` にCA証明書のパスを渡して接続前に呼ぶ形で、この呼び出し順や再接続時のふるまいは[paho-mqtt 2系のクライアント実装をまとめた記事](https://www.issoh.co.jp/tech/details/16866/)で扱っています。Mosquitto 2.0以降の `tls_version` は最小バージョンの指定として解釈されるため、古い版を許す設定が残っていないかも見ておくとよいでしょう。

### 双方向TLS｜クライアント証明書で機器を識別する構成と発行の負荷

機器台数が数百を超えるなら、識別はクライアント証明書へ寄せるのが現実的です。パスワードと違い、ブローカー側で失効させればその1台だけを止められます。

負荷を引き受けるのは運用側です。製造時に1台ずつ鍵ペアを作り、証明書を焼き、有効期限を管理する工程が要ります。数十台の社内実験なら共有の資格情報でも回りますが、出荷先の顧客ごとに機器が散る構成では、後から証明書へ移行する作業が現地対応になります。台数が伸びる見込みがあるなら、最初から双方向TLSで組んでおくほうが安く済むでしょう。

### 443番へ寄せる構成｜ALPNとWebSocketでファイアウォールを越える判断

顧客の拠点から外向きに8883番が開かない、という制約は珍しくありません。逃げ道は2つあります。

AWS IoT Coreの場合、X.509クライアント証明書のまま443番を使うにはTLSのALPN拡張で `x-amzn-mqtt-ca` を送る必要があり、MQTT over WebSocketなら443番でSignature Version 4の署名認証になります。カスタムオーソライザーはMQTT over TLS・WebSocket・HTTPSのいずれでも使えます。接続の最大継続時間にも差があり、証明書とカスタム認証が1〜2週間、SigV4は最大24時間です。24時間で切れる前提を知らずに常時接続の設計を組むと、原因不明の再接続として現れます。

## 認証の設計｜資格情報の限界とMQTT 5.0の拡張認証・機器単位の識別

ユーザー名とパスワードは仕様上のフィールドとして用意されており、検証はブローカー側の実装に委ねられます。問題はその配り方です。

### ユーザー名とパスワードで足りる範囲と、機器台数が増えたときの限界

共有の資格情報が耐えられるのは、機器が社内に閉じていて台数が数十、かつ全台を同時に入れ替えられる場合までです。1台の漏洩が全台のパスワード変更を意味するため、現地作業の総量が台数に比例して膨らみます。

機器ごとにユーザーを分ければ失効は1台で済みますが、今度はブローカー側にユーザー管理が増えます。EMQXのように内蔵データベースやMySQL・PostgreSQL・Redis・LDAP・HTTPを認証と認可のデータソースにできる製品なら、既存の機器台帳をそのまま権限の元データにできるでしょう。Mosquittoの `password_file` だけで数千台を回すのは、更新のたびにファイル全体を書き換えるため向きません。

### MQTT 5.0のAUTHパケット｜チャレンジ応答型の拡張認証が使える条件

MQTT 5.0では、CONNECTとCONNACKの一往復では収まらない認証方式のためにAUTHパケットが追加されました。プロパティはAuthentication Methodが識別子21（0x15）、Authentication Dataが22（0x16）です。

SCRAMのようなチャレンジ応答型や、外部の認証基盤とトークンをやり取りする方式をここに載せます。仕様では、CONNECTでAuthentication Methodを設定したクライアントは、CONNACKを受け取るまでAUTHとDISCONNECT以外のパケットを送ってはならない、と定められています。使える条件は明快で、機器側とブローカー側の双方が5.0に対応し、かつブローカーがその認証方式を実装していること。片方が3.1.1のままなら、この経路は選べません。

## トピック認可の設計｜発行・購読・受信を分けて権限を切る実装の粒度

認可は「誰が」「どのトピックへ」「何をしてよいか」の3点で書きます。ブローカーによって書ける粒度が違い、そこが設計の自由度を決めます。

### 三製品の認可モデル比較｜Mosquitto・EMQX・AWS IoT Coreの権限粒度

2026年8月時点の主要3系統を、認可の書き方と一致しなかったときの既定で並べます。

| 製品             | 認可の書き方           | 不一致時の既定       | 権限の粒度           |
| -------------- | ---------------- | ------------- | --------------- |
| Mosquitto 2.1系 | acl\_fileとプラグイン  | 拒否            | 発行・購読のトピック単位    |
| EMQX 6系        | 内蔵DB・SQL・HTTP等8種 | 拒否（no\_match） | トピックとQoS・Retain |
| AWS IoT Core   | IAM形式のポリシー       | 拒否            | 接続・発行・購読・受信     |

EMQXは認可のチェッカーを並び順に評価し、どれにも一致しなければ no\_match の設定（6系の既定は拒否）が適用されます。トピックに加えてQoSとRetainを条件にできるのは5.1.1からで、Retain付きの発行だけを禁じるといった書き方ができます。製品そのものの選定軸は[ブローカーの仕組みと構築手順を扱った記事](https://www.issoh.co.jp/tech/details/3894/)を参照してください。

### 購読の権限と配信の権限を分ける設計｜取り消しが効くまでの時間差

AWS IoT Coreのポリシーは、この分離をアクションとして持っています。`iot:Subscribe` はSUBSCRIBEが届いたときに評価され、`iot:Receive` はメッセージが配信されるたびに評価されます。

差が出るのは権限を取り消したときです。購読時にしか見ないモデルでは、すでに購読を張っている接続は切れるまで受信を続けます。配信のたびに評価するモデルなら、ポリシーを外した時点で流れが止まります。侵害された機器を即座に黙らせたい要件があるなら、この粒度を持つかどうかが選定条件になるでしょう。`iot:RetainPublish` を `iot:Publish` とは別に付与する必要がある点も、見落としやすい部分です。マネージド側の料金と接続手順は[AWS IoT Coreの機能と料金を整理した記事](https://www.issoh.co.jp/tech/details/2991/)にまとめています。

### 変数展開で1台1権限を書く方法｜ClientIDとユーザー名を条件に使う

機器が1,000台あっても、ルールを1,000本書く必要はありません。ブローカー側の変数展開を使い、接続元の識別子をトピックの一部に埋めます。

Mosquittoなら `pattern` 行で、ClientIDを表す `%c` とユーザー名を表す `%u` がトピックの中で展開されます。AWS IoT Coreなら、モノの名前を差し込むポリシー変数を使う形です。書き方は違っても狙いは同じで、機器は自分の名前が入ったトピックにしか発行できず、他機器のトピックは購読できません。この形が成立するかどうかは、トピックの階層に権限境界となる値が含まれているかで決まります。階層の命名規約そのものは、同じ通信プロトコル群の別記事で扱います。

## 拒否されたときのふるまい｜3.1.1と5.0の応答差で変わる切り分けの手順

認可を厳しくすると、次に来るのは「つながらない」「届かない」という問い合わせです。原因を絞る速さは、使っている版で変わります。

### 3.1.1のCONNACK戻り値とSUBACKの0x80｜原因が絞り切れない場面

MQTT 3.1.1のCONNACKは、4がBad user name or password、5がNot authorizedを表します。接続の段階なら、ここまでは切り分けられます。

厄介なのは購読です。3.1.1のSUBACKが返せるのは、許可されたQoSを示す0x00・0x01・0x02と、失敗を示す0x80だけ。認可で弾かれたのか、トピックフィルタの形式が不正なのか、ブローカー内部の問題なのかを、クライアント側からは区別できません。結果として、届かない原因の切り分けはブローカーのログ頼みになります。

### MQTT 5.0の理由コード｜0x87と0x8Cで認証と認可を切り分ける手順

5.0では理由コードが整理され、0x86がBad User Name or Password、0x87がNot authorized、0x8CがBad authentication methodです。0x87はCONNACKだけでなく、SUBACKとPUBACKでも返せます。

これが運用に効く理由です。PUBACKに0x87が返れば、接続は通ったが発行先のトピックで弾かれた、と1回のやり取りで確定します。0x8Cなら拡張認証の方式がブローカー側と噛み合っていない、と分かります。クライアント側では理由コードをそのままログへ落とし、監視では0x87の発生数をトピック別に数えておくと、設定漏れと侵害の試行を同じ指標で見張る構成が妥当です。新規に組むなら5.0を選ぶ理由の1つがここにあります。

## ブローカーを外に置くときの脅威｜匿名接続・広域購読・Retainの汚染

インターネットから到達できるブローカーは、公開した時点で総当たりの接続試行を受けます。既定値のまま出したときに何が起きるかを押さえておきます。

### 設定ファイルを書いた途端に全インターフェースへ開く既定の挙動

Mosquitto 2.0以降は、設定ファイルなしで起動すると127.0.0.1と::1のループバックだけにバインドし、そこでは匿名接続を許します。ところが設定ファイルに `listener` を書くと、全アドレスへバインドする挙動に変わります。

同時に `allow_anonymous` の既定はfalseになるため、認証を設定しない限り接続を弾く仕様です。この組み合わせを知らずに `allow_anonymous true` を足して疎通を通した瞬間、認証なしのブローカーが世界へ開きます。疎通確認で足した1行が本番へ残る、という事故はここから生まれます。

### ワイルドカード購読とRetain汚染｜1台の乗っ取りで広がる被害の範囲

認可を書かないブローカーで `#` を購読されると、その1接続で全トピックが読めます。加えて、Retain付きで偽の値を発行されると、以後そのトピックを購読した機器すべてに古い偽値が配られ続けます。

止め方は3つあり、優先順位も明確です。第1に、機器の権限から購読側のワイルドカードを外す。第2に、Retain付き発行の権限を分けて、状態を持つトピックだけに許す。第3に、接続数とメッセージ数のレート制限を機器単位でかける。まず第1だけでも入れておけば、被害はその機器が扱うトピックの範囲に閉じます。

## 採用判断｜工場のブローカーを公開しない基準と証明書運用を止めない設計

ここからは判断を書きます。守り方の話ではなく、そもそも外へ出すかどうかの線引きです。

### ブローカーをインターネットへ公開してよい条件と、見送るべき場面

結論から書くと、**工場の制御系ネットワークに置いたブローカーをインターネットへ直接公開する構成は採りません**。認証を固めても接続試行そのものが制御系へ到達しますし、機器側のTLS実装は更新が難しく、脆弱性が出ても現地作業なしには直せないためです。

採る形は、現場側からクラウドのブローカーへ外向きに接続を張り、制御系への着信は開けない構成です。IEC 62443のゾーンとコンジットの考え方でいえば、制御ゾーンの外側にゲートウェイを置き、そこだけが上位との通信点です。現場ネットワークの階層構造は[産業用ネットワークの分類と規格選定を扱った記事](https://www.issoh.co.jp/tech/details/16808/)で整理しています。公開してよいのは、情報系に置いた収集専用のブローカーで、双方向TLSと機器単位の認可が入り、制御指令のトピックを持たない場合に限られます。遠隔から設備を止める指令が同じブローカーに同居しているなら、その時点で公開は見送りです。

### 証明書の有効期限と失効｜現地作業を発生させないローテーション設計

双方向TLSで組んだ現場が数年後に止まる原因の筆頭は、攻撃ではなく有効期限切れでしょう。設計時に決めておく項目は4つあります。

1. 証明書の有効期間と、期限の何割を過ぎたら更新を始めるかの閾値
2. 更新の経路（MQTT上で新しい証明書を受け取るか、別系統で配るか）
3. 失効の手段（ブローカー側で該当証明書を無効にする操作と反映までの時間）
4. 期限切れ間近の機器を数える監視（残日数を機器台帳と突き合わせる）

4つ目が抜けている現場を多く見かけます。証明書は静かに切れ、切れた機器は再接続を繰り返すだけで警報を出しません。残日数のしきい値監視を入れておけば、現地作業を計画に載せられます。有効期間を長く取れば運用は軽くなりますが、盗まれた鍵が使える期間も伸びます。出荷先が広く回収が難しい機器ほど短めに切り、更新経路を自動化する側へ倒すのが現実的な落としどころでしょう。

### 外部へ委ねるときに仕様書へ書く5項目｜責任範囲を曖昧にしない

MQTT収集基盤の構築を外部へ発注する場合、セキュリティ面で仕様書に明記する項目は次の5つです。第1にTLSの版と証明書の発行主体、第2に機器の識別方式（共有資格情報か機器単位か証明書か）、第3にトピック認可の設計が成果物に含まれるか、第4に証明書や資格情報の失効・更新の運用を誰が持つか、第5に監視対象とする拒否イベントの種類です。

費用の差が出るのは第3と第4でしょう。TLSを張るところまでは短期間で終わっても、機器単位の権限設計と証明書のライフサイクルは、機器の製造工程や保守体制と噛み合わせる作業になります。一創では、現場のセンサーや設備からデータを集める基盤の設計と構築を[AI・IoTソリューション開発](https://www.issoh.co.jp/service/ai/iot/)として請けており、認可設計と証明書運用を含む範囲で見積もりを出しています。

## よくある質問

MQTTのセキュリティ設計で実装前に問われることの多い5点をまとめます。

### MQTTのポートは8883番と1883番のどちらを使うべきですか？

検証環境の外へ出すなら8883番です。IANAでは1883番が平文のmqtt、8883番がsecure-mqttとして登録されており、1883番ではCONNECTに入れたユーザー名とパスワードもそのまま流れます。顧客拠点のファイアウォールで8883番が開かない場合は、443番へ寄せる方法があります。AWS IoT Coreならクライアント証明書のままALPNで443番を使うか、MQTT over WebSocketで接続してください。

### ユーザー名とパスワードだけの認証では不十分ですか？

台数と設置場所によります。社内に閉じた数十台で、漏洩時に全台のパスワードを一斉に変えられるなら成立するでしょう。出荷先へ機器が散る構成では、1台の解析で全台分の資格情報が露出し、変更が現地作業になるため向きません。台数が伸びる見込みがあるなら、最初からクライアント証明書による双方向TLSで組むほうが、後の移行費用を含めて安くつきます。

### トピックのACLには具体的に何を書けばよいですか？

機器が自分の名前の入ったトピックにだけ発行でき、他機器のトピックを購読できない状態を作ります。Mosquittoなら `pattern` 行でClientIDの `%c` やユーザー名の `%u` を展開し、EMQXなら内蔵データベースやSQL・HTTPのデータソースに機器台帳を持たせる形です。購読側のワイルドカードは、上位の収集プロセスにだけ許すのが原則になります。

### MQTT 3.1.1のままでもセキュリティは確保できますか？

TLSと認証と認可の三層は、どちらの版でも組めます。差が出るのは障害の切り分けで、3.1.1のSUBACKは成功のQoSと失敗の0x80しか返せないため、認可拒否とフィルタ不正を区別できません。5.0なら0x87のNot authorizedがSUBACKとPUBACKでも返り、原因が1往復で分かります。新規開発で5.0を選ぶ理由の1つです。

### ブローカーはクラウドと自社設置のどちらが安全ですか？

設置場所より、制御系ネットワークからの分離と認可の粒度で決まります。工場の制御ゾーンに置いたブローカーをインターネットへ直接公開する構成は避け、現場から外向きに接続を張る形にしてください。運用体制が薄いなら、証明書の発行と失効を仕組みとして持つマネージドサービスへ寄せるほうが、自前で証明書基盤を維持するより事故は減ります。

## 関連記事

- [MQTTとは？Pub/Subの仕組み・QoS・MQTT 5.0の実装からHTTPとの使い分けまで実装者向けに解説](https://www.issoh.co.jp/tech/details/15819/)：プロトコル本体の仕組みと制御パケットの並び
- [MQTTブローカーとは？仕組み・比較・構築手順を解説](https://www.issoh.co.jp/tech/details/3894/)：ブローカー製品の選定と構築の手順
- [EMQXとは？Mosquittoとの違い・選び方｜MQTTブローカー比較](https://www.issoh.co.jp/tech/details/1498/)：認可のデータソースが多い製品との比較
- [MQTT QoSとは？レベル0・1・2の違い・仕組み・選び方を解説](https://www.issoh.co.jp/tech/details/3611/)：認可と併せて決めるQoSの選び方
- [Sparkplug Bとは？MQTT上の産業データ規約と状態管理を実装目線で解説](https://www.issoh.co.jp/tech/details/16864/)：権限境界を作るトピック名前空間の規約

---

出典: [MQTTセキュリティ｜TLS 8883番・証明書認証・トピックACLの設計を実装目線で解説](<https://www.issoh.co.jp/tech/details/16868/>)（株式会社一創）
