- 物联网
- 消息队列
- 后端
- 网络/通信
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
导读
Mosquitto 2.0.16 于 2023-08-16 发布,是一个以安全修复为主、兼顾稳定性缺陷修复的维护版本,一次性修复了 CVE-2023-28366、CVE-2023-0809、CVE-2023-3592 三个安全漏洞,并同步修复了 Broker、客户端库(libmosquitto)、命令行客户端(mosquitto_pub/mosquitto_sub)与应用工具(mosquitto_passwd、mosquitto_ctrl)中的一批缺陷。本文以官方发布公告为骨架,结合仓库源码与完整 ChangeLog.txt 逐条解析每项修复的成因、影响范围与验证依据,帮助运行 1.3.2~2.0.15 版本的部署方评估升级必要性,并指导升级前后的配置与运维动作。
版本概览:为什么 2.0.16 值得优先升级
官方发布公告将该版本定性为security and bugfix release(安全与缺陷修复版本)。从 ChangeLog.txt 可以看到,该版本共包含 7 项安全相关修复、16 项 Broker 修复、3 项客户端库修复、2 项客户端工具修复与 2 项应用工具修复,密度和覆盖面在 2.0.x 维护序列中相当突出。
三个 CVE 分别覆盖了 QoS 2 消息处理、恶意初始报文、v5 Will 消息属性解析三条攻击路径,且均为可远程触发的资源耗尽(内存泄漏/过量分配)型漏洞,对长期运行的公开 Broker 影响尤为直接。任何运行在1.3.2~2.0.15之间的版本都应优先评估升级。
| 条目 | 说明 |
|---|---|
| 发布时间 | 2023-08-16 |
| 版本性质 | 安全修复 + 缺陷修复(security and bugfix release) |
| 安全漏洞 | CVE-2023-28366、CVE-2023-0809、CVE-2023-3592 |
| 受影响范围 | 1.3.2 ~ 2.0.15(视具体 CVE 而定,详见下文) |
| 仓库依据 | ChangeLog.txt、www/pages/security.md |
安全修复:三个 CVE 逐一拆解
CVE-2023-28366:QoS 2 重复消息 ID 引发内存泄漏
漏洞描述:客户端反复发送相同消息 ID 的 QoS 2 消息,但从不回应 Broker 下发的 PUBREC 报文,导致 Broker 内存持续泄漏。
受影响版本:1.3.2 至 2.0.15(含),在 2.0.16 修复(见 www/pages/security.md)。
源码视角:QoS 2 的完整交付依赖 PUBLISH → PUBREC → PUBREL → PUBCOMP 四步握手,每一份未完成的 QoS 2 消息都会以 inflight 状态驻留在 Broker 内存中。从 src/context.c 可以看到,每个客户端连接的入站(msgs_in)与出站(msgs_out)消息队列都受inflight_maximum/inflight_quota约束,其默认值来自配置项max_inflight_messages = 20(见 src/conf.c)。攻击者只需让大量"只发 PUBLISH、不回 PUBREC"的连接停留在线,Broker 便会在每个连接上持续累积未完成状态,从而耗尽内存。2.0.16 修复了这种同 ID 消息反复提交场景下的泄漏路径,同时max_inflight_messages(默认 20,上限 65535,见 src/conf.c)与max_inflight_bytes(默认 0,即不限制)依然是运维层面控制 inflight 水位的关键旋钮。
CVE-2023-0809:恶意初始报文导致过量内存分配
漏洞描述:针对"并非 CONNECT 报文"的恶意初始报文,Broker 会基于其内容分配过量内存。
受影响版本:1.5.0 至 2.0.15(含),在 2.0.16 修复(见 www/pages/security.md)。
源码视角:MQTT 连接建立后,Broker 需要先读取第一个报文并判断其类型。对非 CONNECT 报文,Broker 会按报文头携带的长度字段进行读入与解析,攻击者可通过伪造的长度值诱导 Broker 预先分配远超实际需要的内存,形成资源耗尽。2.0.16 对该分配路径增加了约束,避免基于不可信报文头进行过量分配。
CVE-2023-3592:v5 Will 消息非法属性类型引发内存泄漏
漏洞描述:客户端发送包含非法属性类型的 v5 CONNECT 报文(携带 Will 消息)时,Broker 解析失败后未正确释放已分配内存,造成泄漏。
受影响版本:1.6.0 至 2.0.15(含),在 2.0.16 修复(见 www/pages/security.md)。
源码视角:MQTT v5 的 CONNECT 报文允许携带 Will Properties,Broker 在 src/handle_connect.c 中读取 Will 消息并逐项解析属性。当属性类型非法时,解析流程需进入错误清理路径;2.0.16 修复了该路径上对已分配 Will 相关内存的释放遗漏。
安全加固类修复(非 CVE)
除三个 CVE 外,2.0.16 还包含多项主动安全加固:
- 拒绝 Will 消息发布到
$CONTROL/主题:从 src/handle_connect.c 可以看到,Broker 在 CONNECT 阶段即检查 Will 主题,若以$CONTROL/开头则直接返回MOSQ_ERR_ACL_DENIED拒绝连接。$CONTROL/是 Broker 内部控制主题(如$CONTROL/broker/v1,见 src/broker_control.c 与 src/control.c),此前允许 Will 向其发布意味着攻击者可借遗嘱机制向控制通道注入消息。 - 校验 TLS 证书或 TLS-PSK 身份中的用户名是否为合法 UTF-8:防止通过证书字段注入畸形用户名绕过认证或触发编码问题。
- 修复加载无效持久化文件时可能崩溃的问题:见下文 Broker 部分。
- 客户端库不再允许单级通配符证书(如
*.com):TLS 证书校验更加严格,避免通配符覆盖范围过宽导致的信任风险。
Broker 修复:稳定性与兼容性细节
运行时行为修复
$SYS消息 60 秒过期问题:修复了$SYS消息在 60 秒后被错误过期、导致不变数值消失的缺陷。$SYS主题是 Broker 自监控统计的载体(对应 src/sys_tree.c),该修复保证了统计值的持续可见。- 保留消息内存未即时释放:修复了部分保留主题内存使用后未被立即清理的问题,降低长期运行的内存占用(保留消息逻辑见 src/retain.c)。
bind_interface选项错误处理:修复了该配置项相关错误路径上的处理缺陷,保证绑定指定网卡失败时能给出正确反馈(配置解析见 src/conf.c)。- 移除断言构建下的守护进程标准流重定向:以无断言(NDEBUG)方式编译并 daemon 化时,stdin/stdout/stderr 未正确重定向的问题得到修复。
- stdout 改为行缓冲模式:Broker 日志输出在管道/重定向场景下不再因全缓冲而延迟落盘,便于
mosquitto -d与日志采集工具的实时对接。
配置与安全默认值修复
- 默认设置不再错误允许 TLS v1.1:修复了默认 TLS 版本设置允许 v1.1 的问题。由于默认值同时影响 Broker(
listener的tls_version配置)与客户端库,升级后请确认依赖旧默认值的存量客户端兼容性(TLS 配置文档见 man/mosquitto.conf.5.xml)。 - Windows 连接数上限 2048 → 8192:修复了 Windows 平台连接数被固定限制在 2048 的问题,在支持的平台上提升至 8192。
- 敏感文件权限告警:Broker 在启动/加载阶段若发现敏感文件(如密码文件、ACL 文件、持久化文件)对全体用户可读/可写,或属主/属组与 Broker 运行身份不一致,将输出警告日志;发布公告明确指出未来版本将直接拒绝打开这些文件,建议升级后立即清理文件权限(如
chown mosquitto:mosquitto并收紧权限位),为后续大版本平滑过渡做准备。 mosquitto_memcmp_const更接近常数时间:用于密码/密钥比较的常数时间比较函数被强化,降低时序侧信道风险(该函数在认证路径中被使用)。- 仅在启用 DLT 日志时注册 DLT:避免在未启用 DLT 日志功能时多余注册,减少日志后端副作用。
持久化与插件修复
- 桥接会话恢复错误:修复了桥接的
cleansession与local_cleansession不匹配时,从持久化恢复后在启动时被错误过期的缺陷。 - dynsec 配置 JSON 加载崩溃:修复了从文件加载动态安全(Dynsec)插件配置时,若角色(role)的
textname或textdescription字段不是字符串类型,可能因 JSON 字符串加载错误而崩溃的问题(相关配置加载逻辑见 plugins/dynamic-security/config.c)。 - dynsec 禁止重复条目:从文件加载配置时不再允许重复的客户端/组/角色,与运行时创建时的行为保持一致(相关校验逻辑见 plugins/dynamic-security/clientlist.c、plugins/dynamic-security/grouplist.c、plugins/dynamic-security/rolelist.c)。
log_dest file配置读取堆溢出:修复了读取损坏配置(包含异常log_dest file指令)时的堆溢出问题,该修复同样属于防御畸形配置输入的加固。
客户端库(libmosquitto)修复
使用 CLOCK_BOOTTIME 追踪时间,解决系统休眠导致的 Keepalive 失效
这是 2.0.16 客户端库最具代表性的改动:当系统支持时改用CLOCK_BOOTTIME时钟追踪时间,解决客户端操作系统休眠(suspend)后无法正确计算 keepalive 实际时间的问题。
从 common/time_mosq.c 可以看到mosquitto_time()的时钟选择逻辑:
#elif _POSIX_TIMERS>0 && defined(_POSIX_MONOTONIC_CLOCK) struct timespec tp; #ifdef CLOCK_BOOTTIME clock_gettime(CLOCK_BOOTTIME, &tp); #else clock_gettime(CLOCK_MONOTONIC, &tp); #endif return tp.tv_sec;CLOCK_BOOTTIME与CLOCK_MONOTONIC的差异在于:单调时钟在系统休眠期间会暂停计时,而 BOOTTIME 会将休眠时间计入。此前客户端休眠后,单调时钟"停表"导致 keepalive 间隔被严重低估,Broker 可能误判客户端失联而主动断开(或客户端实际已超时却未察觉)。改用 BOOTTIME 后,休眠时长被正确计入,keepalive 与连接保活行为在笔记本、嵌入式网关等经常休眠的设备上回归正确。该时钟选择逻辑同样用于 lib/mosquitto.c 中随机数种子生成,保证进程时间戳的全局一致性。
其余客户端库修复
- 默认设置不再错误允许 TLS v1.1:与 Broker 修复同源,保证客户端库与 Broker 的 TLS 默认策略一致(lib/mosquitto.c 中 TLS 相关默认值设置)。
- 慢速 TLS 连接下的高 CPU 占用:修复了 TLS 握手在慢速网络下客户端空转忙轮询导致的高 CPU 问题,改善弱网/慢速 TLS 场景下的功耗与资源占用。
命令行客户端与应用工具修复
Clients(mosquitto_pub / mosquitto_sub / mosquitto_rr)
- mosquitto_sub JSON 输出的 topic-alias 属性值错误:修复了
mosquitto_sub -F的 JSON 输出格式中 topic-alias 属性值不正确的问题(输出格式化实现见 client/sub_client_output.c)。 - TLS 证书校验失败时的提示信息更清晰:修复了证书验证失败时易产生误解的提示文案(相关 TLS 处理见 client/client_shared.c)。
Apps(mosquitto_passwd / mosquitto_ctrl)
- mosquitto_passwd 使用 mkstemp() 创建备份文件:密码文件修改时的备份文件改用
mkstemp()创建,消除临时文件名可预测带来的符号链接攻击面(实现见 apps/mosquitto_passwd/mosquitto_passwd.c)。 mosquitto_ctrl dynsec init拒绝覆盖已存在文件:初始化动态安全配置文件时,若目标文件已存在则拒绝覆盖,且该检查是无竞态(race-condition free)的,避免两个管理进程同时初始化时互相覆盖(实现见 apps/mosquitto_ctrl/dynsec.c)。
升级与运维建议
升级必要性评估
结合 www/pages/security.md 的受影响版本矩阵:
| CVE | 受影响版本 | 触发条件 |
|---|---|---|
| CVE-2023-28366 | 1.3.2 ~ 2.0.15(含) | 客户端发送重复 ID 的 QoS 2 消息且不回应 PUBREC |
| CVE-2023-0809 | 1.5.0 ~ 2.0.15(含) | 任意客户端发送非 CONNECT 的恶意初始报文 |
| CVE-2023-3592 | 1.6.0 ~ 2.0.15(含) | 客户端发送含非法属性类型的 v5 Will 消息 |
三个漏洞均无需认证即可远程触发(Broker 在认证之前便需解析 CONNECT 报文),因此凡是暴露在公网或不可信网络中的 Broker,均应尽快升级至 2.0.16 或更高版本。从源码结构看,这些漏洞与 MQTT 报文解析、inflight 队列管理、Will 属性解析等 Broker 核心路径直接相关,无法通过配置规避。
升级后建议执行的检查项
- 清理敏感文件权限:2.0.16 已对权限不当的敏感文件输出告警日志,请检查
/var/lib/mosquitto/(持久化文件)、密码文件、ACL 文件、动态安全配置文件的属主与权限位,因为未来版本将直接拒绝打开这些文件。 - 复核 TLS 配置:确认 Broker 与客户端均显式配置了 TLS 版本(如
tls_version tlsv1.2或tlsv1.3,参见 man/mosquitto.conf.5.xml),不要依赖已被收紧的旧默认值;同时检查所用证书是否符合"禁止单级通配符"的新校验规则(*.com这类证书将被拒绝)。 - 复核桥接配置:确认各桥接的
cleansession与local_cleansession设置一致或符合预期,避免持久化恢复后的会话被过早过期(桥接配置说明见 mosquitto.conf 与 src/bridge.c)。 - 回归 QoS 2 与 Will 场景:重点回归测试 QoS 2 消息收发、带属性(properties)的 v5 Will 消息,以及
$CONTROL/控制主题相关插件场景。 - 关注 inflight 水位:若此前曾受 QoS 2 资源占用困扰,可结合
max_inflight_messages(默认 20)与max_inflight_bytes(默认 0,即不限制)审视队列水位配置(src/conf.c)。
小结
Mosquitto 2.0.16 是一个"小而关键"的维护版本:三个可远程触发的内存类 CVE 覆盖了 QoS 2、初始报文与 v5 Will 三条常见攻击路径,$CONTROL/Will 拦截与证书校验收紧进一步压缩了攻击面;同时,CLOCK_BOOTTIME 时钟切换解决了真实设备上长期存在的休眠场景 keepalive 失效问题,Windows 连接上限提升与 daemon 日志重定向等修复也让生产部署更稳。对于运行 1.3.2~2.0.15 的部署,本版本应视为优先级最高的升级目标;升级后按上文清单复核文件权限、TLS 与桥接配置即可平滑落地。
- 物联网
- 消息队列
- 后端
- 网络/通信
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
相关推荐
Mosquitto 2.0.16 版本解析:CVE 安全修复、Broker 与客户端库关键改进全解读
Mosquitto 2.0.16 版本解析:CVE 安全修复、Broker 与客户端库关键改进全解读 本篇文章以 Eclipse Mosquitto 官方发布说
后端消息队列消息路由Mosquitto 2.0.15 发布详解:安全修复、Broker 关键缺陷与客户端库改进全解析
Mosquitto 2.0.15 发布详解:安全修复、Broker 关键缺陷与客户端库改进全解析 本文基于官方发布公告与仓库源码,系统梳理 Mosquitto
后端消息队列消息路由Eclipse Mosquitto 1.4.13 发布详解:CVE 安全修复与 Broker/客户端稳定性改进
Eclipse Mosquitto 1.4.13 发布详解:CVE 安全修复与 Broker/客户端稳定性改进 本文基于仓库 www/posts/2017/07
后端消息队列消息路由
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考