SpringBoot

消息通讯——MQTT安全认证和测试

Nick · 6月8日 · 2021年 · 本文5824字 · 阅读15分钟626

EMQX安全认证

EMQ X 消息服务器的连接认证和访问控制由一系列的认证插件(Plugins)提供,他们的命名都符合 emqxauth 的规则,在 EMQ X 中,这两个功能分别是指:
连接认证: EMQ X 校验每个连接上的客户端是否具有接入系统的权限,若没有则会断开该连接;
访问控制: EMQ X 校验客户端每个 发布(Publish)/订阅(Subscribe) 的权限,以 允许/拒绝 相应操作;

EMQ X 消息服务器认证的插件支持按用户名密码、ClientID 或匿名认证三种方式,系统默认开启匿名认证,我们可以配置插件开启认证链:

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

特别需要注意:

  • 当开启Username认证之后,系统会忽略Client ID认证和匿名认证;
  • 当开启Client ID认证之后,系统会忽略匿名认证;

1. 默认方式——匿名认证

搭建完成之后,设备端对接MQTT服务器没有任何的身份认证,直接连接即可。

使用mqtt.fx作为mqtt客户端进行测试:

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

设置完成之后点击连接即可:

测试订阅主题:

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

测试发布消息

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

发布之后看一下是否收到(客户端已订阅此主题):

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

这种无认证方式的优缺点非常明显:

  • 优点:客户端对接简单,利于编程;
  • 缺点:毫无安全性可言,任何设备都可以连接并且发布消息,容易遭受攻击;

注意:如果添加认证权限功能,需要禁止匿名方式连接:
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
allow_anonymous = false:禁止匿名访问

2. Username 认证插件

emqx_auth_username 提供了Username 认证功能,目前只支持连接认证,通过 username 和 password 认证客户端,此插件在存储密码时会按照配置的 hash 算法将明文加密后存入。

停止EMQX服务:
在配置插件之前首先停止服务:

cd emqx
./bin/emqx stop

配置Username插件

登录部署了EMQ-X的服务器,编辑EMQX目录下的这个文件:

cd emqx/
vim ./etc/plugins/emqx_auth_username.conf

修改官方示例,配置一个username和密码,并将加密方式改为plain(方便起见,直接文本传输):
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

启动EMQ-X服务

./bin/emqx start

开启Username插件
开启插件的方式有两种:

  • 直接在命令行启动:
    ./bin/emqx_ctl plugins load emqx_auth_username
    消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

  • 在DashBoard中启动:
    在DashBoard的左侧点击“插件”一栏,找到 emqx_auth_username 插件,点击开启(这里我已经命令行开启,所以显示停止):

    消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

客户端登录测试

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

点击连接即可成功登陆:

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

如果对username或者密码稍作修改,则不可登录:

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

测试完毕,这种用户名认证方式非常推荐:

优点:给客户端分配 username 和 password 即可,如果不对应,则不会连接,测试方便;
缺点:每个设备都需要手动或者 API 请求分配认证信息,建立阶段较复杂

Username 认证插件增加用户

打开后台管理系统面板:http://localhost:18083/#/plugins
点击emqx_auth_username 的管理功能
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
可以进行手动添加用户
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
手动添加用户后,就可以使用新增的用户名和密码进行连接登录

3. EMQX使用MYSQL认证插件

EMQ开源版的MYSQL认证是免费的
使用步骤:

1) 配置EMQ MYSQL

首先我们要配置emq里的mysql.conf才可以使用MYSQL认证插件
如果是压缩包方法安装的话,就只需要找到我们解压出来的emqx/etc/plugins/emqx_auth_mysql.conf。
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
官方给出的MYSQL认证数据库表参考如下

DROP TABLE IF EXISTS `mqtt_acl`;

CREATE TABLE `mqtt_acl` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow',
  `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
  `username` varchar(100) DEFAULT NULL COMMENT 'Username',
  `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
  `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
  `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `mqtt_acl` WRITE;

INSERT INTO `mqtt_acl` (`id`, `allow`, `ipaddr`, `username`, `clientid`, `access`, `topic`)
VALUES
    (1,1,NULL,'$all',NULL,2,'#'),
    (2,0,NULL,'$all',NULL,1,'$SYS/#'),
    (3,0,NULL,'$all',NULL,1,'eq #'),
    (4,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'),
    (5,1,'127.0.0.1',NULL,NULL,2,'#'),
    (6,1,NULL,'dashboard',NULL,1,'$SYS/#');

UNLOCK TABLES;

DROP TABLE IF EXISTS `mqtt_user`;

CREATE TABLE `mqtt_user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  `salt` varchar(35) DEFAULT NULL,
  `is_superuser` tinyint(1) DEFAULT 0,
  `created` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `mqtt_username` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

配置完了之后就可以启动MYSQL认证了,登录18083端口的仪表盘。
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
启动成功就说明我们的MYSQL配置成功。
没有成功的原因可能有以下:
1.auth.mysql.username和auth.mysql.password 这两个配置字段前面的#号没去掉。
2.URL地址错误
3.3306数据库端口没有开
4.防火墙 或者云服务器安全组

2) 测试连接认证

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
然后我们使用官方的MQTTX工具测试连接
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
注意:如果账号密码都正确,还是连接失败,则可能是配置问题,查看emqx_auth_mysql.conf
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
可以看到这里的密码加密方式是sha256,说明我们连接时候的密码是加密后才与数据库内的password字段的值做匹配。这里我们可以改成plain明文不加密,又或者我们可以把数据库的字段改成sha256加密后的字段。
这里我选择改成plain不加密
在这里插入图片描述
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
重启一下mysql认证插件,重新连接即可连接成功。

4. 测试ACL权限控制

来到ACL权限控制,使用到数据库mqtt_acl数据表。这里引用官方文档关于表内字段的说明

ACL 规则表

CREATE TABLE `mqtt_acl` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `allow` int(1) DEFAULT 1 COMMENT '0: deny, 1: allow',
  `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
  `username` varchar(100) DEFAULT NULL COMMENT 'Username',
  `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
  `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
  `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

规则表字段说明:
allow:禁止(0),允许(1)
ipaddr:设置 IP 地址
username:连接客户端的用户名,此处的值如果设置为 $all 表示该规则适用于所有的用户
clientid:连接客户端的 Client ID
access:允许的操作:订阅(1),发布(2),订阅发布都可以(3)
topic:控制的主题,可以使用通配符,并且可以在主题中加入占位符来匹配客户端信息,例如 t/%c 则在匹配时主题将会替换为当前客户端的 Client ID
%u:用户名
%c:Client ID

默认配置下示例数据:

-- 所有用户不可以订阅系统主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (0, NULL, '$all', NULL, 1, '$SYS/#');

-- 允许 10.59.1.100 上的客户端订阅系统主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (1, '10.59.1.100', NULL, NULL, 1, '$SYS/#');

-- 禁止客户端订阅 /smarthome/+/temperature 主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (0, NULL, '$all', NULL, 1, '/smarthome/+/temperature');

-- 允许客户端订阅包含自身 Client ID 的 /smarthome/${clientid}/temperature 主题
INSERT INTO mqtt_acl (allow, ipaddr, username, clientid, access, topic) VALUES (1, NULL, '$all', NULL, 1, '/smarthome/%c/temperature');

如果想限制一个叫ceshi的用户只能订阅 aaa 的主题,应该怎么做呢

1.我们在数据表添加一个数据
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
这条数据可以解读为:我们要允许admin用户订阅 aaa 的主题

  1. 连接用户订阅测试
    连接上之后我们发现 ceshi用户 可以关注随便一个主题,表中添加的数据并没有生效。
    这里就是存在误解的地方
    ACL认证在遍历时是按照顺序来做遍历的,我这里设置为允许他订阅,实际上相当于没有设置。
    我们应该是先把admin用户所有的订阅关上,再打开admin用户的123/#主题订阅权限。
    那么我们在数据表订阅 aaa 之前添加一个关闭的语句
    消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
  2. 测试效果
    这样就完成了admin用户只能订阅 aaa 的主题的要求。

    • 测试订阅失败(任意一个主题进行订阅)
      消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
    • 测试订阅成功
      消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
  3. 最后可以使用不同的acces允许的操作进行测试,但需要注意的还是:ACL认证在遍历时是按照顺序来做遍历的,注意ACL认证执行的顺序。
    如果需要允许订阅两个topic,只需要新添加一条数据topic即可
    消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
    这样就可以允许该客户端同时订阅两个topic。

5. clientId的唯一性

在连接EMQX客户端时,连接属性中clientId是唯一的,如果使用同一个clientId登录客户端两次,后面登录的客户端会将前一个挤下线,前一个客户端将会断开连接。

测试同一个用户登录同一个clientId

  • 使用js客户端登录
    消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
  • 使用Mtqq.fx登录
    消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客

    测试不同用户登录同一个clientId

    出现和上述同样的情况,前一次的登录的客户端被挤下线。

6. emqx使用HTTP接口

EMQ X 提供了 HTTP API 以实现与外部系统的集成,例如查询客户端信息、发布消息和创建规则等。
EMQ X 的 HTTP API 服务默认监听 8081 端口,可通过 etc/plugins/emqx_management.conf 配置文件修改监听端口,或启用 HTTPS 监听。EMQ X 4.0.0 (opens new window)以后的所有 API 调用均以 api/v4 开头。
除了帮助页面,所有URI返回application/json格式的的资源,每个请求都需要HTTP基本认证。默认用户是admin / public。

消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
接口安全
EMQ X 的 HTTP API 使用 Basic 认证 (opens new window)方式,id 和 password 须分别填写 AppID 和 AppSecret。 默认的 AppID 和 AppSecret 是:admin/public。你可以在 Dashboard 的左侧菜单栏里,选择 "管理" -> "应用" 来修改和添加 AppID/AppSecret。

具体使用详情参考API官方文档

7. emqx使用的mysql数据存储

使用emqx的mysql数据持久化的插件,必须是使用emqx企业版。
消息通讯——MQTT安全认证和测试-左眼会陪右眼哭の博客
使用详情参考:https://blog.csdn.net/feixiangsmile/article/details/111152477

0 条回应
在线人数:1人 来访统计
隐藏