MQTT
Message Queuing Telmetry Transport,消息队列遥测传输;基于代理的“发布/订阅”模式的消息传输协议。
网上有很多关于MQTT的数据结构的分析,但是很少有实际抓包的分析,此文是根据实际抓包来解析MQTT的数据格式,来认识MQTT;
控制报文格式不介绍,直接开始抓包看,下面为MQTT的控制报文;
1. 连接服务端
1.1 连接标志 (Connect Flag)
连接标志字节包含一些用于指定MQTT连接行为的参数。它还指出有效载荷中的字段是否存在。
1.1.1 用户名密码标志位(User Name Flag/Password FLag):
顾名思义,设置了就必须包含对应字段;
1.1.2遗嘱保留(Will Retain)
如果遗嘱消息被发布时需要保留,需要指定这一位的值。
遗嘱标志位设置为0:遗嘱标志位为0,遗嘱保留必须为0;
遗嘱标志位设置为1:
遗嘱保留为0:服务端必须将遗嘱消息当中非保留消息发布;
遗嘱保留为1:服务端必须将遗嘱消息当中保留消息发布
1.1.3 遗嘱QoS(QoS Level)
指定发布遗嘱消息时使用的服务质量等级。
设置为00:遗嘱标志位为0,遗嘱QoS必须为0;
设置为01:遗嘱QoS可以等于0(0x00),1(0x01),2(0x02)。不能等于3。
1.1.4 遗嘱标志位(Will Flag)
设置为1:表示Will Message消息必须被存储在服务端,并与这个网络连接关联;连接标志中的Will QoS和Will Retain字段会被服务端用到,且必须包含Will Topic字段,
设置为0:表示连接标志中的Will QoS和Will Retain字段必须设置为0,并且不能包含Will Message和Will Topic字段。
1.1.5 清理会话(Clean Session Flag)
指定了会话状态的处理方式;控制会话状态的生存时间;
设置为0:服务端基于当前会话(以Client ID识别)的状态恢复与客户端的通信,若没有关联会话,则创建新会话;
设置为1:服务端与客户端丢弃之前的任何会话,重新开始新的会话,与该会话关联的状态数据不能被任何会话复用;
1.1.5 有效载荷 playload:
必须以这个顺序出现:客户端标识符、遗嘱主题、遗嘱消息、用户名、密码
1.1.6.1 客户端标识符 Client ID
客户端连接服务端的唯一标识;
服务端可以允许编码后超过23个字节的客户端标识符 (ClientId)。
“0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ”
服务端可以允许包含不是上面列表字符的客户端标识符 (ClientId)。
当客户端提供零字节的客户端标识符时,必须将清理会话标志设置为1;
如果提供了零字节但清理会话标志为0,服务端拒绝,并返回0x02(表示标识符不合格),然后关闭网络连接。
1.1.6.2 遗嘱主题Will Topic
1.1.6.3 遗嘱消息Will Message
1.1.6.4 用户名密码
用于身份验证和授权。
服务端根据对应的标志位来对消息采取对应操作。
1.2 确认连接请求
1.4 发布消息
1.4.1 重发标志(DUP Flag)
为0:表示客户端或服务的第一次请求发送这个PUBLISH报文;
为1:表示可能是一个早前报文请求的重发。
1.4.2 服务质量等级(QoS Level)
参考上面;
1.4.3 保留标志(Retain)
为0:
为1:表示服务端必须存储这个消息和其QoS,以便分发给遗嘱主题匹配的订阅者;
1.5 发布确认
后面的几种数据类型都没有有效载荷,均为较简单的报头;
1.6 订阅主题
1.7 订阅确认
还有以下消息,因为没有抓到对应的包,但是下面的数据包也比较简单;
以下数据包没有有效载荷,数据包比较简单,与发布确认类似,以前几位的MQTT控制报文类型来识别指令:
1.8 取消订阅
1.9 取消订阅确认
1.10 发布收到
1.11 发布释放
1.12 发布完成
1.13 心跳请求
1.14 心跳相应
1.15 断开连接
2. 操作行为
2.1 状态存储
常连接,服务端会已知保留连接,只有等客户端发出断开连接请求才会删除会话状态;
因为会话状态常存储在易失性存储器(内存)中,资源限制、电力供应等原因可能会造成会话丢失的情况出现;
所以也有出现会话状态存储在非易失性存储器(硬盘)。
2.2 网络连接
MQTT要求底层传输层提供有序的、可靠的、双向传输的字节流;
支持TCP、WebSocket协议,不支持UDP协议;
TCP端口8883和1883已在IANA注册,分别用户MQTT的TLS和非TLS通信。
2.3 服务质量等级和协议流程 QoS
等
3 安全
在看完整个MQTT的数据通信报文后,从安全方面考虑,我们有哪些测试点,以及怎么防范这些问题的发生;
3.1 客户端身份验证
包含用户名和密码,实现身份验证机制;
并使用TLS(VPN)确保数据私密。
3.2 客户端授权
基于客户端提供如账号密码、客户端标识符等信息,服务端提供限制对某些服务端资源的访问。
3.3 服务端身份验证
MQTT不是双向信任,通过TLS(VPN)来解决;
3.4 控制报文和应用消息的完整性
数据传输包含HASH,以提供数据的完整性校验;
或者通过TLS(VPN)的方式解决;
3.5 控制报文和应用消息的保密性
TLS可以对网络传输的数据加密,如果有效的TLS密码组合包含的加密算法位NULL,此时不会加密数据,避免使用这些密码组合;
应用可以单独加密应用消息的内容,但不能给应用消息的其他属性如主题名加密;
3.6消息传输的不可抵赖性(可选)
3.7 检测客户端和服务端的盗用
TLS可解决;
3.8 检测异常行为(物联网安全运营)
潜在风险:
- 重复的连接请求
- 重复的身份验证请求
- 连接的异常终止
- 主题扫描(请求发送或订阅大量主题)
- 发送无法送达的消息(没有订阅者的主题)
- 客户端连接了但是不发送数据
可以以此实现MQTT服务的防火墙,与WAF的实现类似,检测到潜在风险,服务端实现可以断开客户端的连接(拒绝客户端的响应);亦可基于IP地址或可达标识符实现动态黑名单;
对公司的MQTT防火墙做了简单调研,由于目前MQTT使用了TLS,但是防火墙没有解密操作,所以过了的数据也无法识别,后续可以对数据解开再进行分析,有效阻隔恶意攻击。
参考:https://mcxiaoke.gitbooks.io/mqtt-cn/content/