之前写过mosuqitto编译和使用相关的博文,本文将介绍一个可以在生产环境使用的mosquitto配置过程,引入了更多的权限和安全管理。这次实验博主是在阿里云的ECS上完成的,没有云服务器的小伙伴可以在本地安装一个Ubuntu 22.04的虚拟机或者看看腾讯云或者阿里云有没有优惠的云服务器。

获取mosquitto的源代码和mosquitto-go-auth的源代码

wget https://mosquitto.org/files/source/mosquitto-2.0.18.tar.gz
git clone https://github.com/iegomez/mosquitto-go-auth.git

编译安装mosquitto

编译安装mosquitto程序

apt install libssl-dev libcjson-dev

tar -zxf mosquitto-2.0.18.tar.gz
cd mosquitto-2.0.18/
make
make install

groupadd mosquitto
useradd -s /sbin/nologin mosquitto -g mosquitto -d /var/lib/mosquitto
mkdir -p /var/log/mosquitto/ /var/lib/mosquitto/
chown -R mosquitto:mosquitto /var/log/mosquitto/
chown -R mosquitto:mosquitto /var/lib/mosquitto/

编写配置文件,修改监听地址等等

cd /etc/mosquitto/
cp mosquitto.conf.example mosquitto.conf
vim mosquitto.conf

测试用的配置

allow_anonymous true
listener 1883 0.0.0.0

然后运行进行测试,查看客户端能否连接

mosquitto -c /etc/mosquitto/mosquitto.conf

连上之后我们来写一个服务配置文件,使得systemd能够管理服务的启动

vim /etc/systemd/system/mosquitto.service

填入以下内容

[Unit]
Description=Mosquitto MQTT v3.1/v5 server
Wants=network.target
Documentation=http://mosquitto.org/documentation/

[Service]
Type=simple
User=mosquitto
Group=mosquitto
ExecStart=/usr/local/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Restart=on-failure
SyslogIdentifier=Mosquitto

[Install]
WantedBy=multi-user.target
systemctl start mosquitto.service 
systemctl enable mosquitto.service

编译配置go-auth插件

接下来就可以编译mosquitto-go-auth插件了,首先确保自己安装了go-1.18以上的版本

cd mosquitto-go-auth
make

构建完成后可以看到目录下有一个go-auth.sopw可执行文件分别是mosquitto的插件和密码生成工具,将这两个工具拷贝到/etc/mosquitto/conf.d

cp go-auth.so /etc/mosquitto/conf.d/
cp pw /etc/mosquitto/conf.d

编写一个go-auth插件的配置文件

vim /etc/mosquitto/conf.d/go-auth.conf

填入以下内容配置通过文件来授权

auth_plugin /etc/mosquitto/conf.d/go-auth.so

auth_opt_backends files
auth_opt_disable_superuser true

auth_opt_files_password_path /etc/mosquitto/conf.d/password_file
auth_opt_files_acl_path /etc/mosquitto/conf.d/acl_file


auth_opt_hasher_salt_size 16           # salt bytes length
auth_opt_hasher_iterations 100000      # number of iterations
auth_opt_hasher_keylen 64              # key length
auth_opt_hasher_algorithm sha512       # hashing algorithm, either sha512 (default) or sha256
auth_opt_hasher_salt_encoding          # salt encoding, either base64 (default) or utf-8

auth_opt_hasher pbkdf2

auth_opt_log_dest file
auth_opt_log_file /var/log/mosquitto/mosquitto.log
auth_opt_log_level debug

并且生成一个配置文件/etc/mosquitto/conf.d/acl_file

user test1
topic write test/topic/1
topic read test/topic/2

user test2
topic read test/topic/+

通过刚才拷贝的工具生成加密的密码

./pw -p <your password>

然后将生成的字符串写入到/etc/mosquitto/conf.d/password_file中,其中用户名test1的密码是testtest2的密码是mosquitto

test1:PBKDF2$sha512$100000$fAdA5klpGch9lRCmwM2Ozw==$fxkXYWi0QlFtk+oYdMHYZxBQSNtJ05ogHxfKmza5CpUDGL6+MysG3ier8hFl6BsAsE3t1Tq6Y3JkEzn9mhlLgQ==
test2:PBKDF2$sha512$100000$JecNIqpn7hX8dueP3gQsGQ==$1nYeN8L9V96/C9yAUz7FokqzQq1DpyjBRcxvR1fauCsie+q9cb4dxcFvPbi4V6JgiNHGRP1Zn2vQp3KiTLlRgA==

修改mosquitto.conf的配置以支持插件的配置

include_dir /etc/mosquitto/conf.d
allow_anonymous false

重启服务以后,我们发现必须需要用户名密码正确才可以连接了,并且对主题的独写权限也有了区分。

配置Postgres和Redis缓存

安装Redis作为缓存

apt update
apt install redis

配置redis的密码,vim /etc/redis/redis.conf,增加以下行

requirepass mosquitto

启动redis

systemctl start redis-server
systemctl enable redis-server

安装Postgresql

apt install postgresql

配置数据库

sudo -u postgres psql

执行以下sql语句创建数据库

create user mosquitto with login password 'mosquitto';
create database mosquitto with owner mosquitto;
\c mosquitto;
GRANT ALL PRIVILEGES ON DATABASE mosquitto to mosquitto;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO mosquitto;

create table tb_user(
id bigserial primary key,
username character varying (100) not null,
password_hash character varying (200) not null,
is_admin boolean not null);

create table tb_acl(
id bigserial primary key,
user_id bigint not null references tb_user on delete cascade,
topic character varying (200) not null,
rw int not null);

insert into tb_user (username, password_hash, is_admin) VALUES ('test1', 'PBKDF2$sha512$100000$fAdA5klpGch9lRCmwM2Ozw==$fxkXYWi0QlFtk+oYdMHYZxBQSNtJ05ogHxfKmza5CpUDGL6+MysG3ier8hFl6BsAsE3t1Tq6Y3JkEzn9mhlLgQ==', false);

insert into tb_user (username, password_hash, is_admin) VALUES ('test2', 'PBKDF2$sha512$100000$JecNIqpn7hX8dueP3gQsGQ==$1nYeN8L9V96/C9yAUz7FokqzQq1DpyjBRcxvR1fauCsie+q9cb4dxcFvPbi4V6JgiNHGRP1Zn2vQp3KiTLlRgA==', false);

insert into tb_acl (user_id, topic, rw) VALUES (1, 'test/topic/1', 2);
insert into tb_acl (user_id, topic, rw) VALUES (1, 'test/topic/2', 1);
insert into tb_acl (user_id, topic, rw) VALUES (2, 'test/topic/#', 1);

修改go-auth.conf

auth_plugin /etc/mosquitto/conf.d/go-auth.so

auth_opt_backends postgres
auth_opt_disable_superuser true

auth_opt_files_password_path /etc/mosquitto/conf.d/password_file
auth_opt_files_acl_path /etc/mosquitto/conf.d/acl_file


auth_opt_hasher_salt_size 16           # salt bytes length
auth_opt_hasher_iterations 100000      # number of iterations
auth_opt_hasher_keylen 64              # key length
auth_opt_hasher_algorithm sha512       # hashing algorithm, either sha512 (default) or sha256
auth_opt_hasher_salt_encoding          # salt encoding, either base64 (default) or utf-8

auth_opt_hasher pbkdf2

auth_opt_log_dest file
auth_opt_log_file /var/log/mosquitto/mosquitto.log
auth_opt_log_level info


auth_opt_cache true
auth_opt_cache_type redis
auth_opt_cache_reset true
auth_opt_cache_refresh true

auth_opt_auth_cache_seconds 30
auth_opt_acl_cache_seconds 30
auth_opt_auth_jitter_seconds 5
auth_opt_auth_jitter_seconds 5

auth_opt_cache_host 127.0.0.1
auth_opt_cache_port 6379
auth_opt_cache_password mosquitto
auth_opt_cache_db 3

auth_opt_pg_host 127.0.0.1
auth_opt_pg_port 5432
auth_opt_pg_dbname mosquitto
auth_opt_pg_user mosquitto
auth_opt_pg_password mosquitto
auth_opt_pg_sslmode disable

auth_opt_pg_connect_tries 5
auth_opt_pg_userquery select password_hash from "tb_user" where username = $1 limit 1
auth_opt_pg_superquery select count(*) from "tb_user" where username = $1 and is_admin = true
auth_opt_pg_aclquery select acl.topic FROM tb_acl acl inner join tb_user u ON u.id = acl.user_id WHERE u.username = $1 AND acl.rw >= $

重启mosquitto即可生效

参考链接

mosquitto-go-auth插件

Redis相关的配置

在Ubuntu22.04上安装Redis

postgresql配置

改变表格权限

benchmark