在Docker中运行EMQX,并且使用MySQL鉴权

发布于 2023-01-14  19 次阅读


使用docker安装EMQX

docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx
docker cp emqx:/opt/emqx/bin /data/docker/emqx
docker cp emqx:/opt/emqx/etc /data/docker/emqx
docker cp emqx:/opt/emqx/lib /data/docker/emqx
docker cp emqx:/opt/emqx/data /data/docker/emqx
docker cp emqx:/opt/emqx/log /data/docker/emqx
# 修改挂载目录权限
chown -R 1000:1000 /data/docker/emqx/
chmod -R 755 /data/docker/emqx/
# 停止并删除临时容器
docker container stop emqx
docker container rm emqx
docker run -d --name emqx --restart=always -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 -v /data/docker/emqx/bin:/opt/emqx/bin -v /data/docker/emqx/etc:/opt/emqx/etc -v /data/docker/emqx/lib:/opt/emqx/lib -v /data/docker/emqx/data:/opt/emqx/data -v /data/docker/emqx/log:/opt/emqx/log emqx/emqx

#真正数据在/data/docker/emqx ,宝塔的显示不准确应该手动寻找

使用MySQL鉴权

本文仅介绍认证功能,ACL 功能见后续文章。

认证原理

设备连接时 EMQX 将执行按照配置的查询语句,比较查询结果中的 password 字段的值是否与当前请求客户端的密码进行加盐 (salt) 处理、加密后的值是否相等,验证流程如下:

查询结果集中必须有 password、salt 字段,可以使用 AS 语法设置如 SELECT *, pwd as password FROM mqtt_user
在数据库中可以为每个客户端都指定一个 salt,EMQX 根据客户端传入的密码和通过 SQL 返回的 salt 信息生成密文结果集为空或比对结果不相等,认证失败
你可以使用任何自己喜欢的 客户端,创建好相应的数据库。这里用的是 MySQL 自带的命令行客户端,打开 MySQL 的控制台,如下所示,创建一个名为 emqx 的认证数据库,并切换到 emqx 数据库。

create database emqx;
CREATE TABLE `mqtt_user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password_hash` varchar(255) DEFAULT NULL,
  `salt` varchar(40) 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;

准备认证数据

本文提供示例数据中密码为 test_password,加密 salt 为 ''。即客户端连接时使用的密码是 test_password 。

在 EMQX 的配置文件的 auth.mysql.password_hash 中,salt 只是一个标识符,表示 salt 与密码明文的拼接关系。

如果采用auth.mysql.password_hash = md5,salt ,那么 EMQX 使用 MD5 算法对 test_passwordsecret 字符串加密
如果采用auth.mysql.password_hash = salt,md5 ,那么 EMQX 使用 MD5 算法对 secrettest_password 字符串加密
本文采用第一种配置方式,将得到的 MD5 密文插入表 mqtt_user。读者可以通过在线的 MD5 工具或者自己写程序对密码进行编码。

MD5("test_password") -> a904b2d1d2b2f73de384955022964595
INSERT INTO mqtt_user(username,password_hash,salt) VALUES('test_username', '16ec1ebb01fe02ded9b7d5447d3dfc65', '');

启用认证功能,修改插件配置并启用插件

修改 etc/plugins/emqx_auth_mysql.conf,修改后的有效配置如下所示,其余 ACL 相关的配置项可以注释:

## 修改为实际 mysql 所在的服务器地址

auth.mysql.server = XXX:3306
## 修改为上面创建成功的 emqx 数据库
auth.mysql.database = emqx
auth.mysql.username = XXX
auth.mysql.password = XXX
## 连接认证查询语句
auth.mysql.auth_query = SELECT password_hash AS password, salt FROM mqtt_user WHERE username = '%u'
## 加密算法 plain | md5 | sha | sha256 | bcrypt
## 加盐加密算法
auth.mysql.password_hash = md5,salt
## 不加盐加密算法,直接写算法名称即可
# auth.mysql.password_hash = md5

关闭匿名认证

EMQX 默认开启了匿名认证,即便启用了认证功能,数据库没有查询到数据时设备也能正常连接,只有当查询到数据且密码错误时才会拒绝连接。

打开 etc/emqx.conf 配置文件,禁用匿名认证:

## Value: true | false
allow_anonymous = false

重启 emqx 完成配置应用。

对于MySQL 8需要修改配置MySQL配置文件

[mysqld]

default_authentication_plugin=mysql_native_password

本当の声を響かせてよ