基于PostgreSQL的MQTT访问控制

 

基于PostgreSQL的MQTT访问控制

2018年5月25日

MQTT的轻量级发布-订阅模型是物联网系统的自然选择,但需要一些保护措施。与诸如HTTP之类的流行协议相比,文档更少,特别是对于特定的代理([Mosquitto(http://mosquitto.org)与Apache,有人吗?)。由于Mosquitto具有广泛的硬件支持,因此已经选择了Mosquitto,除了内置的访问控制列表之外,我还需要可扩展的每设备身份验证,该列表在测试中运行良好,但是需要重新启动服务以更新访问权限。已经配置了PostgreSQL安装,它是与设备相关的数据存储的自然场所。

mosquitto-auth-plug进行救援。这个Mosquitto插件将身份验证扩展到包括各种数据库。从Mosquitto 1.3.5和MySQL已有三年历史的指南中可以看出,该设置略有涉及。这篇文章建立在PostgreSQL(插件完全支持)和Mosquitto 1.5的基础上。假定已经安装了数据库,git和编译库(make,gcc,g ++)。使用Debian风格的命令。

初始安装和构建

由于必须使用到源的路径来构建插件,因此我必须先卸载Mosquitto(您可能要先从/ etc / mosquitto备份任何复杂的配置,并完全清除安装以避免重新安装时出现问题)。建造新鲜的蚊子的初始步骤包括:

sudo apt-get install libc-ares-dev libssl-dev uuid uuid-dev
wget http://mosquitto.org/files/source/mosquitto-1.5.tar.gz
tar xvzf mosquitto-1.5.tar.gz
cd mosquitto-1.5
make mosquitto
sudo make install

插件的设置保持不变:

git clone https://github.com/jpmens/mosquitto-auth-plug.git
cd mosquitto-auth-plug
cp config.mk.in config.mk

编辑config.mk,以说明不同的数据库和文件夹,

BACKEND_MYQSL ?= no
# ...
BACKEND_POSTGRES ?= yes
# ...
# Specify the path to the Mosquitto sources here
MOSQUITTO_SRC = [path]/mosquitto-1.5
# And since I wanted to have websockets (allow browser clients),
# this was the moment to set:
WITH_WEBSOCKETS:=yes

([路径]取决于早期的tar)。

制作mosquitto-auth-plug包括:

make clean #recommended by the make script since configuration changed
sudo apt-get install libpq-dev #The server was already installed and working, and this was supposed to install without it, but otherwise I hit a missing header error
make
sudo mv auth-plug.so /etc/mosquitto/ #As in the guide

配置和数据库

现在该配置Mosquitto了。我之前的mosquitto.conf具有一些持久性和日志设置,因此我将其保留在原处,或者用示例覆盖了所有内容。我添加了指南文本的修改版本,幸运的是PostgreSQL的文本更短

auth_plugin /etc/mosquitto/auth-plug.so
auth_opt_backends postgres
auth_opt_dbname [dbname] %[use your own]
auth_opt_user [user]
auth_opt_pass [password]
auth_opt_userquery SELECT pw FROM account WHERE username = $1 limit 1
auth_opt_superquery SELECT COALESCE(COUNT(*),0) FROM account WHERE username = $1 AND superuser = 1
auth_opt_aclquery SELECT topic FROM acls WHERE (username = $1) AND (rw & $2) > 0

最后三个是默认的PostgreSQL调用(原则上,我建议使用您自己的模式)。根据文档

  • userquery:强制查询,返回给定用户的1x1结果和PBKDF2密码哈希

  • superquery:查询不受访问控制限制的超级用户,返回带有0/1的1x1条目,指示该用户是否是超级用户(有用,因为我需要一个全局用户才能从所有通道读取)

  • aclquery:查询返回具有任意行数的单列,每行包含一个MQTT主题字符串

现在是时候测试np密码生成实用程序并设置数据库了。

./np #Enter a password twice
Enter password:
Re-enter same password:
PBKDF2$sha256$901$gjOcwLF+xs92U5Mf$wHdnuPJTAdhTsy7bMOco+9vtO2W86K8h
sudo psql -U [dbuser]
\connect [database]
#'You are now connected to database "[database]" as user "[dbuser]"'
CREATE TABLE account (
id serial PRIMARY KEY,
username varchar(20) NOT NULL,
pw varchar(100) NOT NULL,
superuser smallint NOT NULL DEFAULT 0,
CONSTRAINT superuser CHECK (superuser = 0 OR superuser = 1)
);
-- CREATE TABLE
INSERT INTO account(username, pw)
VALUES
('testuser', 'PBKDF2$sha256$901$gjOcwLF+xs92U5Mf$wHdnuPJTAdhTsy7bMOco+9vtO2W86K8h');
-- INSERT 0 1
SELECT * FROM account;
-- Should show new user
​
CREATE TABLE acls (
id serial PRIMARY KEY,
username varchar(20) NOT NULL,
topic varchar(40) NOT NULL,
rw smallint NOT NULL DEFAULT 1,
CONSTRAINT rw CHECK (rw >= 1 AND rw <= 4)
);
-- CREATE TABLE
INSERT INTO acls(username, topic, rw)
VALUES
('testuser', 'testuser/#', 2);
-- INSERT 0 1
SELECT * FROM acls;
-- Should show new user

测验

cd /usr/local/sbin
./mosquitto -c /etc/mosquitto/mosquitto.conf

经过几次错误的启动(使用-c参数静默失败,但没有使用-c参数即可正常运行),日志使用相同的解决方案显示了Rex Xia描述错误

sudo ln -s /usr/local/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1

从这里开始,Mosquitto和插件运行完美。请注意,在mosquitto.conf中配置的用户的PostgreSQL身份验证中的任何缺陷,或该用户对新创建的表的访问权限,都在这里暴露出来,从而使身份验证/授权检查提前终止。

成功看起来像

1527399177: |-- mosquitto_auth_unpwd_check(testuser)
1527399177: |-- ** checking backend postgres
1527399177: |-- GETTING USERS: testuser
1527399177: |-- getuser(testuser) AUTHENTICATED=1 by Postgres

在使用例如MQTT.fx进行订阅时(除testuser / password之外的所有凭据都无法连接),并且:

USERNAME: testuser, TOPIC: testuser/test, acc: 2
1527400680: |--   postgres: topic_matches(testuser/#, testuser/#) == 1
1527400680: |-- aclcheck(testuser, testuser/test, 2) trying to acl with postgres
1527400680: |-- aclcheck(testuser, testuser/test, 2) AUTHORIZED=1 by postgres

发布到测试用户/测试时。奇怪的是,尽管rw值3会同时授予读写权限,但是更改此值对于testuser而言还不够。由于每当我尝试订阅同一主题时都会显示以下内容,

1527401125: |-- USERNAME: testuser, TOPIC: testuser/#, acc: 4

我将权限设置为4,并且能够发布消息并使用相同的连接接收消息。尝试订阅任何不允许的主题仍然会导致连接终止。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值