原 EMQ百万级MQTT消息服务(ACL鉴权)

虽然EMQ已经搭建起来了,但是投入到业务使用中还面临着一些问题,当然MQTT设计之初也考虑了这一点,比如不是任何一个客户端都能链接到服务器和限制客户端能够对topic操作的权限

附上:

喵了个咪的博客:w-blog.cn EMQ官方地址:http://emqtt.com/ EMQ中文文档:http://emqtt.com/docs/v2/guide.html

1.ACL鉴权

先说实际场景,我们需要监听每一台设备的链接和断开事件等EMQ的系统行为,这样的事件当然不是任何一个连接到服务器的终端,这样的限制就是ACL鉴权,官方也提供了默认的鉴权,在 /usr/local/emqttd/etc/acl.conf 下,默认值允许127.0.0.1的IP地址链接监听系统主题

%% 允许'dashboard'用户订阅 '$SYS/#'
{allow, {user, "dashboard"}, subscribe, ["$SYS/#"]}.
%% 允许本机用户发布订阅全部主题
{allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.
%% 拒绝用户订阅'$SYS#'与'#'主题
{deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.

规则如下:

允许|拒绝  用户|IP地址|ClientID  发布|订阅  主题列表

## 访问控制规则采用 Erlang 元组格式,访问控制模块逐条匹配规则:
         ---------              ---------              ---------
Client -> | Rule1 | --nomatch--> | Rule2 | --nomatch--> | Rule3 | --> Default
          ---------              ---------              ---------
              |                      |                      |
            match                  match                  match
             \|/                    \|/                    \|/
        allow | deny           allow | deny           allow | deny

这个时候如果在外网链接EMQ定于如下主题,当客户端链接的时候是无法获取消息的

$SYS/brokers/+/clients/+/connected
$SYS/brokers/+/clients/+/disconnected

但是只需要修改acl配置文件如下然后重启节点:(所有节点都需要修改)

> vim /usr/local/emqttd/etc/acl.conf
## 修改
# {allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.
{allow, {ipaddr, 你的外网IP}, pubsub, ["$SYS/#", "#"]}.

重新监听当客户端链接的时候就可以获得如下信息

{"clientid":"V10115125355235","username":"cline","ipaddress":"116.192.34.23","clean_sess":true,"protocol":4,"connack":0,"ts":1521689797}
{"clientid":"V10115125355235","username":"cline","reason":"normal","ts":1521689801}

2.MYSQL实时配置ACL

一般来说我们不会使用外网IP来进行限制,有限会选择用户来进行限制行为,官方提供如下方式来进行用户和ACL验证的存储: (对应的配置方式可以参考官网文档)

  • 配置文件和命令
  • LDAP
  • HTTP
  • MySQL
  • Postgre
  • Redis
  • MongoDB

笔者这里采用大家经常用到的MYSQL作为鉴权的数据来源,首先先关闭匿名认证(默认是开启的谁都能够登录)

vim /usr/local/emqttd/etc/emq.conf 

## Allow Anonymous authentication
mqtt.allow_anonymous = false

重启服务器之后不管是谁都会被链接拒绝,我们需要准备好用于检查用户和权限的mysql表:

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


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=utf8;


-- 建立ACL默认访问控制
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 #'),
    (5,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'),
    (6,1,'127.0.0.1',NULL,NULL,2,'#'),
    (7,1,NULL,'dashboard',NULL,1,'$SYS/#');

修改mysql配置文件

> vim /usr/local/emqttd/etc/plugins/emq_auth_mysql.conf

auth.mysql.server = xxxxxxxxx:3306
auth.mysql.username = root
auth.mysql.password = xxxxxxxx
auth.mysql.database = emq

建立用户

# 用户名 server 密码 server 密码默认是sha256
insert `mqtt_user`(`username`,`password`) values('server','b3eacd33433b31b5252351032c9b3e7a2e7aa7738d5decdf0dd6c62680853c06');
# 用户名 cline 密码 cline
insert `mqtt_user`(`username`,`password`) values('cline','84829dbd815311888f0e3d85822e9b07d14be89a480a3c09ee67353f0e806e3b');

可以配置超级管理员(超级管理员会无视ACL规则对所有的topic都有订阅和推送的权限)

update `mqtt_user` set `is_superuser`=1 where `id`=1;

注意:可以注释掉acl.conf的默认规则(也可以结合使用) 注意:emq任何配置文件的变动都需要重启服务(可以在UI上直接修改配置不需要重启) 注意:如果是在集群下集群中每一个节点都需要执行命令

> emqttd stop
ok
> emqttd start
emqttd 2.3.5 is started successfully!
## 打开mysql鉴权
> emqttd_ctl plugins load emq_auth_mysql
Start apps: [emq_auth_mysql]
Plugin emq_auth_mysql loaded successfully.

在插件中就可以看到对应的mysql鉴权插件已经打开了

3 总结

这个时候在链接的时候配置用户名和密码就可以顺利链接上了,并且ACL的配置可以动态的变更谁能做什么事情,在不同的业务需求场景下这样的功能可以让程序做到更加安全又利于编程

注:笔者能力有限有说的不对的地方希望大家能够指出,也希望多多交流!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏令仔很忙

SQL To LinQ 你知道么?

 学习linQ的时候,你应该用到过LinQ to SQL 的工具---LinQPad,刚开始用,不太熟悉,尤其是涉及到多表查询,不会写LinQ语句怎么办?

862
来自专栏技术博文

mysql导出select结果到文件

mysql -hxx -uxx -pxx -e "query statement" db > file  例如:  mysql -h127.0.0.1 -uro...

3734

在CentOS 6上使用Postfix,Dovecot和MySQL发送电子邮件

Postfix 邮件传输代理(MTA)是一种高性能的开源电子邮件服务器系统。本指南将帮助你在CentOS 6 Linode上运行 Postfix,使用 Dove...

3195
来自专栏Samego开发资源

oracle常用基础命令创建表多字段组合主键约束查看表的主键名称 注意大写禁用开启主键约束删除约束等效上面

3175
来自专栏文渊之博

解决session阻塞的问题

简介     对于数据库运维人员来说创建session或者查询时产生问题是常规情况,下面介绍一种很有效且不借助第三方工具的方式来解决类似问题。 最近开始接触运维...

2025
来自专栏LeeCen

Ubuntu 环境下远程连接 MySQL 数据库

然后打开 vi /etc/mysql/mysql.conf.d/mysqld.cnf

1901
来自专栏nummy

python中MySQLdb模块用法实例

MySQLdb提供了connect方法用来和数据库建立连接,接收数个参数,返回连接对象:

781
来自专栏程序员的SOD蜜

获取SqlServer存储过程定义的3种方法

第一种: declare @p_text varchar(max) SELECT @p_text= text FROM syscomments WHERE...

2527
来自专栏武培轩的专栏

MySQL存储引擎

定义 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定...

3474
来自专栏禅林阆苑

Sphinx&coreseek实现中文分词索引

众所周知,mysql等数据库的LIKE模糊搜索不支持索引,因此查询效率极低,需要结合第三方索引引擎程序(索引程序)来提高查询性能。

2533

扫码关注云+社区

领取腾讯云代金券