curl 收紧 CONNECT 处理:401 不是代理认证挑战
curl 项目在 2026 年 9 月 4 日合并了一项聚焦 HTTP 代理的修正:当代理对 CONNECT 请求返回 401 Unauthorized 时,curl 应忽略该隧道交换中的 WWW-Authenticate 并让连接失败。代理认证仍应由 407 Proxy Authentication Required 和 Proxy-Authenticate 驱动。

这一区别很重要,因为 CONNECT 请求发给代理,而不是目标源站。401 属于源站认证语义,407 才属于代理认证。若客户端在建立隧道时响应 401,便可能混淆信任边界并触发不应发生的认证重试。
截至 9 月 9 日,该修正已合并到 curl 开发分支,并列入下一维护版本的开发发布说明;这不代表所有已安装的 curl 软件包已经包含修正。调整生产策略前,应核对实际二进制版本以及发行商是否回移补丁。
公开来源说明: curl 项目 PR 22817《HTTP-CONNECT: do not react to 401 responses》,2026 年 9 月 3 日提交、9 月 4 日合并;curl 项目开发版发布说明,2026 年 9 月 9 日查阅。
发生了什么变化
HTTP CONNECT 握手中,客户端要求代理为目标 authority 建立字节隧道。2xx 响应表示隧道建立成功;407 表示代理要求认证,并可通过 Proxy-Authenticate 告知允许的方法。
合并后的修正阻止 CONNECT 解析器在响应为 401 时转交或解释 WWW-Authenticate。curl 将其视为隧道失败。补丁还增加了专门的回归测试,使该行为保持明确。
这是解析器与认证边界修正,不会新增认证方式,不会绕过代理策略,也不会让被拒绝的隧道获得无限重试资格。
为什么必须区分 401 与 407
使用代理的客户端通常持有两套独立凭据:
- 隧道建立前使用的代理凭据;
- 隧道建立后、只在隧道内部使用的目标凭据。
混用两者会带来安全和运营风险:客户端可能把目标凭据送向代理层、反复重试确定性拒绝、轮换健康出口,或错误地把事件归类为目标登录失败。连接池共享时,模糊的认证状态也会增加事故取证难度。
| CONNECT 结果 | 当前边界含义 | 客户端动作 |
|---|---|---|
| 2xx | 隧道已建立 | 继续目标协议 |
| 407 加 Proxy-Authenticate | 代理要求认证 | 仅使用批准的代理凭据并限制协商次数 |
| 401 加 WWW-Authenticate | 不应驱动代理认证 | 让隧道失败,不把它当作代理挑战 |
| 其他非 2xx | 隧道未建立 | 记录状态并执行失败策略 |
curl CONNECT 尾端字段测试指南解释了相邻的响应边界;SPNEGO 与 NTLM 回退文章介绍了另一项代理认证加固。
建立受控回归环境
使用自己拥有或获准测试的代理模拟器和目标服务。并发设为 1,关闭自动网关轮换,让每个结果只有一个原因。准备四种代理行为:
- 返回正常 2xx CONNECT 并转发隧道。
- 返回 407 和受支持的
Proxy-Authenticate挑战。 - 返回 401、携带
WWW-Authenticate,随后关闭连接。 - 返回另一种确定性的非 2xx,且不带认证头。
分别使用当前生产构建和包含该修正的构建执行全部用例。不要在无关公共代理上制造异常认证响应。
应记录哪些证据
记录客户端版本、构建标识、TLS 后端、代理传输方式、网关群组、地址族和时间。CONNECT 交换只保留脱敏字段:
- 响应状态;
- 是否出现
Proxy-Authenticate或WWW-Authenticate; - 最终选择的代理认证方式;
- CONNECT 尝试次数;
- curl 结果码与总耗时;
- 是否发出任何目标 TLS 字节;
- 是否尝试直连。
不得记录用户名、密码、Bearer Token、原始 Authorization 值、Cookie 或完整会话标识。不需要原始地址时,对网关和出口标识进行令牌化。
通过与失败标准
2xx 用例只有在预期代理路径上的目标 TLS 和应用检查都成功时才算通过。407 用例应使用正确作用域的代理凭据,在重试上限内完成允许的认证流程并建立隧道。
401 用例应在不响应 WWW-Authenticate、不发送目标凭据、不进入目标 TLS、也不静默直连的情况下让 CONNECT 失败。只有一个通用失败码还不够,必须确认没有认证重试。
另一个非 2xx 用例应以一次可归因结果结束。面对同一确定性响应仍不断轮换出口,说明重试策略本身存在问题。
不混淆客户端与网络健康的发布方式
先在小型灰度组部署,并与使用相同代理网关、目标和工作负载的对照组比较:
- 首次尝试有效结果率;
- CONNECT 状态分布;
- 代理认证挑战轮数;
- 凭据越界次数,预期为零;
- 直连回退次数,预期为零;
- 隧道建立耗时的 p50 与 p95;
- 每个完成任务的重试量。
如果客户端升级后 401 失败增多,不要立即归咎于出口质量。更严格的客户端可能暴露了返回源站式认证的网关、中间设备或测试夹具。保留脱敏响应,定位真正生成它的组件。
上线前检查清单
- 确认实际二进制是否包含该合并修正。
- 在配置和日志中分离代理凭据与目标凭据。
- 覆盖 2xx、407、401 和另一种非 2xx。
- 确认 401 不触发认证重试。
- 确认 CONNECT 失败绝不回退直连。
- 限制重试,不因确定性的客户端策略失败惩罚出口。
- 清除所有凭据和高基数会话值。
- 扩大部署前,将灰度组与当前客户端对照。
常见问题
代理是否绝对不能返回 401?
CONNECT 期间的代理认证应使用 407。401 属于源站认证语义,不应驱动代理凭据协商。
修正是否已经包含在 curl 8.22.0?
不能根据开发发布说明这样推断。该修正在 8.22.0 之后合并并列入下一版本;请检查具体二进制和供应商回移补丁。
401 是否应该触发住宅代理出口轮换?
不应自动轮换。先把它归类为隧道边界失败,查明生成响应的组件。盲目轮换会掩盖确定性的网关或客户端策略问题。
调试日志可以保存认证头吗?
只记录头名称与脱敏的方法标签。除非获批的安全流程明确要求,否则不要保存凭据、Token 或原始挑战内容。
合规说明
仅在你拥有或获准测试的系统和代理服务中执行该流程。遵守目标条款、访问控制、速率限制、隐私义务和数据最小化要求。目标是确保认证作用域正确和失败处理可靠,而不是绕过拒绝。