mosquittoにDBでパスワード要求機能をつける
概要
mosquittoはデフォルトでパスワード無しアクセスが可能です。セキュリティ的に問題がある場合はこの記事のようにファイル管理方式でパスワード要求を機能追加することが出来ますが、システムとして扱いづらい場合があります。この記事ではパスワード管理をDBで行わせます。これにより、Webアプリ経由でのユーザ任意のパスワード変更などに容易に対応できる様になります。
環境は以下図のとおりです。
ソフト環境
名前 | バージョン |
---|---|
OS | Ubuntu 20.04 |
docker | 24.0.2, build cb74dfc |
docker compose | v2.18.1 |
dockerコンテナ外のmosquitto | 1.6.9 |
ハード環境
名前 | バージョン |
---|---|
CPU | AMD Ryzen 9 3900XT 12-Core |
RAM | 76GB |
環境構築
このdocker-compose環境を作っておきましたので任意のディレクトリにて以下を実行してください。
git clone git@github.com:yosukeueda33/mosquitto-go-auth-example.git
cd mosquitto-go-auth-example
docker compose build
docker compose up
これによりlocalhost:21883経由でmosquitto_pub,subができるようになります。
確認
上記により出来た環境のpostgresには以下を受け付けるテーブルが予め設定されています。
username | password |
---|---|
user1 | password1 |
user2 | password2 |
user3 | password3 |
ホスト側のターミナルでsub側として以下を実行し[user3/password3]、
mosquitto_sub -d -V 5 -h localhost -p 21883 -t tmp/topic1 -u user3 -P password3
別のホスト側のターミナルでpub側として以下を実行すると[user1/password1]、
mosquitto_pub -d -V 5 -h localhost -p 21883 -t tmp/topic1 -u user1 -P password1 -m "hello"
sub側ターミナルにhelloが出力されます。以下は実行開始からhello受信までのsub側ターミナル出力です。
Client (null) sending CONNECT
Client auto-8815EB9D-DE2A-E301-CB44-CA4DAF13EE34 received CONNACK (0)
Client auto-8815EB9D-DE2A-E301-CB44-CA4DAF13EE34 sending SUBSCRIBE (Mid: 1, Topic: tmp/topic1, QoS: 0, Options: 0x00)
Client auto-8815EB9D-DE2A-E301-CB44-CA4DAF13EE34 received SUBACK
Subscribed (mid: 1): 0
Client auto-8815EB9D-DE2A-E301-CB44-CA4DAF13EE34 received PUBLISH (d0, q0, r0, m0, 'tmp/topic1', ... (5 bytes))
hello
なお、それぞれのコマンドのユーザ名やパスワードを間違ったものにしてみると以下のように出力されます。
Client (null) sending CONNECT
Client (null) received CONNACK (135)
Connection error: Not authorized
Client (null) sending DISCONNECT
解説
ディレクトリ構成は以下のようになっています。
├── docker-compose.yaml
├── mosquitto
│ └── Dockerfile
├── mosquitto-conf
│ ├── conf.d
│ │ └── go-auth.conf
│ └── mosquitto.conf
├── postgres
│ ├── Dockerfile
│ └── init.sql
init.sqlはユーザ認証用の以下のようなapp_userテーブルを作っています。
id | username | hash |
---|---|---|
1 | user1 | $2y |
2 | user2 | $2y |
3 | user3 | $2y |
hash列は以下コマンドにより生成したbcryptのhash値です。bcryptはハッシュ生成方式の一つです。内部でsalt値が変化するので同一引数でも実行毎に変化があります。
htpasswd -bnBC 10 "" password1 | tr -d ':\n'
user4などを新たに追加したい場合はpgAdminなどでinsertすれば良いです。その際のhashは上記のhtpasswdコマンドで同様に生成します。
上記app_userテーブルをmosquittoのプラグインであるmosquitto-go-authが参照できるようにgo-auth.confで設定しています。各値の詳細はリポジトリを参照されてください。特に重要なのは以下です。
auth_opt_pg_userquery select hash from "app_user" where username = $1 limit 1
これによりapp_userから対象ユーザのhashを取得し、プラグイン内でパスワードの検証を行います。
注意
以下、TLS/SSL通信無効化をgo-auth.confにて設定しています。運用時はenableしてください。
auth_opt_pg_sslmode disable
Discussion