Web - MQTTブローカー
概要
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ブローカーサービス (無料 / 有料)
- HiveMQ Cloud (無料枠あり)
- 100台までのデバイス接続可能。
- TLS暗号化対応。
- 10[KB]/秒までのデータ転送可能。
- 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通信を使用することを推奨する。
- 定期的にログを確認して、不正なアクセスがないか監視すること。
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 <追加するユーザ名>
Mosquittoの設定
まず、Mosquittoの設定ファイルを作成する。
sudo vi /etc/mosquitto/conf.d/default.conf
次に、Mosquittoの設定を記述する。
# ポート設定 listener 1883 # 匿名接続の許可 / 不許可 allow_anonymous false # パスワードファイルの指定 password_file /etc/mosquitto/passwd
セキュリティ設定 (推奨)
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 # 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証明書ファイルを指定する。
運用時の注意
- セキュリティ
- 本番環境では必ずユーザ認証を使用する。
- 機密性の高い情報を扱う場合はSSL/TLS暗号化を使用する。
- パスワードをコマンドラインで直接指定する代わりに、環境変数や設定ファイルを使用することを推奨する。
- エラーハンドリング
- 接続エラーや認証エラーの際のログを確認する。
- 必要に応じて、
-d
オプション (デバッグモード) を付加して、詳細情報を確認する。
- パフォーマンス
- 大量のメッセージを扱う場合はQoSレベルを適切に選択する。
- リテインメッセージの使用は必要最小限に抑える。