物联网协议漫谈 05

好久没有更新了,今天咱们来聊一下MQTT协议的具体内容。

1 MQTT 协议简介

MQTT 协议通过交换预定义的 MQTT 控制报文来实现通信。MQTT 控制报文由:

固定报头 Fixed Header(所有控制报文都包括)+可变报头(部分控制报文包括)+消息体(即负载,也是仅有部分控制报文包括),这三部分组成。

1.1 固定报头的的构造如下

1.2 MQTT 控制报文类型 Message Type

MQTT拥有 14 种不同的消息类型:

(1)CONNECT:客户端连接到 MQTT 代理

(2)CONNACK:连接确认

(3)PUBLISH:新发布消息

(4)PUBACK:新发布消息确认,是 QoS 1 给 PUBLISH 消息的回复

(5)PUBREC:QoS 2 消息流的第一部分,表示消息发布已记录

(6)PUBREL:QoS 2 消息流的第二部分,表示消息发布已释放

(7)PUBCOMP:QoS 2 消息流的第三部分,表示消息发布完成

(8)SUBSCRIBE:客户端订阅某个主题

(9)SUBACK:对于 SUBSCRIBE 消息的确认

(10)UNSUBSCRIBE:客户端终止订阅的消息

(11)UNSUBACK:对于 UNSUBSCRIBE 消息的确认

(12)PINGREQ:心跳

(13)PINGRESP:确认心跳

(14)DISCONNECT:客户端终止连接前优雅地通知 MQTT 代理

其中第 0 和第 15 位是保留位,禁止报文流动。

1.3 DUP flag 标志位

是用来在保证消息传输可靠的,如果设置为 1,则在下面的变长头部里多加 MessageId,并需要回复确认,保证消息传输完成,但不能用于检测消息重复发送。

1.4 QoS Level 服务质量等级

我们在第一部分讲过了。

1.5 Retain

主要用于 PUBLISH(发布态)的消息,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它。如果不设那么推送至当前订阅的就释放了。

1.6Remaining Length 剩余长度

表示当前报文剩余部分的字节数,包括可变报头和负载的数据。剩余长度不包括用于编码剩余长度字段本身的字节数。但是不是并不是直接保存的,同样也是可以扩展的,其机制是,前 7 位用于保存长度,后一部用做标识。下表归纳了剩余字段的大小。

例如:十进制数 64 会被编码为一个字节,数值是 64,十六进制表示为 0x40。十进制数字321(= 65+2*128)被编码为两个字节,最低有效位在前。第一个字节是 65+128 = 193。注意最高位为 1 表示后面至少还有一个字节。第二个字节是 2。同理还可以加第 3 个字节,最多可以加至第 4 个字节。故 MQTT 协议最多可以实现 268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)将近 256M 的数据。可谓能伸能缩。

1.7 Variable header 可变报头

它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。客户端和服务端彼此独立地分配报文标识符。因此,客户端服务端组合使用相同的报文标识符可以实现并发的消息交换。

可变报头结构如下:

(1)首先最上面的 8 个字节是 Protocol Name(协议名),UTF 编码的字符“MQIsdp”,头两个是编码名提长为 6。

这里多说一些,接下去的协议多采用这种方式组合,即头两个字节表示下一部分的长,然后后面跟上内容。这里头两个字节长为 6,下面跟 6 个字符“MQIsdp”。

(2)Protocol Version,协议版本号,v3 也是固定的。

(3)Connect Flag,连接标识,有点像固定头部的。8 位分别代表不同的标志。第 1 个字节保留。

Clean Session,Will flag,Will Qos, Will Retain 都是相对于 CONNECT 消息来说的。

— Clean Session:0表示如果订阅的客户机断线了,那么要保存其要推送的消息,如果其重新连接时,则将这些消息推送。

— Clean Session:1表示消除,表示客户机是第一次连接,消息所以以前的连接信息。

— Will Flag,表示如果客户机在不是在发送 DISCONNECT 消息中断,比如 I/O 错误等,将些置为 1,要求重传。并且下且的 WillQos 和 WillRetain 也要设置,消息体中的 Topic 和 MessageID 也要设置,就是表示发生了错误,要重传。

— Will Qos,在 CONNECT 非正常情况下设置,一般如果标识了 WillFlag,那么这个位置也要标识。

— Will RETAIN:同样在 CONNECT 中,如果标识了 WillFlag,那么些位也一定要标识。

— Usename flag 和 passwordflag,用来标识是否在消息体中传递用户和密码,只有标识了,消息体中的用户名和密码才用效,只标记密码而不标记用户名是不合法的。

(4)Keep Alive,表示响应时间,如果这个时间内,连接或发送操作未完成,则断开 tcp 连接,表示离线。

(5)Connect Return Code,通常于 CONNACK 消息中,表示返回的连接情况,我可以通过此检验连接情况。

1.8 Topic Name

即订阅消息标识,由于 MQTT 是基于订阅/发布的消息,那么这个就是消息订阅的标识,像新闻客户端里的订阅不同的栏目一样。用于区别消息的推送类别。

主要用于 PUBLISH 和 SUBSCRIBE 中。最大可支持 32767 个字符,即 4 个字节。

1.9 消息负载 PayLoad

只有 3 种消息有消息负载,即 CONNECT,SUBSCRIBE 和 SUBACK。

(1)CONNECT主要是客户机的 ClientID,订阅的 Topic 和 Message 以及用户名和密码,其于变长头部中的 will 是对应的。

(2)SUBSCRIBE包含了一系列的要订阅的主题以及 QoS。

(3)SUBACK是用服务器对于 SUBSCRIBE 所申请的主题及 QoS 进行确认和回复。

而 PUBLISH 是消息体中则保存推送的消息,以二进制形式,当然这里的编辑可自定义。

1.10 Message Identifier

包含于 PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE 和 UNSUBACK 消息中。

其为 16 位字符表示,用于在 Qos 为 1 或 2 时标识 Message 的,保证 Message 传输的可靠性。

————————— 我叫隔离带宽 —————————

2 MQTT 安全机制

关于安全机制的解决方案,需要考虑很多风险。例如:

(1)设备可能会被盗用

(2)客户端和服务端的静态数据可能是可访问的(可能会被修改)

(3)协议行为可能有副作用(如计时器攻击)

(4)拒绝服务攻击

(5)通信可能会被拦截、修改、重定向或者泄露

(6)虚假控制报文注入

由于 MQTT 协议通常部署在不安全的通信环境中。在这种情况下,协议实现通常需要提供这些安全机制:

(1)用户和设备身份认证

(2)服务端资源访问授权

(3)MQTT 控制报文和内嵌应用数据的完整性校验

(4)MQTT 控制报文和内嵌应用数据的隐私控制

2.1 MQTT 安全解决方案:安全和认证

(1)轻量级的加密与受限设备

广泛采用高级加密标准(AES)数据加密标准(DES)。推荐使用为受限的低端设备特别优化过的轻量级加密国际标准 ISO 29192 。

(2)客户端身份验证 Authentication of Clients by the Server

CONNECT 报文包含用户名和密码字段。实现可以决定如何使用这些字段的内容。实现者可以提供自己的身份验证机制,或者使用外部的认证系统如 LDAP 或 OAuth ,还可以利用操作系统的认证机制。

实现可以明文传递认证数据,混淆那些数据,或者不要求任何认证数据,但应该意识到这会增加中间人攻击和重放攻击的风险。

在客户端和服务端之间使用虚拟专用网(VPN)可以确保数据只被授权的客户端收到。

使用 TLS 时,服务端可以使用客户端发送的 SSL 证书验证客户端的身份。

实现可以允许客户端通过应用消息给服务端发送凭证用于身份验证。

(3)客户端授权 Authorization of Clients by the Server

基于客户端提供的信息如用户名、客户端标识符(ClientId)、客户端的主机名或 IP 地址,或者身份认证的结果,服务端可以限制对某些服务端资源的访问。

(4)服务端身份验证 Authentication of the Server by the Client

由于 MQTT 协议不是双向信任的,它没有提供客户端验证服务端身份的机制。

但是使用 TLS 时,客户端可以使用服务端发送的 SSL 证书验证服务端的身份。从单 IP 多域名提供 MQTT 服务的实现应该考虑 TLS 的 SNI 扩展。SNI 允许客户端告诉服务端它要连接的服务端主机名。

实现可以允许服务端通过应用消息给客户端发送凭证用于身份验证。

在客户端和服务端之间使用虚拟专用网(VPN)可以确保客户端连接的是预期的服务器。

(5)控制报文和应用消息的完整性 Integrity of Application Messages and Control Packets

应用可以在应用消息中单独包含哈希值。这样做可以为 PUBLISH 控制报文的网络传输和静态数据提供内容的完整性检查。

TLS 提供了对网络传输的数据做完整性校验的哈希算法。

在客户端和服务端之间使用虚拟专用网(VPN)连接可以在 VPN 覆盖的网络段提供数据完整性检查。

(6)控制报文和应用消息的保密性 Privacy of Application Messages and Control Packets

TLS 可以对网络传输的数据加密。如果有效的 TLS 密码组合包含的加密算法为 NULL,那么它不会加密数据。要确保客户端和服务端的保密,应避免使用这些密码组合。

应用可以单独加密应用消息的内容。这可以提供应用消息传输途中和静态数据的私密性。但不能给应用消息的其它属性如主题名加密。

客户端和服务端实现可以加密存储静态数据,例如可以将应用消息作为会话的一部分存储。

在客户端和服务端之间使用虚拟专用网(VPN)连接可以在 VPN 覆盖的网络段保证数据的私密性。

(7)消息传输的不可抵赖性 Non-repudiation of message transmission

应用设计者可能需要考虑适当的策略,以实现端到端的不可抵赖性(non-repudiation)。

(8)检测客户端和服务端的盗用 Detecting compromise of Clients and Servers

使用 TLS 的客户端和服务端实现应该能够确保,初始化 TLS 连接时提供的 SSL 证书是与主机名(客户端要连接的或服务端将被连接的)关联的。

使用 TLS 的客户端和服务端实现,可以选择提供检查证书吊销列表 CRLs 和在线证书状态协议 OSCP 的功能,拒绝使用被吊销的证书。

物理部署可以将防篡改硬件与应用消息的特殊数据传输结合。例如,一个仪表可能会内置一个 GPS 以确保没有在未授权的地区使用。IEEE 安全设备认证 IEEE 802.1AR 就是用于实现这个机制的一个标准,它使用加密绑定标识符验证设备身份。

(9)检测异常行为 Detecting abnormal behaviors

服务端实现可以监视客户端的行为,检测潜在的安全风险。例如:

— 重复的连接请求

—重复的身份验证请求

—连接的异常终止

—主题扫描(请求发送或订阅大量主题)

—发送无法送达的消息(没有订阅者的主题)

—客户端连接但是不发送数据

一旦发现违反安全规则的行为,服务端实现可以断开客户端连接。

服务端实现检测不受欢迎的行为,可以基于 IP 地址或客户端标识符实现一个动态黑名单列表。

服务部署可以使用网络层次控制(如果可用)实现基于 IP 地址或其它信息的速率限制或黑名单。

关于安全解决方案的话题,我们就不在这里继续展开了,各位可以自行深入研究。

后续我们将继续选取应用较为广泛的几个应用层协议,具体来聊,请大家关注!

图片授权基于:CC0协议

  • 发表于:
  • 原文链接:http://kuaibao.qq.com/s/20180130A0OY8300?refer=cp_1026

同媒体快讯

  • 物联网协议漫谈 04

    2018-10-22
  • LoRaWAN 协议研读 06

    2018-10-22

相关快讯

扫码关注云+社区