浏览器能翻墙,终端却连不上?curl 和 Git 代理排查
浏览器能打开网站,终端里的 curl 或 Git 却一直超时,先检查命令行工具有没有使用代理。开启系统代理,不代表每个程序都会读取这项设置;客户端切到全局模式,也需要请求先进入客户端,才谈得上按规则转发。
有人在 Clash Verge Rev 的 GitHub 原帖中报告:给 curl 加了进程规则,仍然超时,客户端里也找不到对应日志;在终端设置代理环境变量后,请求才出现在日志中。这是用户的个人经历,但它提示了一个有用的排查顺序:先确认请求到了哪里,再判断节点是否有问题。
以下方法针对本机终端中的 curl 和 Git HTTPS 请求。浏览器测试时,尽量访问命令行正在请求的同一个域名;浏览器能打开其他网站,只能说明部分访问正常。
先确认本地代理端口
打开客户端设置,找到 HTTP 代理端口或 Mixed 混合端口,确认核心正在运行。这里需要的是本机应用连接客户端的监听端口,不是订阅地址、远端节点端口或控制面板的 API 端口。
下文用 127.0.0.1:7897 举例,请把 7897 换成你设置中的实际端口。127.0.0.1 指当前运行命令的这台机器。若客户端只开了 SOCKS 端口,就不能照抄 HTTP 代理地址。
先保持当前节点不变,用同一目标做一次显式代理测试。macOS/Linux 的 Bash 或 Zsh 中执行:
curl --proxy http://127.0.0.1:7897 --noproxy "" --connect-timeout 10 --max-time 30 -v https://github.com/ -o /dev/nullWindows PowerShell 中执行:
curl.exe --proxy http://127.0.0.1:7897 --noproxy "" --connect-timeout 10 --max-time 30 -v https://github.com/ -o NULWindows PowerShell 5.1 中,curl 可能是 Invoke-WebRequest 的别名,因此这里明确写 curl.exe。部分旧版 PowerShell 的原生命令参数传递可能丢失空字符串;若上面的命令出现参数解析错误,可在 Windows 的 CMD 中执行同一条 curl.exe 命令。
--proxy 为这一次请求指定代理,--noproxy "" 清空这次请求的绕过列表,避免 NO_PROXY 干扰对照。这些参数不会改写系统或终端的长期配置。参数行为可查 curl 官方手册。
如果监听端口只支持 SOCKS5,将命令中的代理地址换成 socks5h://127.0.0.1:实际端口。curl 的 socks5h 会把目标域名交给 SOCKS 代理解析;socks5 则在本地解析。它们的差别可能影响域名解析失败的情况,但不能替代对端口和服务状态的检查。
看错误发生在哪一段
观察 curl 的输出,同时查看客户端的连接列表或日志。客户端日志可能有级别限制,单凭“没看到记录”不能断定流量没有进入代理。
| 观察到的情况 | 下一步检查 |
|---|---|
无法连接 127.0.0.1 的指定端口,提示拒绝连接 | 核心是否运行、端口是否填错、监听地址是否匹配 |
| 已连上本地代理,但建立到目标的连接失败或超时 | 客户端是否将该目标判为直连、当前节点及目标路径是否可用 |
| 显式代理请求成功,平时的 curl 请求失败 | 终端代理变量、绕过列表,以及工具自己的配置 |
| 收到 HTTP 403、429 等响应 | 请求已收到 HTTP 响应,继续辨别是目标网站还是中间代理返回,再查权限、限流或访问要求 |
| 出现证书验证错误 | 系统时间、证书信任链和是否存在 HTTPS 检查;不要用关闭证书验证作为长期修复 |
对 HTTPS 请求,curl 输出中的 200 Connection established 只表示 HTTP 代理接受了建立隧道的请求,不等于目标网站已经返回正常页面;还要看后续 TLS 握手和 HTTP 响应。
如果浏览器和显式代理测试都失败,再按机场节点全部超时的排查方法检查接入网络、账户与服务状态。
显式代理可用,再检查终端变量
curl 会读取代理环境变量。对 HTTP/HTTPS 请求,先看 http_proxy、https_proxy,也检查 all_proxy 和 no_proxy;除了 http_proxy,curl 还支持这些变量的相应大写形式。在 macOS/Linux 中,HTTP 代理变量要使用小写 http_proxy。
容易漏掉的是:按协议设置的变量优先于 ALL_PROXY;NO_PROXY 中若包含目标域名,请求会绕过代理,设为 * 则对所有目标绕过。 只改 all_proxy,不一定能替换旧的 https_proxy。规则见 curl 的代理环境变量说明。
想先验证环境变量是否生效,Bash/Zsh 可以只为一条命令赋值:
https_proxy=http://127.0.0.1:7897 HTTPS_PROXY=http://127.0.0.1:7897 no_proxy= NO_PROXY= curl --connect-timeout 10 --max-time 30 -v https://github.com/ -o /dev/null这条命令不影响之后的终端会话。它把 HTTPS 代理指向本地 HTTP 代理,所以值以 http:// 开头;变量名中的 https 指目标网址的协议,不要求本地代理本身也使用 HTTPS。
确认有效后,再决定是否写入终端启动配置。已经打开的终端、IDE 或后台任务可能仍持有旧环境,需要重新启动相应进程。PowerShell 用户可先继续使用单次 curl.exe --proxy 测试,避免在原因尚未明确时改动用户级环境变量。
如果显式代理可用,环境变量方式仍然失败,也检查 curl 的个人配置文件(如 .curlrc)是否设置了其他代理或绕过选项。
curl 通了,Git 还不通怎么办
先看 Git 实际使用的地址。在已有仓库目录运行:
git remote -vhttps://github.com/... 使用 HTTPS;[email protected]:... 或 ssh://... 使用 SSH。Git 的 http.proxy 设置针对 HTTP/HTTPS,不能直接解决 SSH 连接问题。
对 HTTPS,可以先测试一次公开仓库的远端查询,不必克隆整个仓库:
git -c http.proxy=http://127.0.0.1:7897 ls-remote https://github.com/git/git.git HEAD-c 只为本次 Git 命令提供配置。若仍受绕过列表影响,Bash/Zsh 可在命令前加 no_proxy= NO_PROXY=,再做对照;公开仓库成功只能说明这次请求可用,不能证明私有仓库的权限或认证正确。
Git 还可能保存着旧代理。在出问题的仓库目录检查代理配置及其来源:
git config --show-origin --get-regexp '^(http\..*proxy|remote\..*\.proxy)$'没有匹配项时,该命令可能不输出内容并返回非零状态,不代表 Git 损坏。若输出里出现旧端口,或某个 URL、某个 remote 专用的代理,先根据显示的文件来源核对。URL 专用配置和 remote 覆盖项也可能影响前面的单次测试;不要只改全局 http.proxy 就认定问题已排除。
确认某个旧值不再需要后,再修改对应配置;修改前记下原值,方便恢复。Git 的代理、按 URL 匹配和配置来源规则见 Git 官方配置文档。配置和日志可能包含认证信息,分享前先去掉密码、令牌及私人仓库地址。
什么时候才需要考虑 TUN
如果只有 curl 或 Git HTTPS 需要代理,应用自己的代理参数通常更容易定位问题。需要让更多不读取系统代理的程序进入客户端时,可以再评估 TUN,并检查权限、路由、DNS 和分流规则;开启 TUN 也不保证每个请求都会使用代理出口。
另外,WSL、容器和远程服务器不能直接套用本机示例:它们的网络环境可能不同,127.0.0.1 不一定指向运行桌面代理的主机。先确认命令运行在哪个环境、能否访问客户端监听地址。对于“浏览器正常、终端失败”,把这条连接路径查清楚,往往比反复更换节点更有帮助。