前書き
MQTTは、「モノのインターネット」デバイスへの軽量のパブリッシュ/サブスクライブ通信を提供するように設計された、マシンツーマシンメッセージングプロトコルです。 一般的に、車両のジオトラッキング車両、ホームオートメーション、環境センサーネットワーク、ユーティリティスケールのデータ収集に使用されます。
Mosquittoは人気のあるMQTTサーバー(またはMQTT用語ではbroker)であり、優れたコミュニティサポートがあり、インストールと構成が簡単です。
このチュートリアルでは、Mosquittoをインストールし、Let’s EncryptからSSL証明書を取得し、SSLを使用してパスワードで保護されたMQTT通信を保護するようにブローカーを設定します。
前提条件
このチュートリアルを開始する前に、次のものが必要です。
-
非ルート、sudo対応ユーザー、および基本的なファイアウォールがセットアップされたCentOS 7サーバー。 これ(およびそれ以上)はすべてNew CentOS 7 Server Checklistでカバーされます。
-
How to Set Up a Host Name with DigitalOceanに従って、サーバーを指すドメイン名。 このチュートリアルでは、全体を通して
mqtt.example.com
を使用します。 -
オプションで、
nano
テキストエディタ。 このチュートリアルでは全体でnano
を使用し、いつでもsudo yum -y install nano
を使用してインストールするか、お気に入りのテキストエディターに置き換えることができます。
[[step-1 -—- installing-mosquitto]] ==ステップ1—Mosquittoのインストール
CentOS 7には、デフォルトでmosquitto
パッケージがありません。 それをインストールするには、まず、Enterprise LinuxのExtra PackagesまたはEPELと呼ばれる追加のソフトウェアリポジトリをインストールします。 このリポジトリには、CentOS、Red Hat、およびその他のエンタープライズ指向のLinuxディストリビューションに適切にインストールされる追加のソフトウェアがいっぱいです。
root以外のユーザーでログインし、yum
パッケージマネージャーを使用してepel-release
パッケージをインストールします。
sudo yum -y install epel-release
これにより、EPELリポジトリ情報がシステムに追加されます。 -y
オプションは、プロセス全体を通じていくつかのプロンプトに自動的に「はい」と答えます。 これで、mosquitto
パッケージをインストールできます。
sudo yum -y install mosquitto
パッケージにはシンプルなデフォルト構成が付属しているため、インストールをテストするために実行してみましょう。
sudo systemctl start mosquitto
また、システムを再起動したときに確実に起動するように、サービスを有効にする必要があります。
sudo systemctl enable mosquitto
それでは、デフォルトの構成をテストしましょう。 mosquitto
パッケージには、いくつかのコマンドラインMQTTクライアントが付属しています。 そのうちの1つを使用して、ブローカーに関するトピックをサブスクライブします。
Topicsは、メッセージを公開およびサブスクライブするラベルです。 これらは階層として配置されているため、たとえば、sensors/outside/temp
とsensors/outside/humidity
を使用できます。 トピックの配置方法は、あなたとあなたのニーズ次第です。 このチュートリアルでは、簡単なテストトピックを使用して構成の変更をテストします。
サーバーに2回ログインすると、2つの端末が並んでいます。 新しいターミナルで、mosquitto_sub
を使用してテストトピックをサブスクライブします。
mosquitto_sub -h localhost -t test
-h
はMQTTサーバーのホスト名を指定するために使用され、-t
はトピック名です。 mosquitto_sub
はメッセージの到着を待機しているため、ENTER
を押しても出力は表示されません。 他の端末に切り替えて、メッセージを公開します。
mosquitto_pub -h localhost -t test -m "hello world"
mosquitto_pub
のオプションはmosquitto_sub
と同じですが、今回は追加の-m
オプションを使用してメッセージを指定します。 ENTER
を押すと、他の端末にhello worldがポップアップするはずです。 最初のMQTTメッセージを送信しました!
2番目の端末にCTRL+C
を入力して、mosquitto_sub
を終了しますが、サーバーへの接続は開いたままにします。 手順5の別のテストで再び使用します。
次に、新しいLet's EncryptクライアントであるCertbotを使用して、SSLでインストールを保護します。
[[step-2 -—- installing-and-running-certbot-for-let-39-s-encrypt-certificates]] ==ステップ2— Let’sEncrypt証明書用のCertbotのインストールと実行
Let's Encryptは、自動化されたAPIを介して無料のSSL証明書を提供する新しいサービスです。 公式のLet's EncryptクライアントはCertbotと呼ばれ、前のステップでインストールしたEPELリポジトリに含まれています。
yum
を使用してCertbotをインストールします。
sudo yum -y install certbot
Certbotは、ドメインを制御していることを証明するために、Let’s Encrypt APIによって発行された暗号化の課題に答える必要があります。 これを実現するために、ポート80
(HTTP)および/または443
(HTTPS)を使用します。 ポート80
のみを使用するので、ここでそのポートでの着信トラフィックを許可しましょう。
firewall-cmd
を使用してHTTPサービスを追加します。
sudo firewall-cmd --permanent --add-service=http
ファイアウォールをリロードして、変更を有効にします。
sudo firewall-cmd --reload
これで、Certbotを実行して証明書を取得できます。 --standalone
オプションを使用して、HTTPチャレンジリクエストを独自に処理するようにCertbotに指示し、--standalone-supported-challenges http-01
は通信をポート80
に制限します。 -d
は、証明書が必要なドメインを指定するために使用され、certonly
は、他の構成手順を実行せずに証明書を取得するようにCertbotに指示します。
sudo certbot certonly --standalone --standalone-supported-challenges http-01 -d mqtt.example.com
コマンドを実行すると、メールアドレスを入力し、利用規約に同意するよう求められます。 そうすると、プロセスが正常に完了し、証明書が保存されている場所を示すメッセージが表示されます。
証明書を取得しました。 次に、Certbotが期限切れになったときに自動的に更新するようにする必要があります。
[[step-3 -—- setting-up-certbot-automatic-renewals]] ==ステップ3—Certbot自動更新の設定
Let's Encryptの証明書は90日間のみ有効です。 これは、ユーザーが証明書の更新プロセスを自動化することを奨励するためです。 有効期限が切れる証明書を確認して自動的に更新するために、定期的に実行するコマンドを設定する必要があります。
更新チェックを毎日実行するために、定期的なジョブを実行するための標準システムサービスであるcron
を使用します。 crontab
というファイルを開いて編集することにより、cron
に何をすべきかを指示します。
sudo EDITOR=nano crontab -e
EDITOR=nano
は、crontabファイルをnano
エディターで開きます。 デフォルトのvi
エディターを使用する場合は、オフのままにします。
これで、デフォルトのcrontab
、つまり空白のファイルが表示されます。 次の行に貼り付けてから、ファイルを保存して閉じます。
crontab
15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"
この行の15 3 * * *
の部分は、「毎日午前3時15分に次のコマンドを実行する」ことを意味します。 Certbotのrenew
コマンドは、システムにインストールされているすべての証明書をチェックし、30日以内に期限切れになるように設定されている証明書を更新します。 --noninteractive
は、ユーザー入力を待たないようにCertbotに指示します。
--post-hook "systemctl restart mosquitto"
は、証明書が更新された場合にのみ、Mosquittoを再起動して新しい証明書を取得します。
証明書の自動更新がすべて設定されたので、Mosquittoをより安全に設定することに戻ります。
[[step-4 -—- configuring-mqtt-passwords]] ==ステップ4—MQTTパスワードの構成
パスワードを使用するようにMosquittoを設定しましょう。 Mosquittoには、mosquitto_passwd
と呼ばれる特別なパスワードファイルを生成するユーティリティが含まれています。 このコマンドは、指定されたユーザー名のパスワードを入力するように求め、結果を/etc/mosquitto/passwd
に配置します。
sudo mosquitto_passwd -c /etc/mosquitto/passwd sammy
ここで、デフォルトの構成ファイルを置き換え、Mosquittoにこのパスワードファイルを使用してすべての接続にログインを要求するように指示します。 まず、既存のmosquitto.conf
を削除します。
sudo rm /etc/mosquitto/mosquitto.conf
そして、新しい空の設定を開きます。
sudo nano /etc/mosquitto/mosquitto.conf
以下に貼り付けます。
/etc/mosquitto/mosquitto.conf
allow_anonymous false
password_file /etc/mosquitto/passwd
allow_anonymous false
は認証されていないすべての接続を無効にし、password_file
行はMosquittoにユーザーとパスワードの情報を探す場所を指示します。 ファイルを保存して終了します。
次に、Mosquittoを再起動して、変更をテストする必要があります。
sudo systemctl restart mosquitto
パスワードなしでメッセージを公開してみてください。
mosquitto_pub -h localhost -t "test" -m "hello world"
メッセージは拒否されるべきです:
OutputConnection Refused: not authorised.
Error: The connection was refused.
パスワードを再試行する前に、2番目のターミナルウィンドウに再度切り替えて、今回はユーザー名とパスワードを使用して「テスト」トピックにサブスクライブします。
mosquitto_sub -h localhost -t test -u "sammy" -P "password"
接続して座って、メッセージを待つ必要があります。 定期的にテストメッセージを送信するため、このターミナルを開いたままにしてチュートリアルの残りの部分で接続しておくことができます。
ユーザー名とパスワードを使用して、もう一方の端末でメッセージを公開します。
mosquitto_pub -h localhost -t "test" -m "hello world" -u "sammy" -P "password"
メッセージはステップ1のように通過するはずです。 Mosquittoにパスワード保護を追加しました。 残念ながら、暗号化されていないパスワードをインターネット経由で送信しています。 次に、MosquittoにSSL暗号化を追加して、これを修正します。
[[step-5 -—- configuring-mqtt-ssl]] ==ステップ5— MQTTSSLの構成
SSL暗号化を有効にするには、Let's Encrypt証明書の保存場所をMosquittoに伝える必要があります。 以前に開始した構成ファイルを開きます。
sudo nano /etc/mosquitto/mosquitto.conf
ファイルの最後に以下を貼り付けて、追加した2行を残します。
/etc/mosquitto/mosquitto.conf
. . .
listener 1883 localhost
listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
2つの別々のlistener
ブロックを構成に追加します。 最初のlistener 1883 localhost
は、ポート1883
のデフォルトのMQTTリスナーを更新します。これは、これまで接続してきたものです。 1883
は、暗号化されていない標準のMQTTポートです。 行のlocalhost
部分は、このポートをlocalhostインターフェイスにのみバインドするようにMosquittoに指示しているため、外部からアクセスすることはできません。 いずれにせよ、外部リクエストはファイアウォールによってブロックされていたはずですが、明示するのは良いことです。
listener 8883
は、ポート8883
に暗号化されたリスナーを設定します。 これは、MQTT + SSLの標準ポートであり、MQTTSとも呼ばれます。 次の3行、certfile
、cafile
、およびkeyfile
はすべて、Mosquittoが適切なLet’sEncryptファイルをポイントして暗号化された接続をセットアップすることを示しています。
ファイルを保存して終了します。
Mosquittoを再起動して新しい構成をロードする前に、デフォルトのmosquitto
サービスファイルで1つ修正する必要があります。 これは、systemd
がmosquitto
の実行方法を決定するために使用するファイルです。 お気に入りのエディターで開きます。
sudo nano /etc/systemd/system/multi-user.target.wants/mosquitto.service
User=mosquitto
という行を探して削除し、ファイルを保存して終了します。
Mosquittoは引き続きmosquittoユーザーとして実行されますが、最初に起動したときはroot特権があり、Let's Encrypt証明書(rootに制限されています)をロードできます。アクセス、セキュリティ上の理由から)。 証明書をロードした後、mosquittoユーザーにドロップダウンします。
systemd
自体をリロードする必要があるため、サービスファイルに加えた変更が認識されます。
sudo systemctl daemon-reload
そして今、Mosquittoを再起動して設定を更新できます。
sudo systemctl restart mosquitto
ポート8883
への接続を許可するようにファイアウォールを更新します。
sudo firewall-cmd --permanent --add-port=8883/tcp
そして、ファイアウォールをリロードします。
sudo firewall-cmd --reload
ここで、SSLのいくつかの異なるオプションを使用して、mosquitto_pub
を使用して再度テストします。
mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --cafile /etc/ssl/certs/ca-bundle.crt -u "sammy" -P "password"
localhost
の代わりに完全なホスト名を使用していることに注意してください。 SSL証明書はmqtt.example.com
に対して発行されるため、localhost
に安全に接続しようとすると、ホスト名が証明書のホスト名と一致しないというエラーが表示されます(両方が同じモスキートを指している場合でも)サーバ)。
--cafile /etc/ssl/certs/ca-bundle.crt
はmosquitto_pub
のSSLを有効にし、ルート証明書を探す場所を指示します。 これらは通常、オペレーティングシステムによってインストールされるため、Mac OS、Windowsなどではパスが異なります。 mosquitto_pub
は、ルート証明書を使用して、Mosquittoサーバーの証明書がLet’sEncrypt認証局によって適切に署名されていることを確認します。 %の標準の安全なポートに接続している場合でも、mosquitto_pub
とmosquitto_sub
はこのオプション(または同様の--capath
オプション)なしではSSL接続を試行しないことに注意することが重要です。 (t6)s。
すべてがテストに問題がなければ、hello againが他のmosquitto_sub
ターミナルに表示されます。 これは、サーバーが完全にセットアップされたことを意味します! MQTTプロトコルを拡張してWebソケットで動作するようにしたい場合は、最後の手順に従ってください。
[[step-6 -—- configuring-mqtt-over-websockets-optional]] ==ステップ6— MQTT Over Websocketの設定(オプション)
Webブラウザ内からJavaScriptを使用してMQTTを話すために、プロトコルは標準のWebソケット上で動作するように適合されました。 この機能が必要ない場合は、この手順をスキップできます。
Mosquitto構成にもう1つのlistener
ブロックを追加する必要があります。
sudo nano /etc/mosquitto/mosquitto.conf
ファイルの最後に、次を追加します。
/etc/mosquitto/mosquitto.conf
. . .
listener 8083
protocol websockets
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
これは、ポート番号とprotocol websockets
行を除いて、前のブロックとほとんど同じです。 WebSocketを介したMQTTの公式の標準化されたポートはありませんが、8083
が最も一般的です。
ファイルを保存して終了し、Mosquittoを再起動します。
sudo systemctl restart mosquitto
次に、ファイアウォールでポート8083
を開きます。
sudo firewall-cmd --permanent --add-port=8083/tcp
最後にもう一度ファイアウォールをリロードします。
sudo firewall-cmd --reload
この機能をテストするには、ブラウザベースの公開MQTTクライアントを使用します。 そこにはいくつかありますが、mqtt-adminは単純で単純です。 Open mqtt-admin in your browser。 以下が表示されます。
接続情報を次のように入力します。
-
Protocolはwss(websocketsecureの略)である必要があります。
-
Hostは、Mosquittoサーバーのドメイン
mqtt.example.com
である必要があります。 -
Portは
8083
である必要があります。 -
UserはMosquittoのユーザー名である必要があります。ここでは、sammyを使用しました。
-
Passwordは選択したパスワードである必要があります。
-
ClientIdは、デフォルト値のmqtt-adminのままにしておくことができます。
Save Settingsを押すと、mqtt-admin
はMosquittoサーバーに接続します。 次の画面で、Topicをtestとして入力し、Payloadのメッセージを入力して、Publishを押します。 メッセージはmosquitto_sub
ターミナルに表示されます。
結論
Let's EncryptサービスからのSSL証明書を自動更新する、安全でパスワードで保護されたMQTTサーバーをセットアップしました。 これは、どんなプロジェクトを考えても堅牢で安全なメッセージングプラットフォームとして機能します。 MQTTプロトコルで適切に動作する一般的なソフトウェアとハードウェアには次のものがあります。
-
OwnTracks、携帯電話にインストールできるオープンソースの地理追跡アプリ。 OwnTracksは定期的に位置情報をMQTTサーバーに報告します。MQTTサーバーは、マップに保存して表示したり、位置に基づいてアラートを作成してIoTハードウェアをアクティブにしたりできます。
-
Node-REDは、モノのインターネットを「配線」するためのブラウザベースのグラフィカルインターフェイスです。 あるノードの出力を別のノードの入力にドラッグすると、フィルターを介して、さまざまなプロトコル間で、データベースなどに情報をルーティングできます。 MQTTはNode-REDで非常によくサポートされています。
-
ESP8266は、MQTT機能を備えた安価なwifiマイクロコントローラーです。 温度データをトピックに公開するために配線するか、気圧のトピックにサブスクライブして、嵐が来ているときにブザーを鳴らすことができます!
これらは、MQTTエコシステムの一般的な例のほんの一部です。 プロトコルを話すハードウェアとソフトウェアがはるかに多くあります。 お気に入りのハードウェアプラットフォームまたはソフトウェア言語を既にお持ちの場合は、MQTT機能を備えている可能性があります。 あなたの「もの」が互いに話し合うのを楽しんでください!