配置使用 mysql 作為 be (back end)
- 使用config.mk 配置編譯參數(shù)
cp config.mk.in config.mk - 修改
安裝 mysql
sudo apt-get install mysql-server libmysqlclient-dev
# Select your backends from this list
BACKEND_CDB ?= no
BACKEND_MYSQL ?= yes # 使用 mysql
BACKEND_SQLITE ?= no
BACKEND_REDIS ?= no
BACKEND_POSTGRES ?= no
BACKEND_LDAP ?= no
BACKEND_HTTP ?= no
BACKEND_JWT ?= no
BACKEND_MONGO ?= no
BACKEND_FILES ?= no
# Specify the path to the Mosquitto sources here
# MOSQUITTO_SRC = /usr/local/Cellar/mosquitto/1.4.12
MOSQUITTO_SRC =/mnt/g/cjc/workspace/mqtt/mosquitto # 指定mosquitto源碼
# Specify the path the OpenSSL here
OPENSSLDIR = /usr
# Specify optional/additional linker/compiler flags here
# On macOS, add
# CFG_LDFLAGS = -undefined dynamic_lookup
# as described in https://github.com/eclipse/mosquitto/issues/244
#
# CFG_LDFLAGS = -undefined dynamic_lookup -L/usr/local/Cellar/openssl/1.0.2l/lib
# CFG_CFLAGS = -I/usr/local/Cellar/openssl/1.0.2l/include -I/usr/local/Cellar/mosquitto/1.4.12/include
CFG_LDFLAGS =
CFG_CFLAGS =
編譯plugin
make
得到 auth-plug.so
編譯 mosquitto
修改 mosquitto-mysql.conf
參考 mosquitto-auth-plug/examples/mosquitto-mysql.conf 中的 插件附加選項(xiàng),增加到 mosquitto-mysql.conf 中
# 插件so路徑
auth_plugin /mnt/g/cjc/workspace/mqtt/mosquitto-auth-plug/auth-plug.so
auth_opt_backends mysql
auth_opt_cdbname pwdb.cdb
auth_opt_host localhost
auth_opt_port 3306
auth_opt_dbname mqtttest
auth_opt_user root
auth_opt_pass root
# mysql 查詢語(yǔ)句約定
auth_opt_userquery SELECT pw FROM users WHERE username = '%s'
auth_opt_superquery SELECT IFNULL(COUNT(*), 0) FROM users WHERE username = '%s' AND super = 1
auth_opt_aclquery SELECT topic FROM acls WHERE username = '%s'
# Usernames with this fnmatch(3) (a.k.a glob(3)) pattern are exempt from the
# module's ACL checking
AUTH_OPT_SUPERUSERS s*
mysql 建表
參考 mosquitto-auth-plug/examples/mysql.sql
測(cè)試,直接跑 mysql.sql 建測(cè)試表
mysql -uroot -p -Dmqtttest<./../mosquitto-auth-plug/examples/mysql.sql
mysql> show tables;
+--------------------+
| Tables_in_mqtttest |
+--------------------+
| acls |
| users |
+--------------------+
mysql> desc users;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(25) | NO | UNI | NULL | |
| pw | varchar(128) | NO | | NULL | |
| super | int(1) | NO | | 0 | |
+----------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> desc acls;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(25) | NO | MUL | NULL | |
| topic | varchar(256) | NO | | NULL | |
| rw | int(1) | NO | | 1 | |
+----------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
客戶端依賴動(dòng)態(tài)庫(kù)
把 ./lib/libmosquitto.so.1 加入 /usr/lib 下
sudo cp lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1
運(yùn)行測(cè)試
- 服務(wù)端
./src/mosquitto -c mosquitto.conf
1500565002: |-- *** auth-plug: startup
1500565002: |-- ** Configured order: mysql
1500565002: |-- }}}} MYSQL
- 客戶端
it MUST return a single column only with the PBKDF2 password hash. A single '%s' in the query string is replaced by the username attempting to access the broker.
未往mysql正確插入數(shù)據(jù)情況(即未授權(quán)),連接將被backend拒絕
Connection Refused: not authorised.
Error: The connection was refused.
密碼使用 PBKDF2 存儲(chǔ)
A user's password is stored as a PBKDF2 hash in the back-end. An example "password" is a string with five pieces in it, delimited by $
, inspired by this.
Note that the salt
by default will be taken as-is (thus it will not be base64 decoded before the validation). In case your own implementation uses the raw bytes when hashing the password and base64 is only used for display purpose, compile this project with the -DRAW_SALT
flag (you could add this in the config.mk
file to CFG_CFLAGS
).
-
pw 格式:
image.png
- 使用auth plugin 提供的 np 工具生成密碼
np 工具使用加密算法,明文把組合隨機(jī)生成的salt,用 sha256作為hash函數(shù), 迭代次數(shù)901 次的 PBKDF2 生成了 hashed password, 返回拼接格式的字符串
mysql數(shù)據(jù)庫(kù)pw存儲(chǔ)拼接后的密碼, auth-plugin 從根據(jù) username從表里查詢得到拼接后的密碼(包括了 salt,interations, hashfunction),并提取出salt,用用戶 password 計(jì)算 hashed password 進(jìn)行比對(duì)鑒權(quán)。
$ ./np
Enter password:12345
Re-enter same password:12345
PBKDF2$sha256$901$IV/rAqUxT519iO+K$4pe0utPHFZnKpJTASyP0Ann5Nwx5yqZY
往 mysql mqtttest 表中添加 user, pw="PBKDF2$sha256$901$IV/rAqUxT519iO+K$4pe0utPHFZnKpJTASyP0Ann5Nwx5yqZY"
update users set pw="PBKDF2$sha256$901$ubLO1LjWJ0+Gpedp$lpPza0X4dDntdrc5qTqyuRVtIvpLx1N2" where id=7;添加 acl 記錄
insert into acls values(13,'cjc','cjc/rw',2);
| 13 | cjc | cjc/rw | 2 |
測(cè)試 訂閱
./mosquitto_sub -t "cjc/rw" -u "cjc" -P "12345"測(cè)試發(fā)布
./mosquitto_pub -t "cjc/rw" -m "hello" -u "cjc" -P "12345"服務(wù)端輸出
1500569102: Sending CONNACK to mosqsub|1240-ra1z (0, 0)
1500569102: Received SUBSCRIBE from mosqsub|1240-ra1z
1500569102: cjc/rw (QoS 0)
1500569102: Sending SUBACK to mosqsub|1240-ra1z
1500569112: |-- mosquitto_auth_unpwd_check(cjc)
1500569112: |-- ** checking backend mysql
1500569112: |-- getuser(cjc) AUTHENTICATED=1 by mysql
1500569112: Sending CONNACK to mosqpub|1241-ra1z (0, 0)
1500569112: |-- mosquitto_auth_acl_check(..., mosqpub|1241-ra1z, cjc, cjc/rw, MOSQ_ACL_WRITE)
1500569112: |-- mysql: topic_matches(cjc/rw, cjc/rw) == 1
1500569112: |-- aclcheck(cjc, cjc/rw, 2) trying to acl with mysql
1500569112: |-- aclcheck(cjc, cjc/rw, 2) AUTHORIZED=1 by mysql
1500569112: |-- Cached [1C2BBC255AB58D79DE677B3078E31D74C900A74D] for (mosqpub|1241-ra1z,cjc,2)
1500569112: Received PUBLISH from mosqpub|1241-ra1z (d0, q0, r0, m0, 'cjc/rw', ... (5 bytes))
1500569112: |-- mosquitto_auth_acl_check(..., mosqsub|1240-ra1z, cjc, cjc/rw, MOSQ_ACL_READ)
1500569112: |-- mysql: topic_matches(cjc/rw, cjc/rw) == 1
1500569112: |-- aclcheck(cjc, cjc/rw, 1) trying to acl with mysql
1500569112: |-- aclcheck(cjc, cjc/rw, 1) AUTHORIZED=1 by mysql
1500569112: |-- Cached [AD78C641352E6B2001205F385A3D612C609D6739] for (mosqsub|1240-ra1z,cjc,1)
1500569112: Sending PUBLISH to mosqsub|1240-ra1z (d0, q0, r0, m0, 'cjc/rw', ... (5 bytes))
np 密碼生成算法與實(shí)現(xiàn)
https://github.com/manolodd/pbkdf2-mosquitto
https://github.com/jpmens/mosquitto-auth-plug/tree/master/contrib/python3
https://github.com/jpmens/mosquitto-auth-plug/issues/44
- Create a salt (byte array with random chars)
- Convert the salt to Base64
- cast this base64 string as a byte array.
- Take the password
- Do the hashing with the password and the converted -> casted salt