记一次被社区用户逼着修Bug经历

孔飞@快猫星云 2025-12-25 09:46:28

最近社区用户反馈了一个问题:使用最新版 Categraf (v0.4.34) 的 http_response 插件监控某域名 https://oa.sdu.edu.cn 时,报错 remote error: tls: handshake failure。但开发人员在自己的环境中测试却一切正常。吃瓜围观见issue, 用户对这个问题定性:“希望在新版本中修复这个bug”。

本文记录了该问题的完整排查过程、根因分析及最终修复方案。

1. 排查过程

欸?在我的环境明明好好的 好好的.好好的

复现的诡异性

  • 开发环境 (Debian, 公网):没有报错,能够正常通过 curl 和 Categraf 采集数据。
  • 用户环境 (Anolis OS, 校园网环境)curl 正常,但 Categraf 持续报错 tls: handshake failure

初步怀疑方向集中在:

  1. TLS 版本不匹配?
  2. 中间人设备(防火墙、WAF)干扰?
  3. DNS 解析差异?

关键线索:Cipher Suite 与 IP 协议

通过对比开发人员与用户在各自环境下执行 curl -vI https://oa.sdu.edu.cn 的详细日志,我们发现了具体的差异。

开发人员环境(正常)

* Connected to oa.sdu.edu.cn (202.194.20.69) port 443  <-- IPv4
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384

特点:访问的是 IPv4 地址,服务器支持 TLS 1.3 和现代化的 GCM 加密套件。

用户环境(报错)

* Connected to oa.sdu.edu.cn (2001:da8:7000:f03:202:194:20:69) port 443 <-- IPv6
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
...
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-SHA256

特点

  1. 访问的是 IPv6 地址。
  2. 服务端不支持 TLS 1.3,协商降级到了 TLS 1.2
  3. 最终选用的加密套件是 ECDHE-RSA-AES128-SHA256(即 CBC 模式)。

2. 根因分析:Go的安全策略变更

至此,问题原因浮出水面。

  1. IPv6 入口设备"老旧":该域名的 IPv6 入口(可能是负载均衡或防火墙)配置落后于 IPv4 入口,仅支持 TLS 1.2 且只接受 CBC 模式的加密套件。
  2. Categraf/Go 的默认行为:Categraf 是用较新的 Go 版本(1.24)编译的,而且升级了TLS的依赖库。Go 语言团队为了安全性,在默认的 Client Hello 加密套件列表中剔除了被认为不够安全的 CBC 模式套件(如 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)。
  3. 握手死锁
    • Categraf: “我支持 TLS 1.2/1.3,但我只用 GCM/Chacha20 等高性能安全算法,不提供 CBC。”
    • Server (IPv6): “我只支持 TLS 1.2 且必须用 CBC。”
    • 结果: 双方无法达成一致,服务端发送 handshake failure
  4. Why Curl Works?curl 使用的 OpenSSL 版本不高, 默认策略包含了旧的 CBC 套件,因此能与“老”服务器成功握手。

3. 修复方案

我们通过代码修改,赋予 Categraf “向下兼容” 的能力,允许用户手动指定那些被 Go 默认屏蔽的加密套件。

代码变更 (Pull Request)

  1. 修改 pkg/tls/config.go: 在 ClientConfig 中增加 TLSCipherSuites 字段,允许从配置文件读取 tls_cipher_suites

  2. 修改 pkg/tls/common.go: 补全 Go 标准库中存在但未在 Categraf 映射表中暴露的 Legacy Cipher Suites:

    // 添加 Legacy CBC 套件
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256": tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA":    tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
    // ...
    

用户配置

用户现在可以通过在 http_response.toml 中显式配置旧套件来解决此问题:

[[instances]]
targets = ["https://oa.sdu.edu.cn"]

# 强制开启兼容旧服务器所需的 CBC 套件
tls_cipher_suites = [
  "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",  # 对应 curl 的 ECDHE-RSA-AES128-SHA256
  "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"      # SHA1 版本作为备选
]

总结

在 IPv6 推进过程中,基础设施的更新往往不同步,导致 IPv4 和 IPv6 入口的 SSL 配置产生“代差”。作为监控客户端,保持对旧协议的适度兼容性配置能力,是应对复杂网络环境的关键。

标签: Categraf
快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云
OpenSource
开源版
Flashcat
Flashcat
Flashduty
Flashduty