MQTTとMosquitto
MQTT(MQ Telemetry Transport)はPublish/Subscribeモデルに基づく軽量なメッセージプロトコルで、Publisher(発信者)はServer(MQTTでは「Broker」と呼ぶのが一般的らしい)にメッセージを送信し、Subscriber(受信者)はBrokerからメッセージを受信します。直に通信した方が効率よさそうに見えますが、Subscriberが増えてもPublisherの負荷は変わらないメリットがあります。
で、Mosquittoは、MQTT Brokerのオープンソース実装です。
MQTTにつていは下記のサイトの解説が参考になると思います。
インストール
- Downloads | Mosquittoを見れば、だいたいのOSでのインストール方法が紹介されています。Windowsだけは少し特殊な感じです。
- SSLで接続する場合は、なるべく最新のバージョンをお勧めします。古いバージョンだと設定ミスなのか、バージョンが古いことが原因なのか切り分けが使いないことがあります。
CentOS7
$ sudo wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7/home:oojah:mqtt.repo -O "/etc/yum.repos.d/Mosquitto.repo"
$ sudo yum install mosquitto mosquitto-clients
EpalリポジトリにMosquitto(Brokerの方)は登録されているようですが、クライアントの方が登録されていないみたいなので、クライアントもインストールしたい場合はMosquittoのリポジトリを追加する必要があるようです。
Debian Linux8(Jessie)
GPG鍵のインストール
$ sudo wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
$ sudo apt-key add mosquitto-repo.gpg.key
mosquitto-jessie.listのインストール
$ sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list -O /etc/apt/sources.list.d/mosquitto-jessie.list
mosquittoのインストール
$ sudo apt-get update
$ sudo apt-get install mosquitto mosquitto-clients
詳しくは、Mosquitto Debian repositoryを参照してください。
Ubuntu Linux16.04
$ sudo apt-get install mosquitto mosquitto-clients
最新版をインストールしたい方は、
$ sudo add-apt-repository ppa:mosquitto-dev/mosquitto-ppa
を実行してMosquitto PPAリポジトリを追加してからインストールしてください。
FreeBSD 10.3
- pkgでインストールする場合
$ sudo pkg install mosquitto
- portsでインストールする場合
# cd /usr/ports/net/mosquitto/
# make install && make clean clean-depends
FreeBSDではmosquittoというパッケージにクライアントアプリも同梱されているみたいです。
動作確認
ターミナルを2つ開きます。一方のターミナルで、
$ mosquitto_sub -d -t orz
を実行しておき、別のターミナルで、
$ mosquitto_pub -d -t orz -m "^o^"
を実行すると、何事もなければ、mosquitto_subを実行したターミナルに「^o^」が表示されるはずです。
Mosquitto-TLS
サーバ証明書を用意するとSSLを利用してBrokerに接続できます。
- 自己認証局(オレオレ認証局)の開局
下記のコマンドで自己認証局を開局します。最初のパスワードの入力で4文字未満のパスワードを指定すると拒否されます。
$ openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt
- サーバ証明書の発行と署名
$ openssl genrsa -out server.key 2048
$ openssl req -out server.csr -key server.key -new
$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
とりあえず、ほかのパラメータは適当に指定しても問題なさそうですが、サーバ証明書のCommon NameとBrokerのFQDNは一致させる必要がありそうです。クライアントが接続するときError: Protocol error
となりました。
- mosquitto.confの設定
SSLで使用する各証明書ファイルのパスをmosquitto.confに追加します。ファイルのどこに書いても大丈夫そうです。
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
- 動作確認
$ mosquitto_sub -d -t orz -h <BrokerのFQDN> -p 8883 --cafile <ca.crtのパス>
$ mosquitto_pub -d -t orz -m "^o^" -h <BrokerのFQDN> -p 8883 --cafile <ca.crtのパス>
クライアント認証
上記の設定ではBroker⇔Publisher/Subscriber間の通信はSSLで暗号化されますが、Brokerでは、信頼できるPublisher/Subscriberからの接続かどうか判断できません。mosquitto.confにrequire_certificate trueを追加すると、正しいクライアント証明書を持つPublisher/Subscriberとだけ通信を行うようになります。
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true # これ追加。デフォルト値はfalseっぽい。
- クライアント証明書の発行
$ openssl genrsa -des3 -out client.key 2048
$ openssl req -out client.csr -key client.key -new
$ openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365
※ CAはMosquitto-TLSのところで作ったオレオレ認証局です。
- 動作確認
$ mosquitto_sub -d -t orz -h <BrokerのFQDN> -p 8883 --cafile <ca.crtのパス> --cert <client.crtのパス> --key <client.keyのパス>
$ mosquitto_pub -d -t orz -m "^o^" -h <BrokerのFQDN> -p 8883 --cafile <ca.crtのパス> --cert <client.crtのパス> --key <client.keyのパス>
秘密鍵のパスワードの解除
上記の作成方法で秘密鍵を作成した場合、mosquittoコマンドを入力する度に秘密鍵のパスワードの入力が必要なため、ディスプレイやキーボードを接続していないと運用できなくなります。下記の方法で秘密鍵のパスワードを解除できます。
$ cp client.key client_nopw.key
$ openssl rsa -in client.key -out client_nopw.key
初めからパスワード無しで運用することが前提の場合、
$ openssl genrsa -out client.key 2048
のように-des3
を付けずに秘密鍵を生成すれば、秘密鍵の暗号化が行われないため、パスワードの入力が不要です。
パスワード認証
mosquitto_passwd
コマンドでパスワードファイルを作成します。
$ sudo mosquitto_passwd -c /etc/mosquitto/pwfile mqtt
で、下記の設定をmosquitto.confに追加します。
allow_anonymous false
password_file /etc/mosquitto/pwfile
動作確認
$ mosquitto_sub -d -t orz -u mqtt -P mqtt
$ mosquitto_pub -d -t orz -m "^o^" -u mqtt -P mqtt