- 后端
- 消息队列
- 消息路由
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
Mosquitto 1.1.2(2013-01-30 发布)是一个纯缺陷修复(bugfix)版本,其核心修复点只有一个却事关安全:客户端库中tls_cert_reqs未被默认设置为SSL_VERIFY_PEER,导致客户端通过 TLS 连接 broker 时默认不校验服务器证书。本文将结合当前仓库源码,剖析该缺陷的成因、影响范围、修复后的默认行为,以及开发者如何在代码中显式控制证书校验策略。
版本概览:一次聚焦 TLS 安全的 bugfix 发布
Mosquitto 1.1.2 发布于 2013 年 1 月 30 日,属于 bugfix 系列版本,不包含新功能。仓库中的 ChangeLog.txt 与该发布公告内容完全一致:
1.1.2 - 20130130 ================ # Client library - Fix tls_cert_reqs not being set to SSL_VERIFY_PEER by default. This meant that clients were not verifying the server certificate when connecting over TLS. This affects the C, C++ and Python libraries.这一版本仅修改客户端库(Client library),不涉及 broker 端改动。源码与二进制包可从 Mosquitto 官方下载渠道获取。
缺陷根因:tls_cert_reqs缺失默认值
在 TLS 握手过程中,OpenSSL 通过SSL_CTX_set_verify()设置对端证书的校验策略,其关键参数包括:
| 常量 | 含义 | 安全性 |
|---|---|---|
SSL_VERIFY_PEER | 请求对端证书并验证其签名链与信任锚 | 安全 |
SSL_VERIFY_NONE | 不验证对端证书 | 存在中间人风险 |
1.1.2 之前的客户端库在初始化连接对象时,没有把tls_cert_reqs设置为SSL_VERIFY_PEER。由于该字段在结构体初始化后默认值为 0,而 0 恰好对应SSL_VERIFY_NONE,结果就是:只要客户端通过 TLS 连接 broker,OpenSSL 不会校验服务器证书是否由受信任的 CA 签发。攻击者只需提供一张任意自签证书,就能伪装成目标 broker 对客户端实施中间人(MITM)攻击,窃取或篡改 MQTT 会话中的凭据与业务消息。
为什么默认值 0 会落在"不校验"分支
从当前仓库源码看,TLS 校验策略的判定逻辑位于 lib/net_mosq.c。当加载 CA 之后,代码根据tls_cert_reqs的值选择调用 OpenSSL 的校验模式:
if(mosq->tls_cert_reqs == 0){ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_NONE, NULL); }else{ SSL_CTX_set_verify(mosq->ssl_ctx, SSL_VERIFY_PEER, mosquitto__server_certificate_verify); }可见tls_cert_reqs == 0会直接落入SSL_VERIFY_NONE分支。因此,1.1.2 之前的版本中,只要应用没有主动调用mosquitto_tls_opts_set()指定校验级别,TLS 连接就处于"只加密、不验真"的危险状态——数据传输虽被加密,但服务器身份未被确认。
修复后的默认行为:源码级验证
本次修复的核心动作,就是在客户端库的初始化函数中为tls_cert_reqs显式赋默认值。当前仓库 lib/libmosquitto.c 的初始化代码(位于#ifdef WITH_TLS编译分支内)可以确认:
mosq->tls_cert_reqs = SSL_VERIFY_PEER; mosq->tls_insecure = false;也就是说,修复后所有新建的struct mosquitto连接对象,默认即要求校验证书,且tls_insecure(跳过校验的开关)默认关闭。对应的结构体字段定义在 lib/mosquitto_internal.h:
int tls_cert_reqs;这一初始化发生在连接对象创建阶段(mosquitto__init),早于任何 TLS 握手,因此无论应用后续是否显式设置 TLS 选项,默认的安全行为都能得到保障。
显式控制证书校验的 API 与调用链
除默认值外,开发者仍可通过公开 API 显式调整校验策略。相关接口集中在 lib/options.c:
1.mosquitto_tls_opts_set():设置证书校验级别
函数原型位于 lib/options.c:
int mosquitto_tls_opts_set(struct mosquitto *mosq, int cert_reqs, const char *tls_version, const char *ciphers);其中第一个参数cert_reqs直接写入mosq->tls_cert_reqs:
mosq->tls_cert_reqs = cert_reqs;推荐传入SSL_VERIFY_PEER;同时该函数还负责设置 TLS 版本(默认tlsv1.2)与密码套件列表。传入非法值会返回MOSQ_ERR_INVAL;在未编译WITH_TLS的构建中则返回MOSQ_ERR_NOT_SUPPORTED。
2.mosquitto_tls_insecure_set():谨慎使用的"跳过校验"开关
函数位于 lib/options.c:
int mosquitto_tls_insecure_set(struct mosquitto *mosq, bool value);仅当确需连接使用自签名证书的内部测试环境时,才建议将value设为true;生产环境应保持false。该开关配合默认的SSL_VERIFY_PEER,共同构成客户端证书信任策略的两道防线。
3. 完整调用链
结合 lib/net_mosq.c 可梳理出完整流程:
- 应用调用
mosquitto_tls_set()设置 CA 文件/路径,或启用系统证书(tls_use_os_certs); - TLS 上下文建立后,
net__tls_load_ca()加载信任锚; - 根据
mosq->tls_cert_reqs决定SSL_CTX_set_verify()的校验模式,非 0 时还会注册mosquitto__server_certificate_verify作为校验回调; - 若设置了
tls_pw_callback,同时注册私钥口令回调; - 加载客户端证书链与私钥(
SSL_CTX_use_certificate_chain_file)。
也就是说,修复后的默认SSL_VERIFY_PEER只有在客户端明确配置了 CA(cafile/capath/系统证书)时才真正生效——这也是客户端 TLS 校验的前提条件。
影响范围:C、C++ 与 Python 客户端库
发布公告明确指出该缺陷影响三类客户端库:
- C 库(libmosquitto):缺陷的直接载体,初始化逻辑与 TLS 选项处理均位于 lib/libmosquitto.c 与 lib/options.c;
- C++ 库(libmosquittopp):其实现封装并复用了 C 库的 TLS 选项与连接逻辑,因此底层默认值修复后 C++ 绑定同步受益;
- Python 库:同样基于 libmosquitto 的 TLS 行为,受同一缺陷影响,随本次修复一并解决。
由于修复发生在共享的底层初始化逻辑中,三者的默认行为在 1.1.2 之后保持一致:不显式调用mosquitto_tls_opts_set()时,证书校验默认开启。
实践建议
- 更新到修复版本:凡使用 Mosquitto 1.1.2 之前版本且通过 TLS 连接 broker 的部署,应尽快升级客户端库,否则连接处于不校验服务器证书的状态;
- 显式声明校验级别:即使是修复后的版本,也建议在代码中显式调用
mosquitto_tls_opts_set(mosq, SSL_VERIFY_PEER, NULL, NULL),避免依赖隐式默认值,提升可读性与可维护性; - 正确配置 CA:
SSL_VERIFY_PEER生效的前提是已通过mosquitto_tls_set()指定可信 CA(文件、路径或系统证书),并使用由该 CA 签发的服务器证书; - 测试环境与生产的策略分离:仅对自签名证书的内部测试环境使用
mosquitto_tls_insecure_set(mosq, true),生产环境保持默认校验; - 关注 broker 端配套配置:客户端校验修复后,broker 端应使用有效证书链(参见 mosquitto.conf 中
cafile、certfile、keyfile等 TLS 监听配置),确保双向信任关系完整。
小结
Mosquitto 1.1.2 虽是一个单点修复的 bugfix 版本,但它修正的"TLS 连接默认不校验服务器证书"问题,对 MQTT 客户端安全至关重要。以当前仓库源码为准,修复后的默认行为已固化为tls_cert_reqs = SSL_VERIFY_PEER(见 lib/libmosquitto.c),并在 lib/net_mosq.c 的 TLS 上下文初始化中强制启用SSL_VERIFY_PEER校验。理解这条默认值链路,有助于开发者正确配置 Mosquitto 客户端 TLS 信任策略,避免"加密但不验真"的安全误区。
- 后端
- 消息队列
- 消息路由
【免费下载链接】mosquitto
Eclipse Mosquitto - An open source MQTT broker
相关推荐
Tolaria ADR-0100:用前端合成的 Vault 根行统一文件夹导航模型
Tolaria ADR 0100:用前端合成的 Vault 根行统一文件夹导航模型 Tolaria 的侧边栏文件夹树需要让用户能一键回到 Vault 根目录、浏
后端消息队列消息路由SafeLine 忘记或泄露数据库密码时如何用管理脚本重置 POSTGRES_PASSWORD 并重启容器?
SafeLine 忘记或泄露数据库密码时如何用管理脚本重置 POSTGRES_PASSWORD 并重启容器? SafeLine(雷池)的控制台配置存放在 Pos
后端消息队列消息路由Mosquitto 2.0.13 发布:Broker 与客户端库关键缺陷修复全解析
Mosquitto 2.0.13 发布:Broker 与客户端库关键缺陷修复全解析 Mosquitto 2.0.13 是 Eclipse Mosquitto 在
后端消息队列消息路由
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考