MQTT安全性设计详解

Wesley13
• 阅读 926

本文属于原创,转载注明出处,欢迎关注微信小程序小白AI博客 微信公众号别打名名或者网站 https://xiaobaiai.net 或者我的CSDN http://blog.csdn.net/freeape

MQTT安全性设计详解

  • 1 前言

  • 2 安全实现方式

  • 2.1 使用用户名和密码限制连接

  • 2.2 使用 SSL(升级版本 TLS)对网络数据进行加密

  • 2.3 配置 Broker ACL

  • 2.4 使用授权管理插件,实现批量级用户权限和 topic 的读写权限管理

  • 3 总结

  • 4 扩展之 MQTT SYS 主题

  • 5 参考链接

1 前言

MQTT(MQ Telemetry Transport, MQ 遥测传输)。它是一种发布/订阅、极其简单和轻量级的消息传递协议,旨在用于受限设备和低带宽,高延迟或不可靠的网络。设计原则是使网络带宽和设备资源要求最小化,同时还要尝试确保可靠性和一定程度的交付保证。这些原则也使该协议成为新兴的“M2M”或“物联网”连接设备世界的理想选择,并且适用于带宽和电池电量极为宝贵的移动应用。

物联网的前景变得越来越大,尤其是 5G 的到来,各领域如车联网、车载娱乐(AR 等)、智能电网、移动和协作机器人、智能视频监控、智慧城市等等。

MQTT安全性设计详解

5G 物联网用例图

IOT ANALYTICS机构预测到 2025 年全世界运行的物联网设备能达到 342 亿(34.2billion)。各互联网大头公司,如亚马逊、微软、阿里巴巴、腾讯、IBM 等等都推出了物联网云平台。而每个云平台都对 MQTT 协议支持,支持直接将设备通过 MQTT 协议与他们的云平台对接起来。MQTT 是一个开放的协议,我们可以自己去搭建自己的云平台,实现定制化开发,那么在实现 MQTT 安全上有什么需要注意的地方呢?本文从实现了 MQTT 协议的 mosquitto broker 具体示例来讲述。

MQTT安全性设计详解

IOT ANALYTICS物联网激活设备趋势预测图

2 安全实现方式

  • MQTT 协议本身支持用户名和密码实现客户端的身份校验

  • 使用 SSL(升级版本 TLS)对网络数据进行加密(这与 MQTT 协议本身是无关的,会增加网络开销)

  • 通过 Broker 配置对 Topic 的读写权限

  • 使用授权管理插件,实现批量级用户权限和 topic 的读写权限管理

2.1 使用用户名和密码限制连接

通过使用用户名和密码限制连接的方式,客户端连接 broker 时需要设置与 broker 要求的用户名密码才能够连接成功。

mosquitto.conf:

# 指定用户名和密码才能连接brokerallow_anonymous falsepassword_file {your password path}/passwdfile

密码文件的生成:

mosquitto_passwd [ -c | -D ] passwordfile usernamemosquitto_passwd -b passwordfile username passwordmosquitto_passwd -U passwordfile-b    以批处理模式运行。这允许在命令行提供密码,这可以很方便,但应小心使用,因为密码将在命令行和命令历史记录中可见-c    创建一个新的密码文件,如果文件已经存在,则会覆盖。输入命令后,控制台会提示输入新建用户的密码,连续输入两次密码后,则密码文件创建完成-D    从密码文件中删除指定的用户-U    此选项可用于使用哈希密码将带有纯文本密码的密码文件升级/转换为一个密码文件

2.2 使用 SSL(升级版本 TLS)对网络数据进行加密

使用 TLS 对网络数据加密,需要在配置文件中指定认证文件、密钥文件。

mosquitto.conf:

cafile {your file path}/m2mqtt_ca.crtcertfile {your file path}/m2mqtt_srv.crtkeyfile {your file path}/m2mqtt_srv.key

如何签发证书,查看另一篇文章“使用 TLS 和 Mosquitto Broker 实现安全通信之密钥和证书生成”;

2.3 配置 Broker ACL

通过设置 Broker ACL,可以限制指定用户对指定 Topic 的数据读写权限。

mosquitto.conf:

# 配置acl_file参数为指定acl文件acl_file {your file path}/aclfile

aclfile 文件内容示例:

# 如下配置会影响没有用户名的客户端的访问控制# topic [read|write|readwrite] <topic>topic read $SYS/## 如下配置会影响用户名为 "roger" 的访问控制.user rogertopic foo/bar# 如下配置会影响所有客户端# pattern [read|write|readwrite] <topic>pattern write $SYS/broker/connection/%c/state

2.4 使用授权管理插件,实现批量级用户权限和 topic 的读写权限管理

使用授权管理插件 https://github.com/jpmens/mosquitto-auth-plug

该插件可以执行身份验证(检查用户名/密码)和授权(通过 ACL 授予订阅和/或发布特定主题的许可),通过与数据库绑定,将身份验证和 ACL 管理录入数据库,从而很方便的实现用户身份验证管理。该插件对数据库 mysql 及 mongodb 支持很友好。具体怎么使用可以参考 README。这里仅给出 mysql 配置示例。

MQTT安全性设计详解

mosquitto.conf:

# 指定插件所需动态库auth_plugin /usr/mosquitto/bin/auth-plug.so# 指定后端数据库auth_opt_backends mysql# 指定数据库主机地址auth_opt_host localhost# 指定数据库访问端口auth_opt_port 3306# 指定数据库名auth_opt_dbname your_database# 指定数据库访问用户名auth_opt_user your_username# 指定数据库访问密码auth_opt_pass your_passwd# 配置身份验证查询语句auth_opt_userquery select (case password_syncstatus when 'sync' then user_passwd else old_password end) as user_passwd from tbl_mqttuser where user_name='%s'# 配置ACL验证查询语句auth_opt_aclquery SELECT topic FROM tbl_mqttacls WHERE (user_name = '%s') AND (rw >= %d)# 匿名MQTT连接时插件配置的用户名auth_opt_anonusername anonymouS

mysql 中 tbl_mqttuser 及 tbl_mqttacls 两个表数据示例:

mysql> select * from  tbl_mqttacls;+--------+--------------+--------+----+| acl_id | user_name    | topic  | rw |+--------+--------------+--------+----+|      1 | user_1 | #      |  6 ||      2 | user_2 | $SYS/# |  4 |+--------+--------------+--------+----+4 rows in set (0.00 sec)mysql> select * from  tbl_mqttuser;+---------+--------------+---------------------------------------------------------------------+---------------------------------------------------------------------+---------------------+---------------------+| user_id | user_name    | user_passwd                                                         | old_password

⚠️ 注意:对$SYS系统主题的权限设置需要注意读写权限,一般来说是不会开放写数据权限的,否则系统主题得到的数据就不是正确的统计数据了,可能是篡改掉了的。在生产环境中一般系统主题是不会开放的。

3 总结

  • 物联网的安全尤为重要,MQTT 作为广泛使用的轻量级协议,实现安全的方式有多种

  • MQTT 协议本身支持用户名和密码实现客户端的身份校验

  • 使用 SSL(升级版本 TLS)可以对网络数据进行加密(这与 MQTT 协议本身是无关的,会增加网络开销)

  • 通过 Broker 可以配置对 Topic 的读写权限

  • 使用授权管理插件,实现批量级用户权限和 topic 的读写权限管理

  • $SYS系统主题的权限设置需要注意读写权限,一般来说是不会开放写数据权限

4 扩展之 MQTT SYS 主题

MQTT v3.1.1 是较旧的 ISO 和 OASIS 标准,MQTT v5.0 是 OASIS 标准,该协议定义了静态主题、必须实现的SYS主题和非必须实现的主题。

「静态 SYS 主题:」 不需要在每个$SYS主题更新时间间隔上发送有关静态$SYS主题的消息,只有在订阅了之后才发送一次。

「必选主题:」 每个声称支持$SYS主题的代理(broker,如 mosquitto)都应支持这些主题,是每个 broker 都需要支持的。

「可选主题:」 代理可以选择性实现这些主题。

必选主题和可选主题中包含静态主题。

必选主题:

  • $SYS/broker/load/bytes/received : 自代理启动以来收到的字节总数。

  • $SYS/broker/load/bytes/sent : 自代理启动以来发送的字节总数。

  • $SYS/broker/clients/connected : 当前连接的客户端数

  • $SYS/broker/clients/disconnected : 在代理上注册但当前已断开连接的持久客户端总数(禁用了 clean session)。

  • $SYS/broker/clients/maximum : 已连接到代理的最大活动客户端数。仅在更新 $SYS主题树时才计算此值,因此可能不计算短暂的客户端连接。

  • $SYS/broker/clients/total : 当前已在代理上连接并注册的持久会话的已连接和已断开连接的客户端总数。

  • $SYS/broker/messages/received : 自代理启动以来收到的任何类型的消息总数。

  • $SYS/broker/messages/sent : 自代理启动以来发送的任何类型的消息总数。

  • $SYS/broker/messages/publish/dropped : 由于运行中/排队限制而删除的发布消息总数。

  • $SYS/broker/messages/publish/received : 自代理启动以来收到的 PUBLISH 消息总数。

  • $SYS/broker/messages/publish/sent : 自代理启动以来发送的 PUBLISH 消息总数。

  • $SYS/broker/messages/retained/count: 代理上活动的保留消息总数。

  • $SYS/broker/subscriptions/count: 代理上活动的订阅总数。

  • $SYS/broker/uptime: 代理已联机的时间(以秒为单位)

  • $SYS/broker/version: broker 的版本。静态主题

可选主题:

  • $SYS/broker/time: 服务器上的当前时间

  • $SYS/broker/timestamp: 生成此特定版本的代理的时间戳。静态主题。

  • ......

5 参考链接

文章难免疏漏,而公众号上每篇文章只能修改几个字,所以我会在我的小程序小白AI博客上也发一遍,任何的错误,我会在及时修改,欢迎随时交流。

关注我的公众号,获取最新学习分享:

MQTT安全性设计详解

本文分享自微信公众号 - 别打名名(biedamingming)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
3年前
Spring Boot从零入门1_详述
本文属于原创,转载注明出处,欢迎关注微信小程序小白AI博客和微信公众号别打名名或者网站https://xiaobaiai.net或者我的CSDNhttp://blog.csdn.net/freeape!(https://oscimg.oschina.net/oscnet/f8db20c4f3964337b76dc956a3a8
Stella981 Stella981
3年前
Spring Boot从零入门6_Swagger2生成生产环境中REST API文档
本文属于原创,转载注明出处,欢迎关注微信小程序小白AI博客和微信公众号别打名名或者网站https://xiaobaiai.net或者我的CSDNhttp://blog.csdn.net/freeape!(https://oscimg.oschina.net/oscnet/cc3a3a51382349e5ab55c2a62f01
Stella981 Stella981
3年前
Spring Boot从零入门5_五脏俱全的RESTful Web Service构建
本文属于原创,转载注明出处,欢迎关注微信小程序小白AI博客和微信公众号别打名名或者网站https://xiaobaiai.net或者我的CSDNhttp://blog.csdn.net/freeape!(https://oscimg.oschina.net/oscnet/378afc2c41cd4b4ba99acadb9d83
Stella981 Stella981
3年前
Spring Boot从零入门3_创建Hello World及项目剖析
本文属于原创,转载注明出处,欢迎关注微信小程序小白AI博客和微信公众号别打名名或者网站https://xiaobaiai.net或者我的CSDNhttp://blog.csdn.net/freeape!(https://oscimg.oschina.net/oscnet/89944effaec841a9b6bad0cce8cf
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Spring Boot从零入门2_核心模块详述和开发环境搭建
本文属于原创,转载注明出处,欢迎关注微信小程序小白AI博客和微信公众号别打名名或者网站https://xiaobaiai.net或者我的CSDNhttp://blog.csdn.net/freeape!(https://oscimg.oschina.net/oscnet/824604023db348fd99425746632b
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这