「Web - MQTTブローカー」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == MQTTブローカーは、IoTデバイスやアプリケーション間のメッセージ通信を仲介する重要なコンポーネントである。<br> 出版社と購読者の関係に似た<u>Publish / Subscribeモデル</u>を採用しており、各デバイスやアプリケーションはブローカーを介してメッセージをやり取りする。<br> <br> ブローカーの主な役割は、発行されたメッセージを適切な購…」)
 
 
(同じ利用者による、間の28版が非表示)
24行目: 24行目:
<br><br>
<br><br>


== オンプレミス ==
== メッセージングの基本的なフロー ==
下図では、MQTTの非同期メッセージング方式、および、1対多の通信パターンを表現している。<br>
<br>
また下図において、以下に示す要素を表現している。<br>
* Publisher (発行者) として温度センサと湿度センサを配置する。
* MQTTブローカーを配置する。
* Subscriber (購読者) として、データロガー、モニタリングアプリ、アラートシステムを配置する。
* また、トピックベースの通信 (sensors/tempやsensors/humidity)、ワイルドカードの使用 (sensors/+およびsensors/#) を示している。
<br>
[[ファイル:MQTT Broker 1.png|フレームなし|中央]]
<br><br>
 
== MQTTブローカーとサブスクライバを兼ねるケース ==
以下に示すような代表的なユースケースがある。<br>
<br>
* モニタリング / 管理目的
*: ブローカー自身が各トピックのメッセージをサブスクライブして監視する場合
*: システムの健全性を確認する場合
*: メッセージ統計の収集する場合
*: アクセスログの記録する場合
<br>
* ブリッジング
*: 複数のMQTTブローカー間でメッセージを中継する場合
*: あるブローカーがサブスクライバとして他のブローカーからメッセージを受信して、自身のブローカーとしての機能で配信する場合
<br>
* データの加工 / 集約
*: 複数のトピックからメッセージを受信して加工する場合
*: 加工したデータを新しいトピックとして配信する場合
<br>
* セキュリティ / フィルタリング
*: メッセージの内容を検証
*: 不正なメッセージのフィルタリング
<br>
ただし、このような構成をとる場合は注意が必要となる。<br>
* ブローカーの負荷が増加する可能性がある。
* 設計が複雑になりやすい。
* 障害発生時の影響範囲が広がる可能性がある。
<br><br>
 
== MQTTブローカーがパブリッシャーを兼ねるケース ==
MQTTブローカーがパブリッシャーとしても機能することにより、システム管理や監視の効率化が図ることができる。<br>
システムの複雑性とのバランスを考慮する必要がある。<br>
<br>
主な用途として、以下に示すようなものがある。<br>
<br>
* システム状態の通知
*: ブローカー自身の状態情報(CPU使用率、メモリ使用量など)
*: 接続クライアント数
*: システムヘルスチェック結果
*: $SYS/トピック配下での統計情報の配信
<br>
* 管理機能の提供
*: クライアントの接続/切断通知
*: セッション状態の変更通知
*: 認証/認可の結果通知
*: システムメンテナンス情報の配信
<br>
* デバイス管理
*: デバイスの構成変更指示
*: ファームウェアアップデート通知
*: リモートコマンド実行結果
<br>
* エラーハンドリング
*: エラー状態の通知
*: 異常検知時のアラート
*: フォールバック処理の実行結果
<br>
* Last Will and Testament (LWT) の管理
*: クライアントの異常切断検知時のメッセージ配信
*: フェイルオーバー通知
<br>
<u>※運用上の注意</u><br>
* メッセージの優先順位付け (システムメッセージvs通常メッセージ)
* パブリッシュ頻度の適切な設定
* システムメッセージとアプリケーションメッセージの分離
* セキュリティ (システムメッセージへのアクセス制御)
<br><br>
 
== パブリックMQTTブローカーサービス (無料 / 有料) ==
==== HiveMQ Cloud (無料枠あり) ====
運用・保守では、クラウドサービスであるHiveMQ Cloudの方が管理の手間は少ない。<br>
<br>
MQTT機能のみに集中して学習する場合や直感的な管理画面を求める場合は、HiveMQが適している可能性がある。<br>
<br>
https://www.hivemq.com/pricing/<br>
<br>
===== 無料版 =====
* 料金
*: 無料
* デバイス接続数
*: 100台までのデバイス接続可能
* 転送速度
*: 10[KB]/秒
* データトラフィック
*: 10[GB]データトラフィック/月
* プロトコル
*: MQTT 3.1 / 3.1.1 / 5.0
* SSL / TLS暗号化
*: MQTT over TLS/SSL
* 基本認証ルール
* Websocketサポート
<br>
===== 有料版 =====
* 料金
*: 1時間 $0.34
* デバイス接続数
*: 無制限
* 転送速度
*: 最大1[MB]/秒
* データトラフィック
*: 10[GB]データトラフィック/月
* プロトコル
*: MQTT 3.1 / 3.1.1 / 5.0
* SSL / TLS暗号化
*: MQTT over TLS/SSL
* クライアント証明書認証
* Websocketサポート
* REST API
<br>
 
==== EMQX MQTT (無料枠あり) ====
フルマネージドMQTTサービスである。<br>
複数のクラウドプロバイダ (AWS、GCP、Azure) に対応している。<br>
<br>
SSL / TLS暗号化にも対応している。<br>
<br>
* サーバーレスプラン
*: 1000台までのデバイス接続が可能。
*: シングルノード構成であり、データ転送速度は1[TPS] (Transaction Per Second) までとなっている。
*: <br>
* 専用プラン (料金 : $263 / 月)
*: 専用のクラウド環境内で完全に管理されたMQTTブローカーである。
*: 無料14日間トライアル付き
*: VPCピアリング、NATゲートウェイ、ロードバランシング等の階層オプションを提供している。
*: 40以上のクラウドサービスとのアウトオブボックス統合を提供している。
*: 24時間体制のグローバルな技術サポート付き。
*: <br>
* Premiumプラン (価格 : カスタム価格)
*: Everything in Dedicated Plan (専用プランの全ての機能を含む)
*: マルチアベイラビリティゾーンによる専用ストレージのサポート
*: 専用データベースに保存される永続的なセッション
*: クラスターリンクによるクロスリージョン通信
*: ネイティブKafkaプロトコルサポート
<br>
EMQXでは、KafkaおよびWebhookコネクタの機能が使用できる。<br>
<br>
コネクタ機能により、IoTデバイスのデータを他のシステムとの連携、リアルタイムなデータ処理やイベント監視、サーバーレス環境でも外部システムとの統合が容易になる。<br>
例えば、- デバイスから送信されたセンサーデータをKafkaに転送して分析、デバイスの接続/切断イベントをWebhookで監視システムに通知、メッセージの受信をWebhookでアプリケーションサーバに通知する等。<br>
<br>
* Kafkaコネクタ
*: EMQXで受信したMQTTメッセージをApache Kafkaに自動的に転送できる。
*: MQTT -> Kafka方向のデータ連携が可能。
*: これは、IoTデバイスからのデータをKafkaのトピックに送信して、ストリーム処理やデータ分析に活用できる。
*: <br>
* Webhookコネクタ
*: MQTTのイベント (接続、切断、メッセージの発行等) をHTTP/HTTPSのWebhookとして外部システムに通知できる。
*: 特定のイベントが発生した時、指定したURLにHTTPリクエストを送信する。
*: 外部のWebアプリケーションやサービスと連携可能である。
<br>
個人学習用途では、EMQXサーバーレスを推奨する。<br>
これは、デバイス接続数が多いため様々な実験が可能であること、KafkaやWebhook等の連携が無料で使用できるためIoTシステム全体のアーキテクチャを学習できることが挙げられる。<br>
<br>
https://www.emqx.com/ja/pricing<br>
<br>
==== CloudMQTT (現在はUpstashの一部) ====
*: スモールスケール向けの無料プラン有り。
*: 管理画面が理解しやすい。
*: セキュリティ設定が充実している。
*: <br>
* AWS IoT Core
*: AWSの完全マネージドサービス
*: 高度なセキュリティ機能
*: 他のAWSサービスと連携可能
*: 従量課金制
<br>
==== test.mosquitto.org (テスト向けは無料) ====
<u>テストや学習用に使用される</u><br>
セキュリティの保証が無いため、本番環境での使用は非推奨である。<br>
<br><br>
 
== パブリックMQTTブローカーサービスとオンプレミスの比較 ==
==== パブリックMQTTブローカーサービス ====
===== メリット =====
* すぐに利用開始可能
* 運用管理不要
* 高可用性
* 自動スケーリング
* セキュリティ対策済み
<br>
===== デメリット =====
* コストが発生 (規模による)
* カスタマイズの制限
* ベンダーロックイン
* データの管理場所に制約
<br>
==== オンプレミス ====
===== メリット =====
* コスト削減可能
* 完全なカスタマイズ制御
* データの完全な管理
* ネットワーク遅延の最適化
<br>
===== デメリット =====
* 保守運用の負担
* セキュリティ対策が必要となる。
* スケーリングの手間
* 可用性の確保が必要となる。
<br>
==== 推奨される環境 ====
開発を始める場合は、まず、パブリックサービスの無料枠を使用して、システムの動作確認や要件の明確化を行う。<br>
その後、本番環境に適したソリューションを選択することを推奨する。<br>
<br>
===== 開発 / テスト段階 =====
最初は、test.mosquitto.org や HiveMQ Cloudの無料枠を使用することを推奨する。<br>
これは、素早く開発を始められ、かつ、コストがかからないからである。<br>
<br>
===== 小規模な本番環境の場合 =====
HiveMQ Cloud や CloudMQTT の小規模プランを使用することを推奨する。<br>
これは、運用の手間を省けることができ、コストが安いからである。<br>
<br>
===== 大規模な本番環境 =====
AWS IoT Core 等のエンタープライズサービスを使用することを推奨する。<br>
<br>
または、十分な運用体制がある場合は自身で構築する。<br>
これは、スケーラビリティとセキュリティを重視する必要がある。<br>
<br><br>
 
== MQTTブローカーの構築 : オンプレミス ==
<u>※運用時の注意</u><br>
* 必ず匿名接続を無効にして、ユーザ認証を設定すること。
* 可能な限り、SSL/TLS通信を使用することを推奨する。
* 定期的にログを確認して、不正なアクセスがないか監視すること。
<br>
==== OpenSSL 3を使用する場合 ====
OpenSSL 3を使用して、Mosquittoで通信することは可能である。<br>
ただし、いくつか注意点がある。<br>
<br>
Mosquitto 2.0以降では、OpenSSL 3.0との互換性が確保されている。<br>
ただし、古いバージョンのMosquittoを使用している場合は、OpenSSL 3.0との互換性の問題が発生する可能性がある。<br>
<br>
これは、OpenSSL 3.0で非推奨となった古い暗号化アルゴリズムやAPIの使用に関連している。<br>
<br>
これを解決するには、以下に示すような方法が挙げられる。<br>
* Mosquittoを最新バージョンにアップグレードする。(推奨)
* Mosquittoをソースコードからビルドする時に、-DWITH_TLS_PSKオプションをNOに指定する。
* OpenSSL 3.0のレガシープロバイダを有効にする。<br>これは、/etc/ssl/openssl.cnfファイルの設定が必要となる。
<br>
# /etc/ssl/openssl.cnfファイル
# OpenSSLのレガシープロバイダを有効にする場合
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
legacy = legacy_sect
[default_sect]
activate = 1
[legacy_sect]
activate = 1
<br>
==== MQTTブローカーのインストール ====
===== パッケージ管理システムからインストール =====
# RHEL
sudo dnf install mosquitto mosquitto-clients
# SUSE
sudo zypper install mosquitto mosquitto-clients
# Raspberry Pi / PinePhone
sudo apt install mosquitto mosquitto-clients
<br>
MQTTブローカーサービスを起動する。<br>
sudo systemctl start mosquitto
<br>
必要であれば、MQTTブローカーサービスを自動起動に設定する。<br>
sudo systemctl enable mosquitto
<br>
===== ソースコードからインストール =====
Mosquittoのビルドに必要なライブラリをインストールする。<br>
# RHEL
sudo dnf install make cmake gcc gcc-c++ cJSON-devel  \
                  openssl3 openssl3-libs openssl3-devel
                  systemd-devel  # Systemdサービスを使用する場合
# SUSE
sudo zypper install make cmake gcc gcc-c++ cJSON-devel  \
                    libopenssl-devel libopenssl-1_1-devel
                    systemd-devel  # Systemdサービスを使用する場合
<br>
[https://mosquitto.org/download/ Mosquittoの公式Webサイト]または[https://github.com/eclipse-mosquitto/mosquitto Github]にアクセスして、ソースコードをダウンロードする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf mosquitto-<バージョン>.tar.gz
cd mosquitto-<バージョン>
<br>
Mosquittoをビルドおよびインストールする。<br>
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_INSTALL_PREFIX=<Mosquittoのインストールディレクトリ> \
      -DWITH_SYSTEMD=ON \  # Systemdサービスユニットを使用する場合
      -DWITH_TLS_PSK=ON \  # TLS-PSKをサポートする場合
      -DWITH_EC=ON \      # 楕円曲線暗号をサポートする場合
      ..
make -j $(nproc)
make install
<br>
Mosquittoをユーザディレクトリにインストールした場合は、Systemdサービスユニットファイルを手動で作成する必要がある。<br>
vi ~/.config/systemd/user/mosquitto.service
<br>
<syntaxhighlight lang="ini">
# ~/.config/systemd/user/mosquitto.serviceファイル
[Unit]
Description=Mosquitto MQTT Broker
Documentation=man:mosquitto.conf(5) man:mosquitto(8)
After=network.target
Wants=network.target
[Service]
Type=notify
NotifyAccess=main
ExecStart=/<Mosquittoのインストールディレクトリ>/sbin/mosquitto -c /<Mosquittoのインストールディレクトリ>/etc/mosquitto/mosquitto.conf
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
ExecStartPre=/bin/mkdir -m 740 -p /<Mosquittoのインストールディレクトリ>/var/log/mosquitto
ExecStartPre=/bin/mkdir -m 740 -p /<Mosquittoのインストールディレクトリ>/run/mosquitto
[Install]
WantedBy=multi-user.target
</syntaxhighlight>
<br>
Systemdデーモンを再読み込みする。<br>
systemctl --user daemon-reload
<br>
Systemdサービスユニットが正常に読み込まれているかどうかを確認する。<br>
systemctl --user mosquitto
<br>
 
====  ファイアウォールの設定 ====
MQTTブローカーの動作に必要なポートを開放する。<br>
<br>
* 標準のMQTT通信用ポート
*: TCP : 1883
* SSL/TLS暗号化通信用ポート
*: TCP : 8883
<br>
sudo firewall-cmd --permanent --add-port=1883/tcp
sudo firewall-cmd --permanent --add-port=8883/tcp
sudo firewall-cmd --reload
<br>
==== ユーザの登録 ====
まず、MQTTユーザを追加する。<br>
次に、パスワード (プロンプトが表示される) を入力する。<br>
sudo mosquitto_passwd -c /etc/mosquitto/passwd <初めて登録するユーザ名>
<br>
<u>※注意</u><br>
<u>追加のユーザを作成する場合は、<code>-c</code>オプションは付加しないこと。</u><br>
<u><code>-c</code>オプションは、既存ファイルを上書きするためである。</u><br>
sudo mosquitto_passwd /etc/mosquitto/passwd <追加するユーザ名>
# または
sudo mosquitto_passwd -b /etc/mosquitto/passwd <追加するユーザ名> <パスワード>
<br>
 
==== Mosquittoの設定 ====
まず、Mosquittoの設定ファイルを作成する。<br>
sudo vi /etc/mosquitto/conf.d/default.conf
<br>
次に、Mosquittoの設定を記述する。<br>
# ポート番号の設定
# ポート番号を変更することも可能
listener 1883
# 匿名接続の許可 / 不許可
# <u>trueを指定する場合、MQTTユーザ名およびパスワードの記述無しでパブリッシュすることができる</u>
allow_anonymous false
# パスワードファイルの指定
password_file /etc/mosquitto/passwd
<br>
また、リスナーごとに異なるallow_anonymous設定を行うことができる。<br>
これにより、用途に応じてポートを使い分けることができる。<br>
* 1883ポート
*: 社内ネットワークなどの信頼できる環境からの接続用
* 51883ポート
*: 外部からのアクセス等、セキュリティが必要な接続用
<br>
# 1883ポート : 認証必須
listener 1883
allow_anonymous false
# 51883ポート : 匿名ユーザを許可
listener 51883
allow_anonymous true
password_file /etc/mosquitto/passwd
<br>
==== 認証の必要性 ====
認証を使用する理由として、以下のことが挙げられる。<br>
* 不正アクセスの防止
* デバイスの識別が容易
* アクセス制御が可能
* 通信ログの追跡が容易
<br>
<u>ただし、開発環境やテスト環境では、allow_anonymous trueの設定で認証無しで使用することもある。</u><br>
<br>
<u>※注意</u><br>
<u>認証設定はサブスクライバ (受信) とパブリッシャー (送信) の両方に適用される。</u><br>
<u>両方のクライアントが設定されたユーザ名とパスワードを使用して接続する必要がある。</u><br>
<br>
 
==== セキュリティ設定 (推奨) ====
TLS/SSL通信を有効にする。<br>
<br>
# SSL/TLS証明書の作成
sudo mkdir /etc/mosquitto/certs
cd /etc/mosquitto/certs
# 証明書ファイルを作成する
# 出力する秘密鍵ファイルは、絶対に外部に漏れないよう、適切なパーミッションで保護する必要がある
# 実行時において、以下の情報の入力を求められる
## Country Name            (2文字の国コード)
## State or Province Name  (都道府県名)
## Locality Name            (市区町村名)
## Organization Name        (組織名)
## Organizational Unit Name (部門名)
## Common Name              (サーバのFQDNやドメイン名)
## Email Address            (メールアドレス)
sudo openssl req -new -x509                                    \
                      -days <証明書の有効期限日数  例: 365>        \
                      -extensions v3_ca                        \  # X.509 v3 CA拡張を使用(CAとしての役割を示す)
                      -keyout <出力する秘密鍵ファイル  例: ca.key> \
                      -out <出力する証明書ファイル  例: ca.crt>
# サーバ向けRSA秘密鍵を生成する
# 鍵の長さ (ビット数) を指定
# 2048ビットは現在の標準的なセキュリティレベル
# 4096ビットはより強力なセキュリティが必要な場合に使用
sudo openssl genrsa -out <生成した鍵の保存先  例: server.key> 2048
# 証明書署名要求 (CSR) を作成する
sudo openssl req -new -out <CSRの出力先  例: server.csr> -key <使用する秘密鍵の指定  例: server.key>
# CSRに対してCA証明書で署名して、サーバ証明書を作成する
sudo openssl x509 -req \
                  -in <署名対象のCSRファイル  例: server.csr>  \
                  -CA <署名に使用するCA証明書  例: ca.crt>      \
                  -CAkey <CA証明書の秘密鍵ファイル  例: ca.key>  \
                  -CAcreateserial                            \  # シリアル番号ファイルの作成
                  -out <生成される証明書の出力先  例: server.crt> \
                  -days <証明書の有効期限日数  例: 365>
<br>
上記のコマンドを実行することにより、以下に示すファイル群が生成される。<br>
* ca.key
*: CA (証明局) の秘密鍵
* ca.crt
*: CA (証明局) の証明書
* server.key
*: サーバの秘密鍵
* server.csr
*: 証明書署名要求
* server.crt
*: サーバの証明書
<br>
<u>※注意</u><br>
<u>秘密鍵 (.keyファイル) は、絶対に外部に漏れないように、適切なパーミッションで保護する必要がある。</u><br>
<u>本番環境では、これらのファイルは安全な場所に保管して、定期的な更新を行うことを推奨する。</u><Br>
<br>
SSL/TLS証明書ファイルをMQTTの設定ファイルに記述する。<br>
# SSL/TLS証明書の設定
listener 8883
cafile  /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key
tls_version tlsv1.2
<br>
 
==== 動作確認 ====
===== QoSとは =====
QoS (Quality of Service) は、MQTTにおけるメッセージ配信の信頼性を保証するための仕組みである。<br>
数字は信頼性のレベルを表しており、以下に示すような意味を持つ。<br>
<br>
* QoS 0 (At most once)
*: 最も基本的なレベルである。
*: メッセージは1度だけ送信され、配信確認は行われない。
*: <u>ベストエフォート型</u>の配信で、メッセージが失われる可能性がある。
*: 例えば、センサデータのような、多少のデータ欠損が許容される用途に適している。
*: <br>
* QoS 1 ((At least once)
*: メッセージは少なくとも1回は配信されることが保証される。
*: 送信者は受信確認を待ち、確認が得られない場合は再送を行う。
*: メッセージの重複を許容できる場合に使用する。
*: 例えば、ログデータの収集などに適している。
*: <br>
* QoS 2 (Exactly once)
*: 最も信頼性の高いレベルである。
*: 4段階のハンドシェイクにより、メッセージが正確に1回だけ配信されることを保証する。
*: 金融取引や重要な制御命令等、メッセージの欠損も重複も許されない場合に使用する。
<Br>
QoSレベルが上がるほど信頼性は向上するが、その分通信オーバーヘッドも増加する。<br>
<br>
===== サブスクライバー (購読者) の起動 =====
# 匿名ユーザを許可している場合
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "test/topic"> -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
## または
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "sensors/#"> -v -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
# ユーザ認証を使用する場合
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "test/topic"> -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
## または
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "sensors/#"> -v -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
# QoSを指定する場合
# QoS 1を使用
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "important/data"> -q 1
# SSL/TLS証明書を使用してサブスクライブ
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> \
              -t <購読するトピック  例: "secure/topic">  \
              -p 8883                                  \
              --cafile <SSL/TLS証明書ファイルのパス  例: /etc/mosquitto/certs/ca.crt> \
              --tls-version tlsv1.2
<br>
* mosquitto_subコマンド
*: MQTTメッセージを購読 (受信) するためのコマンドラインツールである。
*: <br>
* -hオプション
*: 接続先のMQTTブローカーのIPアドレスまたはホスト名を指定する。
*: <br>
*: localhostを指定する場合は、同じPC上のブローカーに接続される。
*: 別のサーバを指定する場合は、IPアドレスやドメイン名を指定する。
*: <br>
* -tオプション
*: 購読するトピックを指定する。
*: トピックは階層構造を持つことができる。
*: トピックの例 : home/livingroom/temperature
*: <br>
* -uオプション
*: 認証用のユーザ名を指定する。
* -Pオプション
*: 認証用のパスワードを指定する。
<br>
その他のオプションを以下に示す。<br>
* -vオプション
*: 受信メッセージと共にトピック名も表示する。
*: <br>
* -qオプション
*: QoSレベルを指定する。
*: 指定できる値は、0、1、2のいずれかである。
*: <br>
* --tls-versionオプション
*: TLSバージョンを指定する。
*: <br>
* --cafile
*: CA証明書ファイルを指定する。
<br>
 
===== パブリッシャー (発行者) の実行 =====
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> -t <発行するトピック  例: "test/topic"> -m "<メッセージ内容  例: Hello MQTT>" -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
# または
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> -t <発行するトピック  例: "sensors/temperature"> -m "<メッセージ内容  例: 25.5"
# QoSを指定する場合
# QoS 1でパブリッシュ
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> -t <発行するトピック  例: "important/data"> -m <メッセージ内容  例: "Critical Info"> -q 1
# SSL/TLS証明書を使用してパブリッシュする場合
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> \
              -t <発行するトピック  例: "secure/topic">  \
              -m <メッセージ内容  例: "Secure Message">  \
              -p 8883                                  \
              --cafile <SSL/TLS証明書ファイルのパス  例: /etc/mosquitto/certs/ca.crt> \
              --tls-version tlsv1.2
<br>
* mosquitto_pubコマンド
*: MQTTメッセージを発行 (送信) するためのコマンドラインツールである。
*: <br>
* -hオプション
*: 接続先のMQTTブローカーのIPアドレスまたはホスト名を指定する。
*: <br>
*: localhostを指定する場合は、同じPC上のブローカーに接続される。
*: 別のサーバを指定する場合は、IPアドレスやドメイン名を指定する。
*: <br>
* -tオプション
*: 発行するトピックを指定する。
*: トピックは階層構造を持つことができる。
*: トピックの例 : home/livingroom/temperature
*: <br>
* -mオプション
*: 送信するメッセージの内容を指定する。
*: <br>
* -uオプション
*: 認証用のユーザ名を指定する。
* -Pオプション
*: 認証用のパスワードを指定する。
<br>
その他のオプションを以下に示す。<br>
* -qオプション
*: QoSレベルを指定する。
*: 指定できる値は、0、1、2のいずれかである。
** 0 : メッセージは最大1回配信 (配信保証なし)
** 1 : メッセージは最低1回配信
** 2 : メッセージは正確に1回配信
*: <br>
* -r
*: リテインフラグを設定 (最後のメッセージを保持)
* -n
*: ヌルメッセージの送信 (メッセージ内容なし)
*: <br>
* --tls-versionオプション
*: TLSバージョンを指定する。
*: <br>
* --cafile
*: CA証明書ファイルを指定する。
<br>
===== 動作確認 =====
まず、MQTTブローカー (Mosquitto) を起動する。<br>
sudo systemctl start mosquitto
<br>
次に、サブスクライバ側を待機させる。<br>
ここでは、接続先のMQTTブローカーは自身のPC (localhost) とする。<br>
# 匿名ユーザを許可している場合
mosquitto_sub -h localhost -t hoge/piyo
# ユーザ名 / パスワードを指定する場合
mosquitto_sub -h localhost -t hoge/piyo -u <ユーザ名> -P <パスワード>
<br>
パプリッシャー側でメッセージをパブリッシュする。<br>
この時、任意のPCやデバイスが同じトピック名を持つメッセージを送信する時、サブスクライバ側は自動的に受信する。<br>
# 匿名ユーザを許可している場合
mosquitto_pub -h localhost -t hoge/piyo -m "Hello, Mosquitto!"
# ユーザ名 / パスワードを指定する場合
mosquitto_sub -h localhost -t hoge/piyo -u <ユーザ名> -P <パスワード>
<br>
 
===== 使用例 =====
例えば、3台のデバイスに対して「LED照明を付けてほしい」とパブリッシャーが送信する場合、以下に示すようにMQTTトピックを効率的に使用する。<br>
<code>#</code>は、MQTTトピックにおけるワイルドカードであり、該当する全てのトピックを購読することができる。<br>
<br>
* 共通トピックを使用する方法
# パブリッシャー側
mosquitto_pub -t "lights/all" -m "ON" -u <ユーザ名> -P <パスワード>
# サブスクライバ側 (各デバイス側)
mosquitto_sub -t "lights/all" -u <ユーザ名> -P <パスワード>
<br>
* 個別制御も可能な階層的トピック構造
# 全体制御 (パブリッシャー側)
mosquitto_pub -t "lights/#" -m "ON" -u <共通のユーザ名> -P <共通のパスワード>
# 個別制御 (パブリッシャー側)
mosquitto_pub -t "lights/device1" -m "ON" -u <デバイス1のユーザ名> -P <デバイス1のパスワード>
mosquitto_pub -t "lights/device2" -m "OFF" -u <デバイス2のユーザ名> -P <デバイス2のパスワード>
# デバイス側は両方のトピックを購読 (サブスクライバ側)
# オプション1: 共通認証
mosquitto_sub -t "lights/#" -u <共通のユーザ名> -P <共通のパスワード>
# オプション2: デバイスごとの認証 (サブスクライバ側)
mosquitto_sub -t "lights/#" -u <デバイス1のユーザ名> -P <デバイス1のパスワード>
mosquitto_sub -t "lights/#" -u <デバイス2のユーザ名> -P <デバイス2のパスワード>
<br>
また、実務では、複数のデバイスで同じ認証情報を共有するケースは一般的である。(例: 同一のユーザ名とパスワードを使用するデバイスが3台ある場合)<br>
* メリット
*: 設定管理が簡単
*: デバイスの追加が容易
* デメリット
*: セキュリティリスク (認証情報が漏洩した場合の影響大)
*: 個別デバイスの追跡が困難
<br>
<u>ただし、セキュリティを重視する場合は、デバイスごとに異なる認証情報を設定することが推奨される。</u><br>
<br>
===== 運用時の注意 =====
* セキュリティ
*: 本番環境では必ずユーザ認証を使用する。
*: 機密性の高い情報を扱う場合はSSL/TLS暗号化を使用する。
*: パスワードをコマンドラインで直接指定する代わりに、環境変数や設定ファイルを使用することを推奨する。
<br>
* エラーハンドリング
*: 接続エラーや認証エラーの際のログを確認する。
*: 必要に応じて、<code>-d</code>オプション (デバッグモード) を付加して、詳細情報を確認する。
*: <br>
* パフォーマンス
*: 大量のメッセージを扱う場合はQoSレベルを適切に選択する。
*: リテインメッセージの使用は必要最小限に抑える。
<br><br>
 
== 接続の制限 ==
mosquitto.confファイルでクライアント接続数を制限することができるが、デフォルトの設定では制限を課していない。<br>
しかし、Linux OSでは制限を課しており、各ユーザに対して1024となっている。<br>
<br>
この制限は、許可されるオープンファイルの最大数である。<br>
<br>
==== コマンドラインからMosquittoを実行する場合 ====
これは、limits.confファイル (/etc/security/limits.conf) を編集することにより、各ユーザごとに変更できる。<br>
<br>
設定を反映させるため、PCを再起動する必要がある。<br>
<br>
PCを再起動した後、制限が変更されているかどうかを確認する。<br>
ulimit -Sn
# または
ulimit -Hn
<br>
ただし、上記の設定は、コマンドラインから起動したmosquittoにのみ影響する。<br>
<br>
==== SystemdサービスからMosquittoを実行する場合 ====
MosquittoをSystemdサービスとして起動する場合は、MosquittoのSystemdサービスユニットファイルに設定を追記する。<br>
# mosquitto.serviceファイル
[Service]
# 最大接続数を4000に設定する場合
LimitNOFILE=4000
<br>
設定を有効にするため、PCを再起動する。<br>
<br>
PCを再起動、および、Mosquittoサービスを実行した後、制限が変更されているかどうかを確認する。<br>
これは、プロセスIDを取得することにより確認できる。<br>
cat /proc/<PID>/limits
<br><br>
<br><br>



2024年12月28日 (土) 05:00時点における最新版

概要

MQTTブローカーは、IoTデバイスやアプリケーション間のメッセージ通信を仲介する重要なコンポーネントである。
出版社と購読者の関係に似たPublish / Subscribeモデルを採用しており、各デバイスやアプリケーションはブローカーを介してメッセージをやり取りする。

ブローカーの主な役割は、発行されたメッセージを適切な購読者に配信することである。
例えば、温度センサがデータを発行すると、そのトピックを購読している全てのクライアントにブローカーが自動的にメッセージを転送する。

セキュリティ面では、ユーザ認証や暗号化通信をサポートしており、機密性の高い情報でも安全に扱うことができる。
また、QoS (Quality of Service) レベルを設定することにより、メッセージの配信保証レベルを制御できる。

人気のあるMQTTブローカーとしては、Mosquitto、HiveMQ、EMQX等がある。
これらはオープンソースで提供されており、小規模なプロジェクトから大規模な商用システムまで幅広く利用されている。

ブローカーの特徴的な機能として、トピックベースのフィルタリングがある。
トピックは階層構造を持ち、ワイルドカードを使用することで柔軟なメッセージのルーティングが可能である。
例えば、"sensors / temperature/+"というトピックを購読することで、全ての温度センサからのデータを受信できる。

また、多くのブローカーは永続化機能を備えており、クライアントが一時的にオフラインになった場合でも、メッセージを保持して、再接続時に配信することができる。
これにより、不安定なネットワーク環境でも確実なメッセージングが実現できる。

スケーラビリティの面では、クラスタリングやロードバランシングをサポートしているブローカーも多く、大規模なIoTシステムの構築も可能である。

MQTTブローカーは、IoTシステムにおける中心的な役割を果たしており、効率的で信頼性の高いメッセージング基盤を提供する。


メッセージングの基本的なフロー

下図では、MQTTの非同期メッセージング方式、および、1対多の通信パターンを表現している。

また下図において、以下に示す要素を表現している。

  • Publisher (発行者) として温度センサと湿度センサを配置する。
  • MQTTブローカーを配置する。
  • Subscriber (購読者) として、データロガー、モニタリングアプリ、アラートシステムを配置する。
  • また、トピックベースの通信 (sensors/tempやsensors/humidity)、ワイルドカードの使用 (sensors/+およびsensors/#) を示している。


MQTT Broker 1.png



MQTTブローカーとサブスクライバを兼ねるケース

以下に示すような代表的なユースケースがある。

  • モニタリング / 管理目的
    ブローカー自身が各トピックのメッセージをサブスクライブして監視する場合
    システムの健全性を確認する場合
    メッセージ統計の収集する場合
    アクセスログの記録する場合


  • ブリッジング
    複数のMQTTブローカー間でメッセージを中継する場合
    あるブローカーがサブスクライバとして他のブローカーからメッセージを受信して、自身のブローカーとしての機能で配信する場合


  • データの加工 / 集約
    複数のトピックからメッセージを受信して加工する場合
    加工したデータを新しいトピックとして配信する場合


  • セキュリティ / フィルタリング
    メッセージの内容を検証
    不正なメッセージのフィルタリング


ただし、このような構成をとる場合は注意が必要となる。

  • ブローカーの負荷が増加する可能性がある。
  • 設計が複雑になりやすい。
  • 障害発生時の影響範囲が広がる可能性がある。



MQTTブローカーがパブリッシャーを兼ねるケース

MQTTブローカーがパブリッシャーとしても機能することにより、システム管理や監視の効率化が図ることができる。
システムの複雑性とのバランスを考慮する必要がある。

主な用途として、以下に示すようなものがある。

  • システム状態の通知
    ブローカー自身の状態情報(CPU使用率、メモリ使用量など)
    接続クライアント数
    システムヘルスチェック結果
    $SYS/トピック配下での統計情報の配信


  • 管理機能の提供
    クライアントの接続/切断通知
    セッション状態の変更通知
    認証/認可の結果通知
    システムメンテナンス情報の配信


  • デバイス管理
    デバイスの構成変更指示
    ファームウェアアップデート通知
    リモートコマンド実行結果


  • エラーハンドリング
    エラー状態の通知
    異常検知時のアラート
    フォールバック処理の実行結果


  • Last Will and Testament (LWT) の管理
    クライアントの異常切断検知時のメッセージ配信
    フェイルオーバー通知


※運用上の注意

  • メッセージの優先順位付け (システムメッセージvs通常メッセージ)
  • パブリッシュ頻度の適切な設定
  • システムメッセージとアプリケーションメッセージの分離
  • セキュリティ (システムメッセージへのアクセス制御)



パブリックMQTTブローカーサービス (無料 / 有料)

HiveMQ Cloud (無料枠あり)

運用・保守では、クラウドサービスであるHiveMQ Cloudの方が管理の手間は少ない。

MQTT機能のみに集中して学習する場合や直感的な管理画面を求める場合は、HiveMQが適している可能性がある。

https://www.hivemq.com/pricing/

無料版
  • 料金
    無料
  • デバイス接続数
    100台までのデバイス接続可能
  • 転送速度
    10[KB]/秒
  • データトラフィック
    10[GB]データトラフィック/月
  • プロトコル
    MQTT 3.1 / 3.1.1 / 5.0
  • SSL / TLS暗号化
    MQTT over TLS/SSL
  • 基本認証ルール
  • Websocketサポート


有料版
  • 料金
    1時間 $0.34
  • デバイス接続数
    無制限
  • 転送速度
    最大1[MB]/秒
  • データトラフィック
    10[GB]データトラフィック/月
  • プロトコル
    MQTT 3.1 / 3.1.1 / 5.0
  • SSL / TLS暗号化
    MQTT over TLS/SSL
  • クライアント証明書認証
  • Websocketサポート
  • REST API


EMQX MQTT (無料枠あり)

フルマネージドMQTTサービスである。
複数のクラウドプロバイダ (AWS、GCP、Azure) に対応している。

SSL / TLS暗号化にも対応している。

  • サーバーレスプラン
    1000台までのデバイス接続が可能。
    シングルノード構成であり、データ転送速度は1[TPS] (Transaction Per Second) までとなっている。

  • 専用プラン (料金 : $263 / 月)
    専用のクラウド環境内で完全に管理されたMQTTブローカーである。
    無料14日間トライアル付き
    VPCピアリング、NATゲートウェイ、ロードバランシング等の階層オプションを提供している。
    40以上のクラウドサービスとのアウトオブボックス統合を提供している。
    24時間体制のグローバルな技術サポート付き。

  • Premiumプラン (価格 : カスタム価格)
    Everything in Dedicated Plan (専用プランの全ての機能を含む)
    マルチアベイラビリティゾーンによる専用ストレージのサポート
    専用データベースに保存される永続的なセッション
    クラスターリンクによるクロスリージョン通信
    ネイティブKafkaプロトコルサポート


EMQXでは、KafkaおよびWebhookコネクタの機能が使用できる。

コネクタ機能により、IoTデバイスのデータを他のシステムとの連携、リアルタイムなデータ処理やイベント監視、サーバーレス環境でも外部システムとの統合が容易になる。
例えば、- デバイスから送信されたセンサーデータをKafkaに転送して分析、デバイスの接続/切断イベントをWebhookで監視システムに通知、メッセージの受信をWebhookでアプリケーションサーバに通知する等。

  • Kafkaコネクタ
    EMQXで受信したMQTTメッセージをApache Kafkaに自動的に転送できる。
    MQTT -> Kafka方向のデータ連携が可能。
    これは、IoTデバイスからのデータをKafkaのトピックに送信して、ストリーム処理やデータ分析に活用できる。

  • Webhookコネクタ
    MQTTのイベント (接続、切断、メッセージの発行等) をHTTP/HTTPSのWebhookとして外部システムに通知できる。
    特定のイベントが発生した時、指定したURLにHTTPリクエストを送信する。
    外部のWebアプリケーションやサービスと連携可能である。


個人学習用途では、EMQXサーバーレスを推奨する。
これは、デバイス接続数が多いため様々な実験が可能であること、KafkaやWebhook等の連携が無料で使用できるためIoTシステム全体のアーキテクチャを学習できることが挙げられる。

https://www.emqx.com/ja/pricing

CloudMQTT (現在はUpstashの一部)

  • スモールスケール向けの無料プラン有り。
    管理画面が理解しやすい。
    セキュリティ設定が充実している。

  • AWS IoT Core
    AWSの完全マネージドサービス
    高度なセキュリティ機能
    他のAWSサービスと連携可能
    従量課金制


test.mosquitto.org (テスト向けは無料)

テストや学習用に使用される
セキュリティの保証が無いため、本番環境での使用は非推奨である。


パブリックMQTTブローカーサービスとオンプレミスの比較

パブリックMQTTブローカーサービス

メリット
  • すぐに利用開始可能
  • 運用管理不要
  • 高可用性
  • 自動スケーリング
  • セキュリティ対策済み


デメリット
  • コストが発生 (規模による)
  • カスタマイズの制限
  • ベンダーロックイン
  • データの管理場所に制約


オンプレミス

メリット
  • コスト削減可能
  • 完全なカスタマイズ制御
  • データの完全な管理
  • ネットワーク遅延の最適化


デメリット
  • 保守運用の負担
  • セキュリティ対策が必要となる。
  • スケーリングの手間
  • 可用性の確保が必要となる。


推奨される環境

開発を始める場合は、まず、パブリックサービスの無料枠を使用して、システムの動作確認や要件の明確化を行う。
その後、本番環境に適したソリューションを選択することを推奨する。

開発 / テスト段階

最初は、test.mosquitto.org や HiveMQ Cloudの無料枠を使用することを推奨する。
これは、素早く開発を始められ、かつ、コストがかからないからである。

小規模な本番環境の場合

HiveMQ Cloud や CloudMQTT の小規模プランを使用することを推奨する。
これは、運用の手間を省けることができ、コストが安いからである。

大規模な本番環境

AWS IoT Core 等のエンタープライズサービスを使用することを推奨する。

または、十分な運用体制がある場合は自身で構築する。
これは、スケーラビリティとセキュリティを重視する必要がある。


MQTTブローカーの構築 : オンプレミス

※運用時の注意

  • 必ず匿名接続を無効にして、ユーザ認証を設定すること。
  • 可能な限り、SSL/TLS通信を使用することを推奨する。
  • 定期的にログを確認して、不正なアクセスがないか監視すること。


OpenSSL 3を使用する場合

OpenSSL 3を使用して、Mosquittoで通信することは可能である。
ただし、いくつか注意点がある。

Mosquitto 2.0以降では、OpenSSL 3.0との互換性が確保されている。
ただし、古いバージョンのMosquittoを使用している場合は、OpenSSL 3.0との互換性の問題が発生する可能性がある。

これは、OpenSSL 3.0で非推奨となった古い暗号化アルゴリズムやAPIの使用に関連している。

これを解決するには、以下に示すような方法が挙げられる。

  • Mosquittoを最新バージョンにアップグレードする。(推奨)
  • Mosquittoをソースコードからビルドする時に、-DWITH_TLS_PSKオプションをNOに指定する。
  • OpenSSL 3.0のレガシープロバイダを有効にする。
    これは、/etc/ssl/openssl.cnfファイルの設定が必要となる。


# /etc/ssl/openssl.cnfファイル

# OpenSSLのレガシープロバイダを有効にする場合
openssl_conf = openssl_init

[openssl_init]
providers = provider_sect

[provider_sect]
default = default_sect
legacy = legacy_sect

[default_sect]
activate = 1

[legacy_sect]
activate = 1


MQTTブローカーのインストール

パッケージ管理システムからインストール
# RHEL
sudo dnf install mosquitto mosquitto-clients

# SUSE
sudo zypper install mosquitto mosquitto-clients

# Raspberry Pi / PinePhone
sudo apt install mosquitto mosquitto-clients


MQTTブローカーサービスを起動する。

sudo systemctl start mosquitto


必要であれば、MQTTブローカーサービスを自動起動に設定する。

sudo systemctl enable mosquitto


ソースコードからインストール

Mosquittoのビルドに必要なライブラリをインストールする。

# RHEL
sudo dnf install make cmake gcc gcc-c++ cJSON-devel   \
                 openssl3 openssl3-libs openssl3-devel
                 systemd-devel  # Systemdサービスを使用する場合

# SUSE
sudo zypper install make cmake gcc gcc-c++ cJSON-devel   \
                    libopenssl-devel libopenssl-1_1-devel
                    systemd-devel  # Systemdサービスを使用する場合


Mosquittoの公式WebサイトまたはGithubにアクセスして、ソースコードをダウンロードする。
ダウンロードしたファイルを解凍する。

tar xf mosquitto-<バージョン>.tar.gz
cd mosquitto-<バージョン>


Mosquittoをビルドおよびインストールする。

mkdir build && cd build

cmake -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_INSTALL_PREFIX=<Mosquittoのインストールディレクトリ> \
      -DWITH_SYSTEMD=ON \  # Systemdサービスユニットを使用する場合
      -DWITH_TLS_PSK=ON \  # TLS-PSKをサポートする場合
      -DWITH_EC=ON \       # 楕円曲線暗号をサポートする場合
      ..

make -j $(nproc)
make install


Mosquittoをユーザディレクトリにインストールした場合は、Systemdサービスユニットファイルを手動で作成する必要がある。

vi ~/.config/systemd/user/mosquitto.service


 # ~/.config/systemd/user/mosquitto.serviceファイル
 
 [Unit]
 Description=Mosquitto MQTT Broker
 Documentation=man:mosquitto.conf(5) man:mosquitto(8)
 After=network.target
 Wants=network.target
 
 [Service]
 Type=notify
 NotifyAccess=main
 ExecStart=/<Mosquittoのインストールディレクトリ>/sbin/mosquitto -c /<Mosquittoのインストールディレクトリ>/etc/mosquitto/mosquitto.conf
 ExecReload=/bin/kill -HUP $MAINPID
 Restart=on-failure
 ExecStartPre=/bin/mkdir -m 740 -p /<Mosquittoのインストールディレクトリ>/var/log/mosquitto
 ExecStartPre=/bin/mkdir -m 740 -p /<Mosquittoのインストールディレクトリ>/run/mosquitto
 
 [Install]
 WantedBy=multi-user.target


Systemdデーモンを再読み込みする。

systemctl --user daemon-reload


Systemdサービスユニットが正常に読み込まれているかどうかを確認する。

systemctl --user mosquitto


ファイアウォールの設定

MQTTブローカーの動作に必要なポートを開放する。

  • 標準のMQTT通信用ポート
    TCP : 1883
  • SSL/TLS暗号化通信用ポート
    TCP : 8883


sudo firewall-cmd --permanent --add-port=1883/tcp
sudo firewall-cmd --permanent --add-port=8883/tcp

sudo firewall-cmd --reload


ユーザの登録

まず、MQTTユーザを追加する。
次に、パスワード (プロンプトが表示される) を入力する。

sudo mosquitto_passwd -c /etc/mosquitto/passwd <初めて登録するユーザ名>


※注意
追加のユーザを作成する場合は、-cオプションは付加しないこと。
-cオプションは、既存ファイルを上書きするためである。

sudo mosquitto_passwd /etc/mosquitto/passwd <追加するユーザ名>
# または
sudo mosquitto_passwd -b /etc/mosquitto/passwd <追加するユーザ名> <パスワード>


Mosquittoの設定

まず、Mosquittoの設定ファイルを作成する。

sudo vi /etc/mosquitto/conf.d/default.conf


次に、Mosquittoの設定を記述する。

# ポート番号の設定
# ポート番号を変更することも可能
listener 1883

# 匿名接続の許可 / 不許可
# trueを指定する場合、MQTTユーザ名およびパスワードの記述無しでパブリッシュすることができる
allow_anonymous false

# パスワードファイルの指定
password_file /etc/mosquitto/passwd


また、リスナーごとに異なるallow_anonymous設定を行うことができる。
これにより、用途に応じてポートを使い分けることができる。

  • 1883ポート
    社内ネットワークなどの信頼できる環境からの接続用
  • 51883ポート
    外部からのアクセス等、セキュリティが必要な接続用


# 1883ポート : 認証必須
listener 1883
allow_anonymous false

# 51883ポート : 匿名ユーザを許可
listener 51883 
allow_anonymous true

password_file /etc/mosquitto/passwd


認証の必要性

認証を使用する理由として、以下のことが挙げられる。

  • 不正アクセスの防止
  • デバイスの識別が容易
  • アクセス制御が可能
  • 通信ログの追跡が容易


ただし、開発環境やテスト環境では、allow_anonymous trueの設定で認証無しで使用することもある。

※注意
認証設定はサブスクライバ (受信) とパブリッシャー (送信) の両方に適用される。
両方のクライアントが設定されたユーザ名とパスワードを使用して接続する必要がある。

セキュリティ設定 (推奨)

TLS/SSL通信を有効にする。

# SSL/TLS証明書の作成
sudo mkdir /etc/mosquitto/certs

cd /etc/mosquitto/certs

# 証明書ファイルを作成する
# 出力する秘密鍵ファイルは、絶対に外部に漏れないよう、適切なパーミッションで保護する必要がある

# 実行時において、以下の情報の入力を求められる
## Country Name             (2文字の国コード)
## State or Province Name   (都道府県名)
## Locality Name            (市区町村名)
## Organization Name        (組織名)
## Organizational Unit Name (部門名)
## Common Name              (サーバのFQDNやドメイン名)
## Email Address            (メールアドレス)
sudo openssl req -new -x509                                    \
                      -days <証明書の有効期限日数  例: 365>        \
                      -extensions v3_ca                        \  # X.509 v3 CA拡張を使用(CAとしての役割を示す)
                      -keyout <出力する秘密鍵ファイル  例: ca.key> \
                      -out <出力する証明書ファイル  例: ca.crt>

# サーバ向けRSA秘密鍵を生成する
# 鍵の長さ (ビット数) を指定
# 2048ビットは現在の標準的なセキュリティレベル
# 4096ビットはより強力なセキュリティが必要な場合に使用
sudo openssl genrsa -out <生成した鍵の保存先  例: server.key> 2048

# 証明書署名要求 (CSR) を作成する
sudo openssl req -new -out <CSRの出力先  例: server.csr> -key <使用する秘密鍵の指定  例: server.key>

# CSRに対してCA証明書で署名して、サーバ証明書を作成する
sudo openssl x509 -req \
                  -in <署名対象のCSRファイル  例: server.csr>   \
                  -CA <署名に使用するCA証明書  例: ca.crt>       \
                  -CAkey <CA証明書の秘密鍵ファイル  例: ca.key>  \
                  -CAcreateserial                            \  # シリアル番号ファイルの作成
                  -out <生成される証明書の出力先  例: server.crt> \
                  -days <証明書の有効期限日数  例: 365>


上記のコマンドを実行することにより、以下に示すファイル群が生成される。

  • ca.key
    CA (証明局) の秘密鍵
  • ca.crt
    CA (証明局) の証明書
  • server.key
    サーバの秘密鍵
  • server.csr
    証明書署名要求
  • server.crt
    サーバの証明書


※注意
秘密鍵 (.keyファイル) は、絶対に外部に漏れないように、適切なパーミッションで保護する必要がある。
本番環境では、これらのファイルは安全な場所に保管して、定期的な更新を行うことを推奨する。

SSL/TLS証明書ファイルをMQTTの設定ファイルに記述する。

# SSL/TLS証明書の設定
listener 8883
cafile   /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key
tls_version tlsv1.2


動作確認

QoSとは

QoS (Quality of Service) は、MQTTにおけるメッセージ配信の信頼性を保証するための仕組みである。
数字は信頼性のレベルを表しており、以下に示すような意味を持つ。

  • QoS 0 (At most once)
    最も基本的なレベルである。
    メッセージは1度だけ送信され、配信確認は行われない。
    ベストエフォート型の配信で、メッセージが失われる可能性がある。
    例えば、センサデータのような、多少のデータ欠損が許容される用途に適している。

  • QoS 1 ((At least once)
    メッセージは少なくとも1回は配信されることが保証される。
    送信者は受信確認を待ち、確認が得られない場合は再送を行う。
    メッセージの重複を許容できる場合に使用する。
    例えば、ログデータの収集などに適している。

  • QoS 2 (Exactly once)
    最も信頼性の高いレベルである。
    4段階のハンドシェイクにより、メッセージが正確に1回だけ配信されることを保証する。
    金融取引や重要な制御命令等、メッセージの欠損も重複も許されない場合に使用する。


QoSレベルが上がるほど信頼性は向上するが、その分通信オーバーヘッドも増加する。

サブスクライバー (購読者) の起動
# 匿名ユーザを許可している場合
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "test/topic"> -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
## または
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "sensors/#"> -v -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>

# ユーザ認証を使用する場合
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "test/topic"> -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
## または
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "sensors/#"> -v -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>

# QoSを指定する場合
# QoS 1を使用
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> -t <購読するトピック  例: "important/data"> -q 1

# SSL/TLS証明書を使用してサブスクライブ
mosquitto_sub -h <IPアドレスまたはホスト名  例: localhost> \
              -t <購読するトピック  例: "secure/topic">   \
              -p 8883                                  \
              --cafile <SSL/TLS証明書ファイルのパス  例: /etc/mosquitto/certs/ca.crt> \
              --tls-version tlsv1.2


  • mosquitto_subコマンド
    MQTTメッセージを購読 (受信) するためのコマンドラインツールである。

  • -hオプション
    接続先のMQTTブローカーのIPアドレスまたはホスト名を指定する。

    localhostを指定する場合は、同じPC上のブローカーに接続される。
    別のサーバを指定する場合は、IPアドレスやドメイン名を指定する。

  • -tオプション
    購読するトピックを指定する。
    トピックは階層構造を持つことができる。
    トピックの例 : home/livingroom/temperature

  • -uオプション
    認証用のユーザ名を指定する。
  • -Pオプション
    認証用のパスワードを指定する。


その他のオプションを以下に示す。

  • -vオプション
    受信メッセージと共にトピック名も表示する。

  • -qオプション
    QoSレベルを指定する。
    指定できる値は、0、1、2のいずれかである。

  • --tls-versionオプション
    TLSバージョンを指定する。

  • --cafile
    CA証明書ファイルを指定する。


パブリッシャー (発行者) の実行
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> -t <発行するトピック  例: "test/topic"> -m "<メッセージ内容  例: Hello MQTT>" -u <MQTTユーザ名> -P <MQTTユーザ名のパスワード>
# または
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> -t <発行するトピック  例: "sensors/temperature"> -m "<メッセージ内容  例: 25.5"

# QoSを指定する場合
# QoS 1でパブリッシュ
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> -t <発行するトピック  例: "important/data"> -m <メッセージ内容  例: "Critical Info"> -q 1

# SSL/TLS証明書を使用してパブリッシュする場合
mosquitto_pub -h <IPアドレスまたはホスト名  例: localhost> \
              -t <発行するトピック  例: "secure/topic">   \
              -m <メッセージ内容  例: "Secure Message">   \
              -p 8883                                  \
              --cafile <SSL/TLS証明書ファイルのパス  例: /etc/mosquitto/certs/ca.crt> \
              --tls-version tlsv1.2


  • mosquitto_pubコマンド
    MQTTメッセージを発行 (送信) するためのコマンドラインツールである。

  • -hオプション
    接続先のMQTTブローカーのIPアドレスまたはホスト名を指定する。

    localhostを指定する場合は、同じPC上のブローカーに接続される。
    別のサーバを指定する場合は、IPアドレスやドメイン名を指定する。

  • -tオプション
    発行するトピックを指定する。
    トピックは階層構造を持つことができる。
    トピックの例 : home/livingroom/temperature

  • -mオプション
    送信するメッセージの内容を指定する。

  • -uオプション
    認証用のユーザ名を指定する。
  • -Pオプション
    認証用のパスワードを指定する。


その他のオプションを以下に示す。

  • -qオプション
    QoSレベルを指定する。
    指定できる値は、0、1、2のいずれかである。
    • 0 : メッセージは最大1回配信 (配信保証なし)
    • 1 : メッセージは最低1回配信
    • 2 : メッセージは正確に1回配信

  • -r
    リテインフラグを設定 (最後のメッセージを保持)
  • -n
    ヌルメッセージの送信 (メッセージ内容なし)

  • --tls-versionオプション
    TLSバージョンを指定する。

  • --cafile
    CA証明書ファイルを指定する。


動作確認

まず、MQTTブローカー (Mosquitto) を起動する。

sudo systemctl start mosquitto


次に、サブスクライバ側を待機させる。
ここでは、接続先のMQTTブローカーは自身のPC (localhost) とする。

# 匿名ユーザを許可している場合
mosquitto_sub -h localhost -t hoge/piyo

# ユーザ名 / パスワードを指定する場合
mosquitto_sub -h localhost -t hoge/piyo -u <ユーザ名> -P <パスワード>


パプリッシャー側でメッセージをパブリッシュする。
この時、任意のPCやデバイスが同じトピック名を持つメッセージを送信する時、サブスクライバ側は自動的に受信する。

# 匿名ユーザを許可している場合
mosquitto_pub -h localhost -t hoge/piyo -m "Hello, Mosquitto!"

# ユーザ名 / パスワードを指定する場合
mosquitto_sub -h localhost -t hoge/piyo -u <ユーザ名> -P <パスワード>


使用例

例えば、3台のデバイスに対して「LED照明を付けてほしい」とパブリッシャーが送信する場合、以下に示すようにMQTTトピックを効率的に使用する。
#は、MQTTトピックにおけるワイルドカードであり、該当する全てのトピックを購読することができる。

  • 共通トピックを使用する方法
# パブリッシャー側
mosquitto_pub -t "lights/all" -m "ON" -u <ユーザ名> -P <パスワード>

# サブスクライバ側 (各デバイス側)
mosquitto_sub -t "lights/all" -u <ユーザ名> -P <パスワード>


  • 個別制御も可能な階層的トピック構造
# 全体制御 (パブリッシャー側)
mosquitto_pub -t "lights/#" -m "ON" -u <共通のユーザ名> -P <共通のパスワード>

# 個別制御 (パブリッシャー側)
mosquitto_pub -t "lights/device1" -m "ON" -u <デバイス1のユーザ名> -P <デバイス1のパスワード>
mosquitto_pub -t "lights/device2" -m "OFF" -u <デバイス2のユーザ名> -P <デバイス2のパスワード>

# デバイス側は両方のトピックを購読 (サブスクライバ側)
# オプション1: 共通認証
mosquitto_sub -t "lights/#" -u <共通のユーザ名> -P <共通のパスワード>

# オプション2: デバイスごとの認証 (サブスクライバ側)
mosquitto_sub -t "lights/#" -u <デバイス1のユーザ名> -P <デバイス1のパスワード>
mosquitto_sub -t "lights/#" -u <デバイス2のユーザ名> -P <デバイス2のパスワード>


また、実務では、複数のデバイスで同じ認証情報を共有するケースは一般的である。(例: 同一のユーザ名とパスワードを使用するデバイスが3台ある場合)

  • メリット
    設定管理が簡単
    デバイスの追加が容易
  • デメリット
    セキュリティリスク (認証情報が漏洩した場合の影響大)
    個別デバイスの追跡が困難


ただし、セキュリティを重視する場合は、デバイスごとに異なる認証情報を設定することが推奨される。

運用時の注意
  • セキュリティ
    本番環境では必ずユーザ認証を使用する。
    機密性の高い情報を扱う場合はSSL/TLS暗号化を使用する。
    パスワードをコマンドラインで直接指定する代わりに、環境変数や設定ファイルを使用することを推奨する。


  • エラーハンドリング
    接続エラーや認証エラーの際のログを確認する。
    必要に応じて、-dオプション (デバッグモード) を付加して、詳細情報を確認する。

  • パフォーマンス
    大量のメッセージを扱う場合はQoSレベルを適切に選択する。
    リテインメッセージの使用は必要最小限に抑える。



接続の制限

mosquitto.confファイルでクライアント接続数を制限することができるが、デフォルトの設定では制限を課していない。
しかし、Linux OSでは制限を課しており、各ユーザに対して1024となっている。

この制限は、許可されるオープンファイルの最大数である。

コマンドラインからMosquittoを実行する場合

これは、limits.confファイル (/etc/security/limits.conf) を編集することにより、各ユーザごとに変更できる。

設定を反映させるため、PCを再起動する必要がある。

PCを再起動した後、制限が変更されているかどうかを確認する。

ulimit -Sn
# または
ulimit -Hn


ただし、上記の設定は、コマンドラインから起動したmosquittoにのみ影響する。

SystemdサービスからMosquittoを実行する場合

MosquittoをSystemdサービスとして起動する場合は、MosquittoのSystemdサービスユニットファイルに設定を追記する。

# mosquitto.serviceファイル

[Service]
# 最大接続数を4000に設定する場合
LimitNOFILE=4000


設定を有効にするため、PCを再起動する。

PCを再起動、および、Mosquittoサービスを実行した後、制限が変更されているかどうかを確認する。
これは、プロセスIDを取得することにより確認できる。

cat /proc/<PID>/limits