📬

mosquittoにDBでパスワード要求機能をつける

2023/08/31に公開

概要

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 $2y10PU/qFWHZanUMGYb/Y86U5uQuHgd31QWu4e10.UKGTUe5xpVoKyxZK
2 user2 $2y10heK/EtaT56.zAIvu.PTsxOip9/S2.lMWIimRJdNKQQRyD1bfg5DMG
3 user3 $2y10D4RLlLWqb/vpSLQyYM98t.UOxCcYsHcfSHLZ2a7A4HsyRYhQsXIli

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