`
Josh_Persistence
  • 浏览: 1653504 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

MQTT协议 - 安全问题

阅读更多

一、概述:

        物联网的核心是连接万物,通过交换并分析数据使得生活更舒适与便捷。不过,敏感数据泄露或者设备被非法控制可不是闹着玩的。比如前段时间国内某著名家电企业的智能洗衣机,使用了某著名电商基于XMPP协议的物联网平台,不费吹灰之力便被黑客攻破并远程遥控,给智能家居的发展带来了一些阴影。究其本质,并不是物联网技术本身有缺陷,而是在物联网系统的设计中最基本的安全设计被工程师轻视了,才导致整个系统的崩塌。

 

在这里我们将介绍为何以及如何运用MQTT提供的安全特性来保证物联网项目的顺利实施。

安全对于几乎所有的项目都是一个挑战,对于物联网项目更是如此:

  • 设备安全性与设备可用性之间往往是零和博弈。
  • 加密算法需要更多的计算能力,而物联网设备的性能往往非常有限。
  • 物联网的网络条件常常要比家庭或者办公室的网络条件差许多。

对于以上挑战,MQTT提供了多个层次的安全特性:

  1. 网络层:有条件可以通过拉专线或者使用VPN来连接设备与MQTT代理,以提高网络传输的安全性。
  2. 传输层:传输层使用TLS加密是确保安全的一个好手段,可以防止中间人攻击(Man-In-The-Middle Attack)。客户端证书不但可以作为设备的身份凭证,还可以用来验证设备。
  3. 应用层:MQTT还提供客户标识(Client Identifier)以及用户名密码,在应用层验证设备。

虽然MQTT提供了多重安全设计,不过世界上并没有银弹能够保障数据的绝对安全,所以应该在设计的时候就把安全放在设计目标之中并拥有相当的优先级,否则上文提到的智能洗衣机就是一个活生生的教训。

而网络层可以使用专线或者VPN超出了本文的范围,下面我们结合Mosquitto仔细了解一下传输层和应用层的MQTT安全特性。

 

加密

MQTT是基于TCP的,默认情况通讯并不加密。如果你需要传输敏感信息或者对设备进行反控,使用TSL几乎是必须的。打个比方,如果你在咖啡店用免费Wi-Fi上网,登录互联网金融的网站不支持HTTPS传输,那么你的账号信息多半已经在咖啡店的Wi-Fi日志里面躺着了……

TSL是非常成熟的安全协议,在握手的时候便可以创建安全连接,使得黑客无法偷听或者篡改内容了。使用TLS的时候有以下注意点:

  • 尽可能使用高版本的TLS。
  • 验证X509证书链防止中间人攻击。
  • 尽量使用有CA发布的证书。

当然,TLS会增加连接时开销,对低运算能力的设备而言是额外的负担,不过如果设备是长连接的话就会避免反复连接的开销。

 

Mosquitto原生支持了TLS加密,生成证书后再配置一下MQTT代理即可。

首先我们需要生成证书权威(Certificate Authority,CA)的认证和密钥,生成过程中Common Name一定要填写Fully Qualified Domain Name(测试期间用IP地址也凑合):

 

openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt

 接下来生成MQTT代理使用的密钥:

 

 

openssl genrsa -des3 -out server.key 2048

 并去除密码:

 

 

openssl genrsa -out server.key 2048

 然后为MQTT代理准备一个认证注册请求(Certificate Signing Request,CSR),这里的Common Name也要写对:

 

 

openssl req -out server.csr -key server.key -new

 最后通过CA签署这个CSR生成MQTT代理证书:

 

 

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365

 现在配置/etc/mosquitto/mosquitto.conf,确保8883端口的设置如下:

 

 

listener 8883
cafile /etc/mosquitto/tls/ca.crt
certfile /etc/mosquitto/tls/server.crt
keyfile /etc/mosquitto/tls/server.key

 重启Mosquitto服务就可以用以下命令订阅和发布消息了,当然所有消息都由TLS加密,可以无忧无虑地传递私密信息啦:

 

mosquitto_sub -h host -p 8883 -t 'topic' --cafile ca.crt
mosquitto_pub -h host -p 8883 -t 'topic' -m '15' --cafile ca.crt

 

其中,host需要与前面指定的Common Name一致,否则TLS连接会报错,错误信息也不是很直观……

认证

认证是验证设备身份的过程。拿旅行做比方,在换登机牌的时候需要出示护照以验明正身,即使别人能够假冒你的名字,但是拿不出护照便无法伪造身份。买房的时候,需要通过户口本证明你妈是你妈。

MQTT支持两种层次的认证:

  • 传输层:传输层使用TLS不但可以加密通讯,还可以使用X509证书来认证设备。
  • 应用层:MQTT支持客户标识、用户名密码以及X509证书,在应用层验证设备。

通过传输层和应用层来解释认证并不直观,下面我们直接从客户标识、用户名密码以及X509证书的角度来了解认证。

客户标识

用户可以使用最多65535个字符作为客户标识(Client Identifier),UUID或者MAC地址最为常见。

使用客户标识来认证并不可靠,不过在某些封闭的环境中或许已经足够。

用户名密码

MQTT协议支持通过CONNECT消息的username和password字段发送用户名和密码。

用户名密码的认证使用起来非常方便,不过再强调一下,由于用户名密码是以明文形式传输,在通过互联网时使用TSL加密是必须的。

Mosquitto支持用户名/密码认证方式,只要确保/etc/mosquitto/mosquitto.conf有如下设置:

 

 

password_file /etc/mosquitto/passwd
allow_anonymous false

 其中passwd文件是用来保存用户名和密码的,可以通过mosquitto_passwd来维护用户名密码。之后便可以通过如下命令订阅和发布消息了:

mosquitto_sub -h host -p 8883 -t 'topic' --cafile ca.crt -u user -P pwd
mosquitto_pub -h host -p 8883 -t 'topic' -m '9' --cafile ca.crt -u user -P pwd

 

 

这里端口使用8883是假设已经配置了TLS加密的。

结合TLS加密的用户名密码认证,已经是相对完善的安全体系了。

X509证书

MQTT代理在TLS握手成功之后可以继续发送客户端的X509证书来认证设备,如果设备不合法便可以中断连接。

使用X509认证的好处,是在传输层就可以验证设备的合法性,在发送MQTT CONNECT之前便可以阻隔非法设备的连接,以节省后续不必要的资源浪费。

如果你可以控制设备的创建和设置,X509证书认证或许是个非常好的选择。不过代价也是有的:

  1. 需要设计证书创建流程。如果你对设备有着完全的控制,在设备出厂前就能烧录X509证书到设备中,那么这条路是非常合适的。但是,对于移动设备等无法实现烧录证书的场景,用户名/密码认证或许是更好的选择。
  2. 需要管理证书的生命周期,最好通过PKI(Public-Key-Infrastructure)来管理。
  3. 如果证书泄露了,一定要立即使证书失效。一个选择是使用证书黑名单(Certificate Revocation Lists),另一个选择是提供在线证书状态协议(Online Certificate Status Protocol),方便MQTT代理及时了解证书的状态。

MQTT原生支持X509认证,生成客户证书后再配置一下MQTT代理便可。

首先生成设备密钥:

openssl genrsa -des3 -out client.key 2048

然后为准备一个设备认证注册请求:

openssl req -out client.csr -key client.key -new

最后通过CA签署这个CSR生成设备证书:

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365

现在配置/etc/mosquitto/mosquitto.conf,确保8883端口的设置如下:

listener 8883
cafile /etc/mosquitto/tls/ca.crt
certfile /etc/mosquitto/tls/server.crt
keyfile /etc/mosquitto/tls/server.key
require_certificate true

重启Mosquitto服务就可以用以下命令订阅和发布消息了,当然所有消息都由TLS加密,可以无忧无虑地传递私密信息啦:

mosquitto_sub -h host -p 8883 -t 'topic' --cafile ca.crt --cert client.crt --key client.key
mosquitto_pub -h host -p 8883 -t 'topic' -m '95' --cafile ca.crt --cert client.crt --key client.key

可以看到,X509同时提供了完善的加密和验证,只是证书的生命周期管理的代价要比用户名密码高一些。

授权

授权是对资源的访问权限。继续拿机场做例子,在使用护照认证了用户之后,系统会根据预定决定用户可以上特定时间和班次的飞机,这就是授权。

对MQTT而言意味着对主题的订阅和发布权限。Mosquitto内置了基本的授权,那就是基于Access Control List的授权。

由于ACL是基于特定用户的,所以需要使用用户名密码认证方式。然后,在/etc/mosquitto/mosquitto.conf中指定ACL文件:

acl_file /etc/mosquitto/acl

在这个ACL文件便可以指定用户的读写权限,比如下面便可以授权用户tom读写指定主题的权限:

user tom
topic readwrite company/building/floor/#

Mosquitto只提供了基本的基于ACL的授权,更高级的基于RBAC的授权可能需要通过插件的形式自行开发了。

体系

在MQTT项目实施时,还可以考虑通过防火墙保护MQTT代理:

  • 仅允许相关的流量传递到MQTT代理,比如UDP、ICMP等流量可以直接屏蔽掉。
  • 仅允许相关端口的流量传递到MQTT代理,比如MQTT over TCP使用1883,而MQTT over TLS使用8883。
  • 仅允许某些IP地址段来访问MQTT代理,如果业务场景允许的话。

 

 

 

 

0
1
分享到:
评论

相关推荐

    MQTT协议-有这一篇就够了

    MQTT协议的安全性: * MQTT协议使用用户名和密码进行身份验证 * MQTT协议使用加密技术来保护数据的隐私 MQTT协议的应用场景: * 机器与机器的通信(M2M) * 物联网(IoT)环境 * 智能家居系统 * 工业自动化系统 ...

    MQTT协议-CN-注释.pdf

    MQTT协议考虑到了安全性问题,并提供了一些机制来保护通信安全,比如: - 使用SSL/TLS加密传输数据。 - 支持认证机制,允许使用用户名和密码进行身份验证。 ### 使用WebSocket 为了更好地适应现代互联网环境,...

    MQTTPacket_mqtt-packet_mqtt协议栈_mqtt_

    MQTT协议栈是实现MQTT协议的核心组件,它包括了处理MQTT报文(packets)的各种功能。 标题中的"MQTTPacket_mqtt-packet_mqtt协议栈_mqtt_"可能是指一个特定的MQTT协议栈实现,其中"MQTTPacket"可能是该实现中的关键...

    paho.mqtt.-master.tar.gz

    通过深入理解Paho MQTT库和MQTT协议,开发者可以构建高效、可靠的物联网解决方案,充分利用MQTT的低开销和高可用性特性。在解压并编译`paho.mqtt.-master.tar.gz`后,你可以开始探索其源代码,了解其内部实现,甚至...

    mqtt-v5_MQTT-V5.0_mqtt_MQTT5.0协议文档_mqtt最新.zip

    1. **协议结构**:MQTT协议基于TCP/IP协议栈,确保数据的可靠传输。它采用客户端-服务器架构,其中客户端可以是设备、应用程序或服务,而服务器称为broker,负责接收、存储和转发消息。 2. **发布/订阅模式**:MQTT...

    tcp封装移植到MQTT协议-ubuntu

    本资源将TCP协议封装到MQTT协议中,使得在Ubuntu操作系统上能够实现TCP到MQTT的转换,这对于在资源有限的设备上进行高效的数据通信具有重要意义。 TCP(Transmission Control Protocol)是一种面向连接的、可靠的、...

    MQTT-3.1.1-CN.pdf

    6. **相关文档**:MQTT协议与其他技术文档相关联,如与NIST网络安全框架的集成,强调了在保障网络安全方面的考虑。 MQTT的使用场景广泛,从环境监测、智能家居、工业自动化到远程医疗等,其灵活性和高效性使得它...

    MQTT 协议 5.0 中文版

    * MQTT 和 NIST 网络安全框架 1.0 版 MQTT 协议 5.0 的发布历史包括: * 2017 年 10 月 26 日,MQTT 协议 5.0 公开评审草案中文版发布 * 2014 年 10 月 29 日,MQTT 协议 3.1.1 版本发布 MQTT 协议 5.0 的主要...

    MQTT 协议 3.1.1 中文版

    1. MQTT 和 NIST 网络安全框架 1.0 版 2. MQTT 技术委员会 MQTT 协议的实现 MQTT 协议可以在 TCP/IP 或其它提供了有序、可靠、双向连接的网络连接上运行。它可以在各种设备上实现,包括计算机、手机、机器等。 ...

    STM32F4_MQTTdemo-master

    MQTT协议本身不提供加密,但可以通过SSL/TLS等安全协议进行加密,确保数据传输的安全性。 9. **编译和烧录**:开发完成后,代码需要通过IDE(如Keil MDK或GCC ARM)编译,并通过编程器烧录到STM32F4芯片中。 10. *...

    MQTT协议 v3.1.1 - 官方标准文档(英文原版).doc

    MQTT协议的核心组成部分包括客户端(Client)、服务器(Broker)和主题(Topic)。客户端通过TCP/IP连接与服务器建立通信,发布(Publish)消息到特定主题或者订阅(Subscribe)特定主题以接收消息。主题是消息路由...

    基于MQTT协议实现(推送系统)

    在本文中,我们将深入探讨如何基于MQTT协议实现一个推送系统。 首先,理解MQTT协议的基本概念至关重要。MQTT采用发布/订阅模型,其中客户端可以作为发布者(Publisher)发送消息,也可以作为订阅者(Subscriber)...

    MQTTnet-master (1)_HTTP_socketserver_socket_MQTTnet_httpserver_源

    MQTT协议由客户端和服务器构成,客户端可以是发布者或订阅者,服务器负责消息的路由和传递。 **2. MQTTnet** MQTTnet是一个.NET开源库,允许开发者在.NET平台上快速构建MQTT服务器和客户端。它提供了高效且易于使用...

    paho.mqtt.c-1.3.5.tar.gz

    **MQTT协议详解** MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是一种轻量级的发布/订阅消息协议,最初由IBM设计,主要用于远程位置、低带宽、高延迟或不可靠网络环境下的设备通信。MQTT协议以...

    paho.mqtt.c-master.zip_C++ MQTT_C++实现MQTT_drawvvw_mqtt_mqtt c语言

    本篇文章将深入探讨如何使用C++语言来实现MQTT协议,主要基于开源库paho.mqtt.c。 1. **MQTT协议介绍** MQTT协议设计的目标是低带宽、低功耗、高可靠性的实时通信,采用发布/订阅模型,确保消息的一对多传递。它...

    MQTT---HiveMQ源码详解(十三)Netty-MQTT消息、事件处理(源码举例解读).pdf

    HiveMQ 是一个高性能的 MQTT 服务器,它利用了 Netty 的网络库来处理 MQTT 协议的通信。在本文档中,我们将深入到 MqttConnectHandler 类,了解 MQTT 客户端连接时的认证流程。 MqttConnectHandler 是 ...

    mqtt-jmeter-master.7z

    1. **发布/订阅模式**:MQTT协议基于发布/订阅模型,允许消息发布者与订阅者之间进行异步通信,不直接交互。 2. **主题(Topic)**:消息是根据主题进行路由的,订阅者通过指定主题来接收感兴趣的消息。 3. **QoS ...

    使用paho-mqtt-c做的mqtt通讯

    MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息协议,常用于物联网(IoT)设备之间的通信。在本项目中,我们利用了`paho-mqtt-c`库来实现MQTT通信。`paho-mqtt-c`是Eclipse Paho项目的一...

    MQTT协议完整中文版版.pdf

    MQTT协议采用客户端-服务器架构,并基于发布/订阅模型,其中客户端向服务器发送消息,服务器根据主题将消息分发给感兴趣(订阅了相关主题)的客户端。MQTT协议的英文全称和缩写经常在文档、论坛和开发者交流中被提及...

Global site tag (gtag.js) - Google Analytics