6、MQTT的安全和调试⼯具
1、MQTT的安全
由于MQTT运⾏于TCP层之上并以明⽂⽅式传输,这就相当于HTTP的明⽂传输,使⽤Wireshark可以完全看到MQTT发送的所有消息,消息指令⼀览⽆遗,如图1所⽰。
Wireshark抓取MQTT数据包
这样可能会产⽣以下风险:
设备可能会被盗⽤;
客户端和服务端的静态数据可能是可访问的(可能会被修改);
协议⾏为可能有副作⽤(如计时器攻击);
拒绝服务攻击;
通信可能会被拦截、修改、重定向或者泄露;
虚假控制报⽂注⼊。
作为传输协议,MQTT仅关注消息传输,提供合适的安全功能是开发者的责任。安全功能可以从三个层次来考虑——应⽤层、传输层、⽹络层。
应⽤层:在应⽤层上,MQTT提供了客户标识(Client Identifier)以及⽤户名和密码,可以在应⽤层验证设备。
传输层:类似于HTTPS,MQTT基于TCP连接,也可以加上⼀层TLS,传输层使⽤TLS加密是确保安全的⼀个好⼿段,可以防⽌中间⼈攻击。客户端证书不但可以作为设备的⾝份凭证,还可以⽤来验证设备。
⽹络层:如果有条件的话,可以通过拉专线或者使⽤VPN来连接设备与MQTT代理,以提⾼⽹络传输的安全性。
(1)认证
MQTT⽀持两种层次的认证:
应⽤层:MQTT⽀持客户标识、⽤户名和密码认证;
传输层:传输层可以使⽤TLS,除了加密通讯,还可以使⽤X509证书来认证设备。
(2)客户标识
MQTT客户端可以发送最多65535个字符作为客户标识(Client Identifier),⼀般来说可以使⽤嵌⼊式芯⽚的MAC地址或者芯⽚序列号。虽然使⽤客户标识来认证可能不可靠,但是在某些封闭环境或许已经⾜够了。
(3)⽤户名和密码
MQTT协议⽀持通过CONNECT消息的username和password字段发送⽤户名和密码。
⽤户名及密码的认证使⽤起来⾮常⽅便,不过由于它们是以明⽂形式传输,所以使⽤抓包⼯具就可以轻易的获取。
⼀般来说,使⽤客户标识、⽤户名和密码已经⾜够了,⽐如⽀持MQTT协议连接的OneNET云平台,就是使⽤了这三个字段作为认证。如果感觉还不够安全,还可以在传输层进⾏认证。
(4)在传输层认证
免费平台源码资源网 在传输层认证是这样的:MQTT代理在TLS握⼿成功之后可以继续发送客户端的X509证书来认证设备,如果设备不合法便可以中断连接。使⽤X509认证的好处是,在传输层就可以验证设备的合法性,
在发送CONNECT消息之前便可以阻隔⾮法设备的连接,以节省后续不必要的资源浪费。⽽且,MQTT协议运⾏在使⽤TLS时,除了提供⾝份认证,还可以确保消息的完整性和保密性。
(5)选择⽤户数据格式
MQTT协议只实现了传送消息的格式,并没有限制⽤户协议需要按照⼀定的风格,因此在MQTT协议之上,我们需要定义⼀套⾃⼰的通信协议。⽐如说,发布者向设备发布⼀条打开消息,设备可以回复⼀个消息并携带返回码,这样的消息格式是使⽤⼆进制、字符串还是JSON格式呢?下⾯就简单做个选型参考。
1)⼗六进制/⼆进制
MQTT原本就是基于⼆进制实现的,所以⽤户协议使⽤⼆进制实现是⼀个不错的选择。虽然失去了直观的可读性,但可以将流量控制在⾮常⼩。其实对于单⽚机开发者来说⼗六进制并不陌⽣,因为单⽚机寄存器都是以位来操作的,芯⽚间通信也会使⽤⼗六进制/⼆进制。⽽对于没有单⽚机开发经验的⼯程师来说,⼗六进制/⼆进制可能就太原始了。
2)字符串
对单⽚机开发者来说,字符串也是⼀个选择。⽐如通过串⼝传输的AT指令就是基于字符串通信的。
使⽤字符串⽅便了⼈阅读,但是对⾼级语⾔开发者来说,字符串依旧不是最佳选择,恐怕键值对(Key-Value)才是最优形式。
3)JSON
JSON中⽂全称是JavaScript对象标记语⾔,在这门语⾔中,⼀切都是对象。因此,任何⽀持的类型都可以通过JSON来表⽰,例如字符
串、数字、对象、数组等。其语法规则是:
对象表⽰为键值对;
数据由逗号分隔;
花括号保存对象;
⽅括号保存数组。
JSON层次结构简洁清晰,易于阅读和编写,同时也易于机器解析和⽣成,有效提升⽹络传输效率。
对于单⽚机开发者,主流的微控制器软件开发⼯具Keil有提供JSON库,可以⽤于STC、STM32等微
控制器开发,所以在微控制器上解析JSON不需要⾃⼰写⼀个JSON解析器或者移植了。
如果实在懒得使⽤JSON库⽣成或解析,也可以直接使⽤C语⾔中的sprintf⽣成JSON字符串,⽐如:
sprintf(buf, "{\"String\":\"%s\", \"Value\":%d}", "Hello World!", 12345);
这样就可以⽣成⼀个{“String”:”Hello World!”, “Value”:12345}JSON字符串了。
(6)XML
MQTT协议只负责通信部分,⽤户协议可以⾃⼰选择,当然也可以选择复杂⼜冗长的XML格式。可是既然要选择MQTT+XML,为什么不考虑换为XMPP呢?
综上所述,MQTT+JSON是⽬前最优⽅案。协议简洁清晰、易于阅读、解析和⽣成等,也考虑了服务器端开发者和设备端开发者的开发成本。
2、有关MQTT的云平台和⼯具
(1)⽀持MQTT的云平台
⽬前,百度、阿⾥、腾讯的云平台都逐渐有了物联⽹开发套件:腾讯QQ物联平台内测中,阿⾥云物
联⽹套件公测中,两者都需要进⾏申请试⽤,⽽百度云物联⽹套件已经⽀持MQTT并且可以免费试⽤⼀段时间。除了BAT三⼤家,下⾯再介绍⼀些其他⽀持MQTT的物联⽹云平台。
OneNET云平台:OneNET是由中国移动打造的PaaS物联⽹开放平台。平台能够帮助开发者轻松实现设备接⼊与设备连接,快速完成产品开发部署,为智能硬件、智能家居产品提供完善的物联⽹解决⽅案。OneNET云平台已经于2014年10⽉正式上线。
云巴:云巴(Cloud Bus)是⼀个跨平台的双向实时通信系统,为物联⽹、App和Web提供实时通信服务。云巴基于MQTT,⽀持Socket.IO协议,⽀持RESTful API。
(2)MQTT服务器
如果不想使⽤云平台,只是纯粹地玩⼀下MQTT,或者只想在内⽹对设备进⾏监控,那么可以⾃⼰本地部署⼀个MQTT服务器。下⾯介绍⼏款MQTT服务器:
Apache-Apollo:⼀个代理服务器,在ActiveMQ基础上发展⽽来,可以⽀持STOMP、AMQP、MQTT、Openwire、SSL和WebSockets等多种协议,并且Apollo提供后台管理页⾯,⽅便开发者管理和调试。
EMQ:EMQ 2.0,号称百万级开源MQTT消息服务器,基于Erlang/OTP语⾔平台开发,⽀持⼤规模
连接和分布式集,发布订阅模式的开源MQTT消息服务器。
HiveMQ:⼀个企业级的MQTT代理,主要⽤于企业和新兴的机器到机器M2M通讯和内部传输,最⼤程度的满⾜可伸缩性、易管理和安全特性,提供免费的个⼈版。HiveMQ提供了开源的插件开发包。
Mosquitto:⼀款实现了消息推送协议MQTT v3.1的开源消息代理软件,提供轻量级的、⽀持可发布/可订阅的消息推送模式。
(3)MQTT调试⼯具
知道了各⼤平台的MQTT,同时⾃⼰也可以在内⽹部署MQTT服务器,那接下来没有调试⼯具怎么⾏呢,难道要⽤⾃⼰喜欢的语⾔编写⼀个?当然不需要。MQTT调试⼯具可以考虑使⽤HiveMQ的MQTT客户端——HiveMQ Websockets Client,这是⼀款基于WebSocket的浏览器MQTT客户端,⽀持主题订阅和发布。
(4)MQTT与其他协议
⽬前各⼤平台都开始⽀持MQTT协议,MQTT相⽐其他协议有什么优势呢?物联⽹设备能不能⽤其他的协议呢?下⾯是MQTT与其他部分协议的⽐较,给⼤家作为参考。
1)MQTT与TCP Socket
虽然MQTT运⾏于TCP层之上,看起来这两者之间根本没有⽐较性,但笔者觉得还是有必要叙述⼀番,因为⼤多数从事硬件或嵌⼊式开发的⼯程师,都是直接在TCP层上通信的。从事嵌⼊式开发⼯作的⼈都应该知道LwIP,LwIP是⼀套⽤于嵌⼊式系统的开放源代码TCP/IP协议栈,LwIP在保证嵌⼊式产品拥有完整的TCP/IP功能的同时,⼜能保证协议栈对处理器资源的有限消耗,其运⾏⼀般仅需要⼏⼗KB的RAM 和40KB左右的ROM。
也就是说,只要是嵌⼊式产品使⽤了LwIP,就⽀持TCP/IP协议栈,进⽽可以使⽤MQTT协议。
由于TCP协议有粘包和分包问题,所以传输数据时需要⾃定义协议,如果传输的数据报超过MSS(最⼤报⽂段长度),⼀定要给协议定义⼀个消息长度字段,确保接收端能通过缓冲完整收取消息。⼀个简单的协议定义:消息头部+消息长度+消息正⽂。
当然,使⽤MQTT协议则不需要考虑这个问题,这些MQTT都已经处理好了,MQTT最长可以⼀次性发送256MB数据,不⽤考虑粘包分包的问题。
总之,TCP和MQTT本⾝并不⽭盾,只不过基于Socket开发需要处理更多的事情,⽽且⼤多数嵌⼊式开发模块本⾝也只会提供Socket接⼝供⼚家⾃定义协议。
2)MQTT与HTTP
HTTP最初的⽬的是提供⼀种发布和接收HTML页⾯的⽅法,主要⽤于Web。HTTP是典型的C/S通讯模式:请求从客户端发出,服务端只能被动接收,⼀条连接只能发送⼀次请求,获取响应后就断开连接。该协议最早是为了适⽤Web浏览器的上⽹浏览场景⽽设计的,⽬前在PC、⼿机、Pad等终端上都应⽤⼴泛。由于这样的通信特点,HTTP技术在物联⽹设备中很难实现设备的反向控制,不过⾮要实现也不是不⾏,下⾯看⼀下Web端的例⼦。
⽬前,在微博等SNS⽹站上有海量⽤户公开发布的内容,当发布者发布消息,数据传到服务器更新时,就需要给关注者尽可能的实时更新内容。Web⽹站基于HTTP协议,使⽤HTTP协议探测服务器上是否有内容更新,就必须频繁地让客户端请求服务器进⾏确认。在浏览器中要实现这种效果,可以使⽤Comet技术,Comet是基于HTTP长连接的“服务器推”技术,主要有两种实现模型:基于AJAX的长轮询(long-polling)⽅式和基于Iframe及htmlfile的流(streaming)⽅式。这两种技术模型在这⾥不详细展开,有兴趣的读者可以查阅相关资料。
如果要实现设备的反向控制,可能就要⽤到前⾯提到的Comet技术。由于需要不断的请求服务器,会导致通信开销⾮常⼤,加上HTTP 冗长的报⽂头,在节省流量上实在没有优势。
当然,如果只是单纯地让设备定时上报数据⽽不做控制,也是可以使⽤HTTP协议的。
3)MQTT与XMPP
最有可能与MQTT竞争的是XMPP协议。XMPP(可扩展通讯与表⽰协议)是⼀项⽤于实时通讯的开放技术,它使⽤可扩展标记语⾔(XML)作为交换信息的基本格式。其优点是协议成熟、强⼤、可扩展性强。⽬前主要应⽤于许多聊天系统中,在消息推送领域,MQTT和XMPP互相竞争。下⾯列举MQTT与XMPP各⾃的特性:
XMPP协议基于繁重的XML,报⽂体积⼤且交互繁琐;⽽MQTT协议固定报头只有两个字节,报⽂体积⼩、编解码容易;
XMPP基于JID的点对点消息传输;MQTT协议基于主题(Topic)发布\订阅模式,消息路由更为灵活;
XMPP协议采⽤XML承载报⽂,⼆进制必须进⾏Base64编码或其他⽅式处理;MQTT协议未定义报⽂内容格式,可以承载JSON、⼆进制等不同类型报⽂,开发者可以针对性的定义报⽂格式;
MQTT协议⽀持消息收发确认和QoS保证,有更好的消息可靠性保证;⽽XMPP主协议并未定义类似机制;
在嵌⼊式设备开发中⼤多使⽤的是C语⾔开发,C语⾔解析XML是⾮常困难的。MQTT基于⼆进制实现且未定义报⽂内容格式,可以很好的兼顾嵌⼊式C语⾔开发者;⽽XMPP基于XML,开发者需要配合协议格式,不能灵活开发。
综上所述,在嵌⼊式设备中,由于需要⼀个灵巧简洁,对设备开发者和服务端开发者都友好的协议,MQTT⽐XMPP更具有优势。
4)MQTT与CoAP
CoAP也是⼀个能与MQTT竞争的协议。其模仿HTTP的REST模型,服务端以URI⽅式创建资源,客户端可以通过GET、PUT、POST、DELETE⽅式访问这些资源,并且协议风格也和HTTP极为相似,例如⼀个设备有温度数据,那么这个温度可以被描述为:CoAP://:/sensors/temperature
其中为设备的IP,为端⼝。
不过,如果使⽤CoAP可能会让物联⽹后台的情况变得复杂,⽐如MQTT可以实现⼀个最简单的IoT架构:Device + MQTT服务器 + APP,⼿机端或Web端可以直接从MQTT服务器订阅想要的主题。⽽CoAP可能需要这样的架构:CoAP + Web + DataBase + App,使⽤CoAP必须经过DataBase才能转给第三⽅。
⾄于CoAP和MQTT孰优孰劣,这⾥不作定论。不过⽬前来说,CoAP资料还是略少。⽽且,MQTT除了可以应⽤于物联⽹领域,在⼿机消息推送、等领域都可以有所作为。
(5)⼩结
经过以上的⽐较,我们可以得出如下结论:MQTT基于异步发布/订阅的实现解耦了消息发布者和订阅者,基于⼆进制的实现节省了存储空间及流量,同时MQTT拥有更好的消息处理机制,可以替代TCP Socket⼀部分应⽤场景。相对于HTTP和XMPP,MQTT可以选择⽤户数据格式,解析复杂度低,同时MQTT也可⽤于⼿机推送等领域。⼿机作为与⼈连接的⼊⼝,正好建⽴了⼈与物的连接,可谓⼀箭双雕。当然,其他协议也可以作为⼀个辅助的存在,HTTP可以为只需定时上传数据的设备服务,CoAP则更适⽤于⾮常受限的移动通信⽹络,表3直观地展⽰了上⽂提到的⼏种协议之间的优劣异同。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论