curl 8.22 收紧无证书场景下的公钥固定校验
curl 8.22.0 于 2026 年 9 月 2 日发布,其中包含一项 OpenSSL TLS 修复,项目将其描述为“只有在未配置公钥固定时,缺少服务器证书才可能被接受”。其核心含义很明确:一旦配置了公钥固定,对端没有提供证书,就不能走专为显式关闭证书验证的环境保留的接受路径。

这项变更还统一了应选用哪一个公钥固定配置,包括区分 HTTPS 代理与目标服务器。HTTPS 请求通过 HTTPS 代理时可能存在两个独立 TLS 对端,因此两层信任决策必须分开。
修复了什么
公钥固定会把对端证书中的公钥与预设值或摘要比较。它是额外的身份约束,不等于可以忽略常规证书与主机名验证。
修复前,OpenSSL 路径遇到“无对端证书”时,只要证书验证被关闭,就可能接受该情况,却没有同时确认当前是否配置了公钥固定。curl 8.22 收紧条件:只有验证关闭且没有任何适用公钥固定时,才可能接受无证书情况。
该修复不会自动轮换固定值,不会修正错误固定,也不会把代理固定与源站固定合并,更不会让 TLS 失败变成可随意重试的网络错误。
为什么代理运营需要关注
客户端可先与 HTTPS 代理建立 TLS,再创建 CONNECT 隧道,随后与目标站建立第二层 TLS。四个概念不可混淆:
- HTTPS 代理证书用于认证代理端点;
- 目标证书用于认证隧道内源站;
- 代理公钥固定约束代理层;
- 源站公钥固定约束目标层。
TCP 已连接代理并不证明源站身份,源站固定也不能认证代理。可参考代理网关证书到期处置手册,把常规到期监控与固定校验分开。
识别需要复核的配置
盘点使用 curl 或 libcurl 且采用 OpenSSL 系列 TLS 后端的应用。必须记录真实运行库版本,不能只看同一主机上的命令行 curl。
优先检查:
- 源站公钥固定;
- HTTPS 代理公钥固定;
- 实验室或历史例外中关闭对端验证;
- 代理与源站使用不同 TLS 设置;
- 自定义连接复用或共享连接缓存;
- TLS 失败后自动轮换代理;
- 代理失败后直连回退。
盘点中不要保存完整固定材料或私密配置值,只记录配置别名、固定版本、负责人、对端层级与计划退役日期。
建立双层回归矩阵
只使用自有或受控代理和源站,不要在无关公共服务上模拟缺少证书。
| 场景 | 代理证书 | 代理固定 | 源站证书 | 源站固定 | 预期 |
|---|---|---|---|---|---|
| 基线 | 有效 | 匹配 | 有效 | 匹配 | 成功 |
| 代理固定错误 | 有效 | 不匹配 | 有效 | 匹配 | 代理 TLS 失败 |
| 源站固定错误 | 有效 | 匹配 | 有效 | 不匹配 | 源站 TLS 失败 |
| 代理无证书 | 缺失 | 已配置 | 未到达 | 已配置 | 代理 TLS 失败 |
| 源站无证书 | 有效 | 匹配 | 缺失 | 已配置 | 源站 TLS 失败 |
| 验证关闭且无固定 | 仅受控实验室 | 无 | 仅受控实验室 | 无 | 按书面政策处理 |
最后一行并非生产建议,只用于证明“关闭验证且无固定”与“存在固定但无法校验”会得到不同结果。
验证真实 TLS 后端
不同 libcurl 构建可使用不同 TLS 后端。容器、语言绑定或静态链接服务未必使用系统 curl。每个测试至少记录:
client_build_alias
curl_version
tls_backend
route_type
peer_layer
verification_policy
pin_configured
certificate_present
curl_result
connection_reused
不得记录代理密码、私钥、完整授权头或 Cookie。若诊断输出包含证书细节,应限制访问权限和保存期限。
分开代理与源站配置
代理 TLS 验证与源站 TLS 验证有不同控制项,公钥固定亦然。代码审查时可建立“代理 TLS”和“源站 TLS”两栏配置图,将 CA 政策、主机名验证、公钥固定、客户端证书与 SNI 归入正确层级。
任何同时出现在两栏的值都必须有明确理由。HTTP 边界可使用代理请求头完整性测试,但不要用头部证据代替 TLS 身份证据。
将缺少证书视为身份失败
配置固定后若对端不提供证书,更换住宅出口并不是解决办法,因为客户端缺少策略要求的身份证据。应将其归类为 TLS 身份失败,停止该线路重试并通知负责人。
禁止:
- 为通过请求而关闭公钥固定;
- 关闭对端或主机名验证;
- 快速轮换大量出口;
- 静默回退直连;
- 用另一 TLS 层的证书代替;
- 把诊断密钥复制进工单。
正确动作可能是恢复预期端点、修正网关配置、执行获批的固定过渡,或在不降低安全要求的前提下回滚客户端升级。
安全轮换公钥固定
固定会让客户端与密钥变化产生运维耦合。在客户端和政策允许时,应维护当前值与下一值的书面过渡计划,并在证书续期或网关替换前完成受控验证。
跟踪固定所属层级、版本与启用窗口、证书或密钥轮换负责人、灰度与回滚标准、最大重叠期和旧值移除。不要为了避免故障而长期保留过宽或过期的固定集合。
覆盖连接复用
复用连接会隐藏新握手问题,直到缓存过期才暴露。测试应同时覆盖全新连接和生产复用策略,并在受控端点或证书切换后验证旧连接不会被错误归因到新配置。
分别统计新建与复用连接。只运行热连接的灰度测试可能错过新部署真正会遇到的问题。
上线门槛
- 代理与源站固定只在各自层级匹配时成功;
- 错误代理固定在隧道使用前失败;
- 错误源站固定在隧道内失败;
- 相关固定存在时,缺少证书必须失败;
- TLS 身份失败不触发失控轮换;
- 强制代理任务不回退直连;
- 新建与复用连接均符合策略;
- 日志指出失败层级且不泄露机密;
- 已记录固定轮换与回滚负责人;
- 有效结果率与尾延迟在灰度预算内。
升级检查清单
- [ ] 已确认运行中的 curl/libcurl 版本与 TLS 后端。
- [ ] 已分别盘点源站和 HTTPS 代理固定。
- [ ] 关闭验证的例外已有记录及移除日期。
- [ ] 受控测试覆盖匹配、不匹配与无证书。
- [ ] 代理和源站两层 TLS 均已测试。
- [ ] 已覆盖新建及复用连接。
- [ ] 身份失败采用有界且不轮换的处理。
- [ ] 强制代理任务禁止直连回退。
- [ ] 日志不含密码、私钥、Cookie 或完整令牌。
- [ ] 当前值与下一值的切换流程已演练。
- [ ] 灰度和回滚阈值已批准。
常见问题
所有 curl 用户都受影响吗?
不是。该修复重点涉及 OpenSSL 后端遇到缺少对端证书,同时配置公钥固定或关闭验证的场景。必须核实实际后端与配置。
公钥固定能代替 CA 与主机名验证吗?
不应这样使用。固定是额外约束,应与组织证书政策共同设计,不能因为存在固定就关闭常规验证。
代理固定和目标固定是同一个吗?
不是。HTTPS 代理与隧道内目标是不同 TLS 对端,必须独立配置、轮换和观测。
缺少证书是否应更换出口重试?
不应自动这样做。策略要求固定时,缺少证书意味着所需身份证据不可用,应停止并诊断对应 TLS 层。
相关 98IP 指南包括代理凭据轮换、代理故障转移演练与代理绕过审计。
来源说明:curl 项目《Changes in 8.22.0》,发布于 2026 年 9 月 2 日;curl 项目变更“openssl: no server cert is only okay if also not pinned”,合并于 2026 年 8 月 25 日。外部资料位置仅保存在内部运营记录。
仅在自有或明确获准的受控系统上测试。遵守证书政策、访问条款、隐私义务与适用法律。不得为了完成代理测试而削弱 TLS 验证或暴露凭据。