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

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

附上:mysql

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

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, "#"}]}.

规则以下:vim

容许|拒绝  用户|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配置文件以下而后重启节点:(全部节点都须要修改)bash

> 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验证的存储: (对应的配置方式能够参考官网文档)app

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

笔者这里采用你们常常用到的MYSQL做为鉴权的数据来源,首先先关闭匿名认证(默认是开启的谁都可以登陆)ide

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的配置能够动态的变动谁能作什么事情,在不一样的业务需求场景下这样的功能可让程序作到更加安全又利于编程

注:笔者能力有限有说的不对的地方但愿你们可以指出,也但愿多多交流!

相关文章
相关标签/搜索