チーフエンジニアの鶴本です。
AWSでのMQTTはIoT Coreで利用できるのですが、そもそも自分で作って動かしてみようと思いEC2上で構築して動作検証してみましたので投稿します。
そもそもMQTTってなに?
IoT、M2M時代を支えるプロトコル「MQTT」( Message Queueing Telemetry Transport )のことです。
「Message Queueing」とは、送信側が送るデータをデータ領域に一旦保持しながら、受信側の処理が完了するのを待たずに次の処理へ移る方式です。
また「Telemetry Transport」とは遠隔測定用の通信を意味し、遠隔にあるセンサーやデバイスなどが収集したデータを、受信側の処理状況を気にせず効率よく送信することができるプロトコルです。
「MQTT」は一方向、1対1の通信のみでなく、双方向、1対多の通信が可能でありながら、プロトコルヘッダが小さくなっています。例えば、HTTPと「MQTT」のヘッダサイズを比べると「HTTP:50バイト~」に対して、「「MQTT」:2バイト~」となります。「MQTT」は、その軽量さから、バッテリーの消費を抑えたいモバイル向けの通信に適しています。
また「MQTT」のトラフィックは、HTTPに比べると10分の1になります。すなわち通信量やCPU負荷、電力消費量などを、従来の10分の1に抑えることができるのです。
かもめエンジニアリング「MQTTとは」より引用
MQTTのイメージ
早速、実践していきましょう!
慣れてる方なら、30分もかからないかな?
今回のゴール
- EC2にMosquittoを入れてブローカーとして起動する
- PCからEC2に構築したMosquittoに対してsubscribeする
- PCからEC2に構築したMosquittoに対してpublishし、subscribeしたPCでメッセージを受信する
- ブローカーに認証情報を追加して、認証情報が無い場合に接続を拒否する
構築
1.AWSのEC2のインスタンスを作成します
インスタンス手順は割愛します。
また、MQTTはport1883を利用しますので、セキュリティグループのインバウンドは1883を追加しましょう。
2.EC2にログインしての初期設定
EC2が作成された直後ですと、まっさらな状態のため、諸々設定していきます。
キーペアを使用して作成したEC2(以降、MQTT_Broker)にSSHログインします。
以下のコマンドをターミナルで実行します。
鶴本はキーペアファイルを「/Users/tsurumotokdi/work/aws/connect/」配下に置いたので
絶対パスで指定しています。
$ ssh -t -i /Users/tsurumotokdi/work/aws/connect/MQTT_Broker.pem -o StrictHostKeyChecking=no ec2-user@3.112.57.27
ターミナルで実行します。
残念です・・・。
アクセス権限関連で怒られてしまいました。
要約すると「誰にもアクセスできないようにせんかい!」ってことです。
今のキーペアはご覧の通りです。
キーペアのファイルのアクセス権限を変更し、再度トライします。
$ chmod 400 /Users/tsurumotokdi/work/aws/connect/MQTT_Broker.pem
成功しました!
それでは、初期設定をやっていきましょう。
まずはパッケージを更新
$ sudo yum update -y
パッケージの自動更新設定
# インストール
$ sudo yum install yum-cron -y
# 有効化確認
$ sudo chkconfig --list yum-cron
# 有効化
$ sudo chkconfig yum-cron on
# 自動更新設定
$ sudo sed -i "s/^apply_updates.*$/apply_updates = yes/g" /etc/yum/yum-cron.conf
# 起動
$ sudo service yum-cron start
# 起動確認
$ sudo service yum-cron status
良い感じになりました。
タイムゾーンを変更します。
# 現在の設定確認
$ date
# ローカルタイムを【Japan】に変更
$ sudo ln -sf /usr/share/zoneinfo/Japan /etc/localtime
# ハードウェアクロックを【Japan】に変更
$ sudo sed -i "s/\"UTC\"/\"Japan\"/g" /etc/sysconfig/clock
# システム再起動
$ sudo reboot
# 現在の設定確認
$ date
無事、タイムゾーンが日本時間になりました。
3.mosquittoのインストール
以下のコマンドでyumを使ってmosquittoをインストールしましょう。
$ sudo yum install mosquitto -y
残念!できませんでした。
というのもmosquittoは、epelリポジトリに属していて、そのリポジトリがEC2上で使えないからです。
というわけで、epelリポジトリを使えるようにしたあと、再度トライします。
# epelリポジトリのインストール
$ sudo amazon-linux-extras install epel -y
# mosquittoのインストール
$ sudo yum install mosquitto -y
無事できました!
4.mosquittoを起動してローカルPCからEC2経由でメッセージを送信&受信してみる
ここから3つのターミナルウィンドウを使用して諸々試してみます。
ターミナルウィンドウは以下の色で判別してください。
・黒 = EC2 MQTT ブローカー
・緑 = Subscriber(メッセージ受信者)
・青 = Publisher(メッセージ送信者)
まずは、EC2のBrokerを起動します。
黒のターミナルで以下のコマンドを入力します。
$ mosquitto
次に緑のターミナルでEC2のブローカーに対して、メッセージ受信待ちの状態を作ります。
以下のコマンドでメッセージ受信状態になります。
この時、EC2へのIPアドレスで接続します。覚えていますか?「3.112.57.27」です。
$ mosquitto_sub -p 1883 -h 3.112.57.27 -t "tp1/test" -I "sub_tsurumoto_pc"
コマンドのオプションは以下のような意味を持ちます。
-p:ポート番号
-h:ブローカーへのホスト(EC2のIPアドレスで良い)
-t:トピック
→メッセージを受信する際のセグメントみたいなものです。
一致するトピックのメッセージが送信されないと、受信側はメッセージを受信しません。
-I:l(エル)ではなくI(アイ)です。クライアントIDの指定です。
ブローカーでどのクライアントIDが接続されたか判別できます。
メッセージ待ち状態になりました。
黒のターミナルでも、sub_tsurumoto_pcが接続したことが確認できます。
青のターミナルでEC2のブローカーに対して以下のコマンドでメッセージを送信します。
$ mosquitto_pub -p 1883 -h 3.112.57.27 -m "hello" -t "tp1/test" -I "pub_tsurumoto_pc"
コマンドのオプションは以下のような意味を持ちます。
-p:ポート番号
-h:ブローカーへのホスト(EC2のIPアドレスで良い)
-t:トピック(このトピックでサブスクライブしているメッセージ受信者にメッセージを送ります)
-m:メッセージ内容
-I:l(エル)ではなく、I(アイ)です。クライアントIDの指定です。
ブローカーでどのクライアントIDが接続されたか判別できます。
メッセージを送信しました。
緑のターミナルではメッセージを受信できています。
黒のターミナルで青のターミナルからメッセージ送信のためにブローカーに接続し、
切断されたことが確認できます。
やったね!
5.認証情報込みでメッセージの送受信をしてみる
今はECのIPアドレスが分かれば誰でも接続できちゃうので、
認証情報(ユーザID/パスワード)が無いと接続拒否するようにしてみましょう。
まずは、動いている黒のターミナルでCtrl+Cでブローカーを終了します。
認証情報付きでブローカーを起動するには、以下のファイルが必要です。
・設定ファイル
・認証情報ファイル
まずは、設定ファイルから作成します。
黒のターミナルで設定ファイルを作成します。
$ touch mosquitto.conf
以下の内容でconfの内容を修正します。
allow_anonymous false
password_file password.txt
※設定できる項目はたくさんありますが、認証を実現するために最小限の設定にしています。
allow_anonymousは認証情報が一致しない場合、接続を許可するか判断する設定項目です。
falseにすることで認証情報が違う場合に接続を拒否できます。
password_fileは認証情報が記載されたファイルへのパスを記載します。
とりあえず、confファイルを作成し修正しました。
次に認証情報ファイルを作成します。
$ touch password.txt
password.txtに以下の認証情報を記載します。
tsurumotokdi:password
これは、tsurumotokdiというユーザ名でpasswordというパスワードを設定しています。
やってみました。
これだと、どんなユーザIDとパスワードでアクセスできるか分かってしまうので、暗号化します。
yumでインストールしたmosquittoのライブラリにあるコマンドを使用します。
$ mosquitto_passwd -U password.txt
無事、暗号化されました!
これで準備は整いましたので、黒のターミナルでブローカーを起動します。
ブローカーを起動する際に「-c」オプションを使用してconfファイルを指定してあげます。
これで、認証情報がないと接続できないようになりました。
緑と青のターミナルで認証情報なしでアクセスしてみます。
$ mosquitto_sub -p 1883 -h 3.112.57.27 -t "tp1/test" -I "sub_tsurumoto_pc"
$ mosquitto_pub -p 1883 -h 3.112.57.27 -m "hello" -t "tp1/test" -I "pub_tsurumoto_pc"
期待通りですね!
黒のターミナルでも接続させなかったことが伺えます。
次は認証情報ありで接続します。
オプションとして「-u(ユーザ名)」と「-P(パスワード)」を設定してコマンドを実行します。
$ mosquitto_sub -p 1883 -h 3.112.57.27 -t "tp1/test" -I "sub_tsurumoto_pc" -u "tsurumotokdi" -P "password"
メッセージ受信状態になりました。
送信側も同様です。
$ mosquitto_pub -p 1883 -h 3.112.57.27 -m "hello" -t "tp1/test" -I "pub_tsurumoto_pc" -u "tsurumotokdi" -P "password"
ちゃんとメッセージが受信できています。
ブローカーもちゃんと動作しています!