DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

curl 通过代理访问 HTTPS 报 wrong version number:检查代理协议

curl 经代理访问 HTTPS 报 wrong version number,先区分代理 TLS 与目标 TLS,确认普通 HTTP 代理后使用正确协议与端口。

curl 访问 HTTPS 网站时指定了 https://proxy.example.net:3128,却在握手阶段报 curl: (35)、wrong version number。先确认代理端口本身是否支持 TLS。访问目标网站的协议和连接代理的协议是两个配置,目标是 HTTPS 不意味着代理地址也必须写成 https://。

本文适用于 curl 经 HTTP CONNECT 代理访问 HTTPS 目标的场景。wrong version number 有多种触发条件,下面的处理仅用于把普通 HTTP 代理端口误当成 HTTPS 代理的情况;SOCKS 代理需要使用其实际协议。

看错误发生在 CONNECT 前还是之后

使用 curl 的详细输出时,先辨认连接到了哪个地址、是否已经发送 CONNECT、代理是否返回成功响应,再看 TLS 错误。诊断输出可能包含代理账号、请求头和其他凭据,分享前需要清理。

如果刚连上代理端口便开始 TLS 握手,尚未收到成功的 CONNECT 响应,就要核对代理 URL 的协议。普通 HTTP 代理收到 TLS 数据时,返回的内容不是客户端预期的 TLS 记录,可能产生这个错误。

如果代理已经返回 200 Connection established,错误发生在随后与目标的 TLS 握手,则需要检查目标地址、目标端口、代理隧道或 TLS 拦截。此时把代理 URL 改成 HTTP 不一定能解决。

407 Proxy Authentication Required 是代理认证问题,curl: (60) 通常涉及证书验证,连接被重置也有多种原因。不要把这些不同结果都归为同一处协议错误。

普通 HTTP 代理要使用 http://

先从代理服务配置或管理员提供的信息确认端口类型。以下是已确认普通 HTTP 代理后的命令示例:

curl --proxy http://proxy.example.net:3128 \
  --output response.bin \
  https://service.example.net/status

将代理与目标地址替换为实际值,输出文件选择未占用的路径。显式 --proxy 可以减少环境变量造成的混淆,但仍要核对 NO_PROXY、curl 配置文件和其他选项是否使实际请求绕过代理。

这里的 http:// 描述 curl 到代理的连接方式。对于 HTTPS 目标,curl 通常先建立 CONNECT 隧道,再与目标进行 TLS 握手;它不会因为代理 URL 是 HTTP 就把目标请求改成明文 HTTP。

不过,普通 HTTP 代理上的 CONNECT 请求和代理认证信息不受代理 TLS 保护。若部署要求这段链路也加密,应使用真正提供 TLS 的 HTTPS 代理端口,而不是仅修改 URL 前缀。

代理确实提供 HTTPS 时,保留它的协议

HTTPS 代理需要 curl 版本与 TLS 后端支持,也需要正确的 TLS 监听端口。不要拿普通代理端口测试 HTTPS 后就判断代理服务整体不支持。

代理证书和目标证书有各自的信任检查。需要信任内部代理 CA 时,使用适用的 --proxy-cacert;目标服务使用内部 CA 时,检查目标侧 --cacert 或系统信任配置。两者不能互相替代。

关闭证书校验不会让明文端口具备 TLS 能力,也不应成为这里的修复步骤。认证、证书或 TLS 后端兼容问题,应在代理协议已经确认后分别处理。

验证脚本实际走的是同一条路径

修复后,应看到预期代理处理 CONNECT,并成功完成目标 TLS 握手、得到业务所需响应。只看到连接代理成功,或 HTTP 状态码变了,还不能证明目标调用正常。

命令行成功而定时任务失败时,比较两者使用的 curl 版本、代理变量、NO_PROXY 和配置文件。修改自动任务前保存原配置,先用单次显式代理请求验证;失败时恢复原设置,避免把一项局部调整扩展成系统全局代理变更。