2、安全威胁分析:MQTT常见攻击类型
MQTT 协议设计之初,主要考虑的是低带宽、低功耗的物联网场景。说实话,那时候大家对安全的重视程度远不如现在。我最早接触 MQTT 是在一个智能路灯项目里,当时觉得协议轻量好用,结果上线不到一周就被黑了——嗯,从那以后我再也不敢轻视 MQTT 的安全问题了。
这一节,我们来拆解 MQTT 最常见的四类攻击。你想想看,攻击者能怎么搞你?无非就是:偷听你说话、让你说不了话、假装是你、或者直接闯进门。下面我们一个一个说。
核心观点:MQTT 本身不提供任何内置安全机制。所有安全防护都需要在传输层、认证层和应用层自行构建。这不是协议缺陷,而是设计取舍——但你必须知道怎么补。
2.1 中间人攻击
中间人攻击,说白了就是攻击者插在你和 Broker 之间,偷听甚至篡改你们的通信内容。MQTT 默认走明文 TCP,数据包在网络上几乎是裸奔的。
我记得有一次帮客户做安全审计,他们用的 MQTT 端口是默认的 1883,连 TLS 都没开。我用 Wireshark 抓了五分钟包,就把所有传感器上报的温度、湿度、设备位置看得一清二楚。更可怕的是,我还能伪造发布消息——你想想看,如果攻击者篡改了一个工业阀门的控制指令,后果是什么?
⚠ 避坑指南:我曾经见过一个团队,只在生产环境开了 TLS,测试环境一直用明文。结果测试环境的 Broker 暴露在公网上,被扫描到后直接抓包拿到了设备凭证。记住:任何暴露在公网上的 MQTT 端点都必须启用 TLS,不分环境。
中间人攻击的常见手法包括:
- ARP 欺骗:在局域网内伪造网关 MAC,劫持客户端到 Broker 的流量
- DNS 劫持:把 Broker 域名解析到攻击者控制的服务器
- SSL 剥离:强制将 TLS 连接降级为明文(如果客户端配置不当)
- 证书伪造:使用自签名证书冒充合法 Broker
💡 我的建议:客户端必须验证 Broker 的证书,不要设置 tls_insecure_set(true)。我见过太多人为了方便调试,把这个选项留在了生产代码里——这等于把门锁拆了。
2.2 拒绝服务攻击
拒绝服务攻击的目标很简单:让 Broker 无法正常服务。MQTT 的轻量特性反而让它更容易被滥用。为什么?因为建立一条 MQTT 连接的成本很低,但 Broker 处理连接的开销却不小。
我参与过一个智慧城市项目,上线第一天就遭遇了 DoS 攻击。攻击者用几十台肉鸡同时发起 CONNECT 请求,每个连接都带着一个超大的 Client ID。Broker 的内存直接被打满,所有合法设备全部掉线。嗯,那天晚上我们团队通宵加了限流和连接速率控制。
常见的 MQTT DoS 攻击手段:
| 攻击类型 | 攻击方式 | 影响 | 防护手段 |
|---|---|---|---|
| CONNECT 洪泛 | 短时间内发送大量 CONNECT 报文 | 耗尽 Broker 连接池 | IP 速率限制、连接数上限 |
| 遗嘱消息炸弹 | 设置超大 Will Message,然后强制断开 | Broker 存储和转发压力剧增 | 限制 Will Message 大小 |
| 主题订阅爆炸 | 单个客户端订阅数千个主题 | Broker 路由表膨胀 | 限制单客户端订阅数 |
| QoS 2 滥用 | 大量发送 QoS 2 消息但不完成流程 | Broker 保留大量会话状态 | 设置 QoS 2 消息超时 |
关键配置示例:Mosquitto Broker 的 DoS 防护配置片段
# 限制客户端连接速率
connection_messages true
max_connections 1000
per_listener_settings true
# 限制单个客户端
max_client_id_length 64
max_inflight_messages 20
max_queued_messages 100
# 限制消息大小
max_packet_size 1048576 # 1MB
# 限制订阅数量
max_subscriptions_per_client 50
2.3 身份伪造
身份伪造,就是攻击者冒充合法设备与 Broker 通信。MQTT 的 Client ID 是唯一标识,但如果 Broker 不做认证,任何人都可以用任意 Client ID 连接。
我遇到过最典型的案例:某智能家居厂商的 MQTT Broker 只靠 Client ID 区分设备,没有密码认证。攻击者抓包拿到一个设备的 Client ID 后,直接连上 Broker 订阅了所有主题——全屋设备的状态、控制指令一览无余。更离谱的是,他还能发送开锁指令。
身份伪造的常见场景:
- Client ID 劫持:攻击者使用与合法设备相同的 Client ID 连接,Broker 会踢掉原有设备(MQTT 协议默认行为)
- 凭证暴力破解:对用户名/密码进行字典攻击
- Token 窃取:从设备固件或配置文件中提取 JWT Token 或 API Key
- 会话重放:捕获合法的 CONNECT 报文,直接重放给 Broker
⚠ 注意:MQTT 3.1.1 协议规定,如果两个客户端使用相同的 Client ID 连接,Broker 会断开前一个连接。攻击者可以利用这个机制实现「设备踢下线」攻击。我个人建议在生产环境中启用 Client ID 前缀校验或结合证书绑定。
2.4 未授权访问
未授权访问,指的是攻击者虽然连上了 Broker,但访问了本不该访问的主题。这通常是因为 ACL(访问控制列表)配置不当或根本没配。
说实话,我审计过的 MQTT 项目里,超过一半的 Broker 没有配置 ACL。默认配置下,任何客户端都可以订阅任何主题、发布到任何主题。你想想看,如果一个温度传感器能发布到控制指令的主题,或者一个手机 App 能订阅所有设备的管理主题,那不乱套了?
未授权访问的典型表现:
- 订阅越权:设备 A 订阅了设备 B 的私有主题,获取敏感数据
- 发布越权:普通设备向系统控制主题发布伪造指令
- 通配符滥用:使用
#或+通配符订阅整个主题树 - 系统主题泄露:访问
$SYS/系列主题获取 Broker 内部状态
💡 我的经验:ACL 配置要遵循最小权限原则。每个设备只允许发布和订阅它业务需要的主题。我曾经帮一个工厂做改造,把原来「全部允许」的 ACL 改成了基于设备角色的细粒度控制,安全事件直接降为零。
下面是一个 Mosquitto 的 ACL 配置示例:
# 只允许 sensor-001 发布传感器数据
user sensor-001
topic write sensor/001/temperature
topic write sensor/001/humidity
topic read command/001/#
# 只允许 admin 客户端管理系统主题
user admin
topic read $SYS/#
topic write command/#
# 拒绝所有其他访问
user anonymous
topic deny #
2.5 攻击链与防护思路
实际攻击中,这四类威胁往往不是孤立出现的。攻击者可能先通过中间人攻击窃取凭证,然后进行身份伪造,再实施未授权访问,最后发起 DoS 攻击掩盖痕迹。
我个人习惯用一张表来梳理防护优先级:
| 优先级 | 威胁 | 最低防护要求 | 推荐方案 |
|---|---|---|---|
| P0 | 中间人攻击 | 启用 TLS | TLS 1.3 + 证书双向验证 |
| P1 | 身份伪造 | 用户名/密码认证 | 证书认证 + JWT |
| P2 | 未授权访问 | 基础 ACL | 基于角色的细粒度 ACL |
| P3 | 拒绝服务攻击 | 连接数限制 | 速率限制 + 资源配额 |
一句话总结:MQTT 本身不设防,安全全靠外围补。传输层上 TLS,认证层上证书,授权层上 ACL,再加一层限流和监控——做到这四步,你的 MQTT 系统才算有了基本的安全底线。