近日,多位使用 Eclipse Mosquitto 桥接(Bridge)功能的开发者在社区中反映,尝试通过 TLS 加密连接将 MQTT 消息桥接至 Azure EventGrid 时遭遇持续失败。该问题影响了依赖 MQTT 桥接实现物联网数据上云的关键业务场景,引发广泛关注。经技术团队与社区协作排查,问题根源指向 Mosquitto 与 Azure EventGrid 在 TLS 握手阶段的证书链验证差异,以及 EventGrid 端对客户端证书的特定要求。本文将对故障现象、技术成因及已验证的解决方法进行深度解读。

故障现象

用户报告显示,在 Mosquitto 配置文件中启用 bridge 模式,并设置 bridge_protocol_version mqttv311connection_messages true 以及 bridge_insecure false 后,Mosquitto 日志反复出现类似以下错误:

Error: bridge connection to azure.eventgrid.com:8883 failed: TLS error: certificate verify failed

或:

OpenSSL Error[0]: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

部分用户尝试将 bridge_insecure 设为 true 后可以连接成功,但这显然不符合安全最佳实践,无法用于生产环境。

技术原因排查

经深入分析,问题主要源自三个方面:

1. 中间证书链缺失
Azure EventGrid 的 TLS 证书由公开受信任的证书颁发机构(CA)签发,但 Mosquitto 默认加载的 CA 证书包(通常是系统的 CA bundle)可能不包含 EventGrid 所使用的中间证书。具体而言,EventGrid 的证书链包含 DigiCert Global Root CA 以及一个或多个中间证书。若 Mosquitto 编译时未正确配置 CA 路径,或操作系统 CA 包未更新,则会导致验证失败。

2. SNI(服务器名称指示)支持不足
Azure EventGrid 要求客户端在 TLS 握手中发送正确的 SNI 扩展,以指示目标主机名。Mosquitto 1.6 及更早版本对 SNI 的支持存在限制,默认未启用或需手动配置 bridge_sni 选项。若未设置 bridge_sni 为 EventGrid 的终结点主机名,握手将被拒绝。

3. 客户端证书要求
Azure EventGrid 的 MQTT 桥接场景通常要求使用 SAS Token 或证书进行身份验证。Mosquitto Bridge 虽然支持客户端证书(通过 bridge_certfilebridge_keyfile 配置),但若证书格式、密钥算法或密码套件不匹配,TLS 握手可能提前终止。此外,EventGrid 对 TLS 1.2 及特定密码套件(如 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)有强制要求,而 Mosquitto 默认密码列表可能过于宽松。

影响范围与社区反应

该问题影响使用 Mosquitto 作为边缘代理、需要桥接数据到 Azure EventGrid 的物联网系统。GitHub Issue 列表中已有超过 200 条相关讨论,不少用户反映生产环境因此中断。Azue IoT 团队在官方文档中更新了连接指南,但未明确提及 Mosquitto 的特殊配置。社区贡献者已提交补丁,但正式版 Mosquitto 2.0.18 以上版本才内置了更完善的 SNI 处理。

已验证的解决方案

综合社区经验与官方反馈,以下步骤可有效解决该问题:

  1. 更新 CA 证书包
    确保 Mosquitto 使用的 CA 文件包含 DigiCert Global Root CA 和中间证书。建议从 DigiCert 官网下载最新 CA 包,并在 Mosquitto 配置中通过 cafile 指定。

  2. 启用 SNI 支持
    在桥接配置中添加 bridge_sni true(针对 Mosquitto 2.0+ 可直接使用,1.6 需升级)。同时设置 bridge_address 为 Azure EventGrid 的主机名,而非 IP。

  3. 调整密码套件
    listenerbridge 段中显式指定密码列表,例如:
    ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
    并确认 OpenSSL 版本不低于 1.1.1。

  4. 升级 Mosquitto 版本
    建议升级至 Mosquitto 2.0.19 或更高版本,该版本修复了多个 TLS 相关 bug,并支持 bridge_tls_version 强制设定 TLS 版本为 1.2。

  5. 使用 SAS Token 替代证书
    若客户端证书管理复杂,可考虑在 Mosquitto 桥接的 bridge_identity 中配置 Azure EventGrid 的 SAS Token(需配合 bridge_password 字段),但注意需在连接前更新 Token 过期时间。

行业观察与建议

此次事件再次提醒物联网开发者:云服务商对 TLS 规范的实现各有差异,轻量级 MQTT Broker 的桥接功能需严格测试多个安全参数的兼容性。建议用户在部署前使用 openssl s_client -connect 命令手动验证 EventGrid 的证书链,并对照 Mosquitto 的 --cafile 测试。同时,Azure EventGrid 团队应补充更详尽的 Mosquitto 桥接配置示例,以减少生产环境中的试错成本。

截至发稿,Mosquitto 维护者已表示将在下一个 LTS 版本中优化对 Azure 服务的默认兼容性。对于正在受影响的用户,可暂时采用上述解决方案中的证书链手动配置与密码套件锁定,也可考虑使用 Azure IoT Hub 的原生 MQTT 端点作为替代桥接目标。