- 物联网
- 消息队列
- 后端
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
导读
Mosquitto 1.6.10 是 Eclipse Mosquitto 于 2020 年 5 月发布的一个 bugfix(缺陷修复)版本,不包含新功能,核心目标是提升 broker、客户端库与构建体系的稳定性与兼容性。本文以官方发布说明为主体,结合当前仓库源码(src/、apps/mosquitto_passwd/、lib/等)逐条解析 1.6.10 的修复内容、背后涉及的底层机制与配置文件写法,帮助读者理解"错误前置校验、密码文件原子更新、OpenSSL 3.0 兼容"等问题的来龙去脉,并掌握对应的升级与验证方法。
一、版本定位与升级背景
1.6.10 属于 1.6.x 系列的第 10 个补丁版本(发布说明原文:"Mosquitto 1.6.10 has been released, this is a bugfix release.")。该版本聚焦于三类问题:
- 配置/桥接可靠性:把桥接 topic 前缀与 pattern 的组合校验从"运行时失败"提前到"配置解析阶段",同时修复 SIGHUP 信号导致的会话过期时间被错误延长的行为。
- 数据一致性:修复
mosquitto_passwd -b无法正确更新已有用户密码的问题,以及加载不同版本持久化文件时的版本检查缺陷。 - 生态兼容性:为当时即将普及的 OpenSSL 3.0 做兼容适配,修复 Windows 平台下
mosquitto_sub格式化输出、BSD 平台下sed脚本等一系列构建/运行问题。
适用前提:本仓库当前主分支已演进到更高的版本线(源码结构包含 MQTT v5、动态安全插件等 1.6 之后的功能),本文涉及的修复点均以 1.6.10 发布说明为基准,并结合仓库源码印证其实现原理。
二、Broker 端修复详解
1. 桥接 topic prefix + pattern 组合:配置期前置校验
发布说明原文:"Report invalid bridge prefix+pattern combinations at config parsing time rather than letting the bridge fail later."(Issue #1635)
这是本次修复中最具架构意义的改动。在 1.6.10 之前,桥接配置中topic指令如果写入了不合法的前缀(prefix)与通配符 pattern 组合,错误不会在mosquitto -c mosquitto.conf解析阶段暴露,而是等到桥接连接建立、实际进行 topic 重映射时才失败,导致问题难以定位。
从当前仓库源码可以确认这一校验逻辑的完整链路:
- 配置解析入口位于 src/conf.c,处理
topic指令时按topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]语法解析方向(out/in/both)、QoS(0–2)与 local/remote 前缀,随后调用bridge__add_topic(); - src/bridge_topic.c 中的
bridge__add_topic()先对 local/remote 前缀做mosquitto_pub_topic_check()校验,再对topic为空串但未同时给出两个前缀的"非法 remapping"情况直接报Error: Invalid bridge remapping.; - 关键校验集中在
bridge__create_prefix()(src/bridge_topic.c):它会把前缀与 pattern 拼接成完整主题(snprintf(*full_prefix, len, "%s%s", prefix, topic)),再调用mosquitto_sub_topic_check()验证拼接结果是否为合法订阅主题,非法时输出:
Error: Invalid bridge topic local prefix and pattern combination '<prefix+pattern>'.并返回MOSQ_ERR_INVAL,使配置解析直接失败、broker 拒绝启动,而不再等到桥接运行期才暴露问题。
配置示例(对应topic指令的标准写法,可用于验证该修复行为):
# 合法:local 前缀 + out 方向 + QoS 1 topic sensors/out/# out 1 local/ remote/ # 非法(示例,勿直接使用):前缀或拼接结果不符合主题规则时, # 1.6.10 起会在启动时直接报错退出 # topic '#' out 0 local/ remote/需要说明的是,prefix 与 pattern 组合的合法性最终仍以mosquitto_sub_topic_check()(订阅主题校验)为准,#通配符必须位于主题末尾等规则均由此函数统一裁决。
2. mosquitto_passwd -b 批量模式更新密码修复
发布说明原文:"Fixmosquitto_passwd -bnot updating passwords for existing users correctly. Creating a new user with-bworked without problem."(Issue #1664)
-b(batch)模式允许在命令行直接携带密码,免去交互输入,常用于脚本化运维。1.6.10 修复的是:-b新建用户正常,但更新已有用户的密码时行为不正确。
结合 apps/mosquitto_passwd/mosquitto_passwd.c 源码可还原其机制:
- 非
-c(不新建文件)时,程序以r+t打开密码文件,先通过create_backup()生成passwordfile.backup.XXXXXX临时备份(L354-L379),再创建临时文件写入新内容; update_pwuser()(L306-L324)调用pwfile_iterate()逐行遍历,回调update_pwuser_cb()(L288-L304):匹配到目标用户时写入新密码哈希并置helper->found = true,未匹配的行原样保留;遍历结束后若found为真打印Updating password for user %s,否则打印Adding password for user %s并追加新行;- 最后通过临时文件替换原文件完成原子更新。整个"先备份、再逐行重写、最后替换"的流程保证了密码文件的完整性。
命令行用法(当前源码支持的完整形态,L112-L122):
# 交互模式创建/更新 mosquitto_passwd [-H argon2 | -H sha512-pbkdf2] [-c | -D] passwordfile username # 批量模式(-b):新建或更新 mosquitto_passwd [-H argon2 | -H sha512-pbkdf2] [-c] -b passwordfile username password # 把明文密码文件升级为哈希格式 mosquitto_passwd -U passwordfile参数速查:-c新建密码文件(与-D/-U互斥);-D删除用户;-H指定哈希算法(argon2id、sha512-pbkdf2、sha512);-I指定迭代次数;-b为批量模式。另外注意用户名校验规则(L391-L414):用户名不得包含控制字符、不得包含:,长度须小于 65536 字符。
3. 拒绝连接时的内存泄漏修复
发布说明原文:"Fix memory leak when connecting clients rejected."
当 broker 拒绝客户端连接(如鉴权失败、协议违规、达到连接上限)时,连接上下文(struct mosquitto相关分配的内存)存在泄漏路径。该修复确保所有拒绝分支统一走释放逻辑,避免长运行 broker 因频繁被拒绝连接而累积内存。
说明:broker 端的连接上下文管理集中在 src/context.c 与 src/handle_connect.c,1.6.10 的修复属于缺陷修复性质,仓库当前版本已包含更完整的上下文生命周期管理。
4. SIGHUP 重载不再延长已断开客户端的会话过期时间
发布说明原文:"Don't disconnect clients that are already disconnected. This prevents the session expiry being extended on SIGHUP."(Issue #1521)
SIGHUP用于触发 broker 配置热重载。旧版本在重载流程中对"已断开客户端"重复执行断开操作,导致会话过期时间(session expiry)被顺延。1.6.10 增加"已断开即跳过"判断,保证重载不会意外延长离线会话的保留时长,从而让按session_expiry_interval配置的清理节奏保持可预期。
5. OpenSSL 3.0 兼容支持
发布说明原文(Broker 与 Client library 两处均提及):"Fix support for openssl 3.0."
OpenSSL 3.0 引入了全新的 Provider 架构与 API 变化(如OPENSSL_init_crypto初始化方式、废弃大量低级 API)。1.6.10 在 broker 与客户端库两侧同步适配,保证在启用 TLS 的部署环境中可无缝升级 OpenSSL 版本。可对照 apps/mosquitto_passwd/mosquitto_passwd.c 中的条件初始化代码(OPENSSL_VERSION_NUMBER与OPENSSL_API_COMPAT分支),理解该版本为兼容新旧 OpenSSL 所采用的防御式写法。
6. 持久化文件版本检查修复
发布说明原文:"Fix check when loading persistence file of a different version than the native version."(Issue #1684)
broker 持久化文件(默认mosquitto.db)带版本号。旧版本在加载"与当前编译版本不一致"的持久化文件时版本检查逻辑存在缺陷,可能导致误读或崩溃。1.6.10 修正版本比对路径,加载前严格校验版本,拒绝不匹配的数据库文件。相关读取逻辑可参阅 src/persist_read.c 及 src/persist_read_v234.c、src/persist_read_v5.c 等多版本读取器。
7. 无 epoll 平台桥接重连断言崩溃修复
发布说明原文:"Fix possible assert crash associated with bridge reconnecting when compiled without epoll support."(Issue #1700)
Linux 下默认使用 epoll 事件多路复用(src/mux_epoll.c),BSD/macOS 使用 kqueue(src/mux_kqueue.c),其他平台回退到 poll(src/mux_poll.c)。在未启用 epoll 的编译环境下,桥接断线重连会触发断言失败(assert crash)。1.6.10 修复该路径,保证跨平台编译时桥接重连稳定。
三、客户端库(libmosquitto)修复详解
1. 意外的 PUBACK/PUBREL/PUBCOMP 不再视为致命错误
发布说明原文:"Don't treat an unexpected PUBACK, PUBREL, or PUBCOMP as a fatal error."(Issue #1629)
MQTT QoS 1/2 流程中,客户端应只对与未完成报文匹配的 PUBACK(QoS 1 确认)、PUBREL/PUBCOMP(QoS 2 两阶段)作出响应。旧版本若收到与本地状态不匹配的意外确认包,会直接按致命错误处理并断开连接。1.6.10 改为忽略这类冗余/重复的确认包,提升对端行为不规范的兼容性。相关报文处理位于 lib/handle_pubackcomp.c、lib/handle_pubrel.c 与 lib/read_handle.c。
2. mosquitto_lib_init/cleanup 重复调用的内存泄漏修复
发布说明原文:"Fix memory leaks from multiple calls tomosquitto_lib_init()/mosquitto_lib_cleanup()."(Issue #1691)
libmosquitto 的全局初始化/清理函数要求成对调用。旧版本在多次交替调用mosquitto_lib_init()与mosquitto_lib_cleanup()的场景下存在资源泄漏(如线程相关、OpenSSL 初始化相关资源)。1.6.10 修复引用计数/状态管理,使重复调用保持内存安全。入口位于 lib/mosquitto.c。
3. Windows 下 mosquitto_lib_init 返回值文档修正
发布说明原文:"Fix documentation on return code ofmosquitto_lib_init()for Windows."(Issue #1690)
mosquitto_lib_init()的返回值在 Windows 与 POSIX 平台存在差异,1.6.10 同步修正了头文件与 man 文档中的描述,避免 Windows 开发者误用返回值判断。可参阅 include/mosquitto.h 中mosquitto_lib_init的声明与注释。
四、命令行客户端与构建体系修复
1. mosquitto_sub %j/%J 在 Windows 下的修复
发布说明原文:"Fix mosquitto_sub%jor%Jnot working on Windows."(Issue #1674)
mosquitto_sub -F格式化输出支持%j(JSON 格式 payload)与%J(带主题的 JSON 格式 payload)。旧版本这两个格式符在 Windows 平台不可用,1.6.10 修复其平台相关实现。对应实现位于 client/sub_client_output.c。
2. 低于 C99 标准构建的兼容修复
发布说明原文:"Various fixes for building with below C99 support."(Issue #1622)
部分旧编译器/嵌入式工具链默认不启用 C99(如for循环内声明变量等语法受限)。1.6.10 修正相关源码写法,使项目在 C89 风格的编译环境下也能通过编译。
3. BSD 平台 sed 用法修复
发布说明原文:"Fix use of sed on BSD."(Issue #1614)
BSD 的sed -i语法与 GNU sed 存在差异(BSD 要求-i ''形式的备份后缀参数)。1.6.10 调整构建脚本中的 sed 调用,保证 FreeBSD/macOS 等平台可以正常完成构建脚本中的文本处理步骤。
五、升级建议与验证要点
- 升级前备份:若使用持久化功能,升级前备份
mosquitto.db与配置文件;1.6.10 加强了持久化文件版本校验,加载旧版本文件失败时会明确报错,此时可按 src/persist_read.c 中的版本处理逻辑确认文件来源。 - 配置自检:升级后立即用
mosquitto -c mosquitto.conf做一次"试启动",让桥接 prefix/pattern 组合等配置错误在启动阶段暴露,而不是等桥接运行失败。 - 密码文件回归测试:用
mosquitto_passwd -b pwfile user newpass更新已有用户密码,再尝试以新密码连接 broker,验证 1.6.10 的修复生效;同时确认生成的pwfile.backup.*备份文件存在。 - TLS 环境:若使用 OpenSSL 3.0,升级后执行一次带 TLS 的发布/订阅测试(可参照 test/ssl 下的测试脚本与证书生成流程),确认 broker 与客户端库的 TLS 握手正常。
六、总结
Mosquitto 1.6.10 虽然是一个 bugfix 版本,但其修复内容覆盖了桥接配置校验、持久化数据一致性、密码文件管理、OpenSSL 3.0 兼容、跨平台构建等对生产部署至关重要的环节。从源码层面看,这些修复大多沉淀为"前置校验 + 原子更新 + 版本兼容"三类模式:桥接 topic 组合错误在解析期即被 src/bridge_topic.c 拦截;密码文件通过备份与逐行重写实现可靠更新;持久化与 TLS 则通过严格的版本/API 兼容检查避免升级风险。对于仍在 1.6.x 系列的部署,1.6.10 是值得尽快落地的稳定化版本。
- 物联网
- 消息队列
- 后端
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
相关推荐
EMQX GreptimeDB 桥接 TLS 密码套件(Cipher Suite)配置支持详解
EMQX GreptimeDB 桥接 TLS 密码套件(Cipher Suite)配置支持详解 EMQX 的 GreptimeDB 数据桥接基于 Rust NI
后端物联网消息队列通信EMQX 修复解析:ssl_opts.ciphers 校验器同时支持 OpenSSL 与 IANA/RFC 两种密码套件命名格式
EMQX 修复解析:ssl_opts.ciphers 校验器同时支持 OpenSSL 与 IANA/RFC 两种密码套件命名格式 导读 本篇文章围绕 EMQX
后端物联网消息队列通信Eclipse Mosquitto 2.0.9 / 1.6.14 / 1.5.11 发布解析:CA 证书校验安全修复与桥接、TLS、队列等关键缺陷修复
Eclipse Mosquitto 2.0.9 / 1.6.14 / 1.5.11 发布解析:CA 证书校验安全修复与桥接、TLS、队列等关键缺陷修复 2.0.
物联网消息队列后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考