モチベーション
- 外出先から家の中にあるラズパイにMQTTでメッセージを送りたい
- 例えば出先からラズパイにMQTTで指令を送り、何か室内にあるIoT機器に何かコマンドを送る、といったことをしたい
- 公衆のMQTTブローカもあるようだが、topicが衝突したときのリスクがよくわからないので自分専用のブローカがしい
- VPSと呼ばれる仮想レンタルサーバを使ってインターネット上に個人用MQTTブローカをセットアップしたい
VPSのセットアップ
今回は(株)NTTPCコミュニケーションズが提供しているWebArena Indigo®というサービスを使うことにした。
MQTTのブローカとしてしか使わないからミニマムな構成でよく、その条件だと月額449円(2025年9月時点)で使えるとのことなので試してみることにした。
お申込みボタンからアカウント開設の手続きを行うことができる。
- アカウント開設の際、クレジットカードの登録が平日の昼間しかできないので注意
- またクレカ登録時に10,000円の請求がいきなり飛んできてビビるが、これは与信なので後で返ってくるはずである
無事アカウントを開設できたらログインし、このスタートアップガイドの "4.SSH接続でインスタンスにログインする"まで進める
ちなみに自分はubuntu24.04の1GB RAMを選択した。
ユーザ管理
デフォルトでubuntuというユーザが登録されているのだが、これを消して自分のユーザを作る。
以下のコマンドで自分用のユーザを作り、次いでにsudoコマンドが使えるようsudoグループにも登録しておく。
# create own user
sudo adduser <your user>
sudo gpasswd -a <your user> sudo
その後作ったユーザにログインしなおして、ubuntuユーザを削除する
# logout from ubuntu user
exit
# ssh connection with created user
ssh <your user>@<ip address> -p 22
# delete ubuntu user
sudo userdel -r ubuntu
参考
SSH設定
次にSSH回りの設定を行う。/etc/ssh/sshd_configにSSHの設定が定義されているので、以下のように書き換える。
# sshのウェルノウンポートである22から任意のポート番号に変更
Port <your prefered ssh port>
:
# ルートユーザでのログインの禁止
PermitRootLogin no
:
# パスワード認証の禁止
PasswordAuthentication no
その後sshをリスタートして接続できるかどうかを試す。
sudo systemctl restart ssh
おそらくこれはよく使われる設定だと思うのだが、これを適用したらSSH接続できなくなってしまった。
調べてみたところ、どうも最新のUbuntu24.04だとssh.socketの設定も変えないといけないそうだ。
/lib/systemd/system/ssh.socketにあるListenStreamの値もsshd_configで指定したポート番号を設定する必要がある。
[Socket]
ListenStream=<your prefered port>
Accept=no
設定したらsystemdをリロードしてssh.socketも再起動させる。
こうすればSSH接続はできるようになっているはずである。
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
参考
mosquittoの設定
mosquittoをインストールする。
sudo apt-get update
sudo apt-get install mosquitto
その後、/etc/mosquitto/mosquitto.confから、MQTTで使用するポートを設定する
- SSHで使うポートとは別の番号にする
- そのほかの設定は後述
listener <your prefered mqtt port>
MQTTがインストールできたらFirewallを設定してSSHとMQTTで使用するポートのみを通すようにする
sudo ufw disable
sudo ufw default deny
sudo ufw allow <ssh port>
sudo ufw allow <mqtt port>
sudo ufw enable
参考
TLS通信の設定
以前の記事でMQTTブローカーとクライアント認証で
注意する点はCNをちゃんと書くことと、サーバ証明書にSANを書くこと
SANの設定に関してはこのサイトを参考にした
CA証明書
自分しか使わないサービスなので自己CAで証明書をつくる。
openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt
サーバ証明書
サーバ証明書を作成する前にSANを定義したファイルを作る。
ドメインをとっていなければサーバのIPアドレスだけでよい。
# san.txt
subjectAltName = IP:<ip address>
SANの定義ファイルを作ったら以下のようにサーバ証明書を発行する。
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 -extfile san.txt
mosquittoへ証明書を登録
CA証明書とサーバ証明書ができたらca.crtを/etc/mosquitto/ca_certificatesに、server.crtとserver.keyを/etc/mosquitto/certsに移動させる。
server.crtとserver.keyのオーナーを確認して、もしmosquittoになっていなければchownでオーナーを変更する。
sudo chown mosquitto:mosquitto server.crt
sudo chown mosquitto:mosquitto server.key
その後/etc/mosquitto/mosquitto.confを以下のように設定し、sudo systemctl restart mosquitto
でmosquittoを再起動させる。
listener <your prefered port>
allow_anonymous false
use_identity_as_username true
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true
tls_version tlsv1.2
クライアント証明書
以下のようにクライアント証明書を作る。
openssl genrsa -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
ここまでは前回と同じだが、今回は後述のアプリがPKCS12形式にしか対応していないため、以下のように作成した
openssl pkcs12 -export -inkey client.key -in client.crt -certfile ca.crt -out client.p12
アプリの設定
今回使用したアプリはAndroidのIoT MQTT Panelである。
MQTTクライアントアプリは色々存在するが、このアプリはクライアント証明書認証に対応しているので採用した。
まずはscpコマンド等でca.crtとclient.p12をサーバからダウンロードし、Androidスマートフォンへ転送する。
- Windowsからダウンロードするとセキュリティでブロックされるかもしれないので、その場合は一時的に以下のトグルをオフにしておく。
IoT MQTT Panelアプリを立ち上げConnections画面を開き、新たなConnectionを作成する。
右下の+ボタンを押すと設定画面が出てくるので、適宜サーバのアドレスやMQTT用に開いたポートを設定する。
- Network protocolをTCP-SSLにすると証明書を選択できるようになるので、以下のようにダウンロードしてきた証明書を指定する
- CA certificate: ca.crt
- Client certificate: client.p12
saveを押すと接続を試みる。
接続できた場合はダッシュボートが開き、panelと呼ばれるいろいろなウィジェットを配置できるようになる。
いろいろなpanelがあるので各自調べてもらえばいいが、試しに以下のようにButtonとText Logを配置してみた。
- Buttonはボタンを押すと"button"トピックに"hello world"というペイロードを持つMQTT PUBLISHを送信する
- Text Logは"button"トピックにメッセージが来たらペイロードを表示する
Testボタンを押すとサーバ上にあるブローカまでメッセージが飛び、またブローカからメッセージが配信される。
スクリーンショットにあるように、logパネルにペイロードが表示されることが確かめられた。
まとめ
VPSを利用してインターネット上に個人用のMQTTブローカを立ち上げて、MQTTのPublish・Subscribeできることを確かめた。
この記事ではPublishもSubscribeも同じスマホアプリで行ったが、ラズパイ上のアプリからこのブローカに接続すればインターネット越しに家の中のラズパイにメッセージを送れるようになるはずである。