curl 访问 127.0.0.1 却返回 502:本机代理环境变量埋的坑

举报
yd_273983069 发表于 2026/10/29 10:16:50 2026/10/29
【摘要】 本地服务明明跑着,curl 127.0.0.1 却稳定返回 502,浏览器打开又是好的。问题不在服务,而在 HTTP_PROXY 把本机回环流量也劫持了。本文讲清判断方法和三种修法。

先说现象。本机起了个服务监听 127.0.0.1:9222,浏览器能正常打开,但命令行 curl 一直返回 502 Bad Gateway,日志里服务端一条请求记录都没有。换端口、重启服务、换 curl 版本都没用,因为它压根没连到你本机的服务。


为什么代理会劫持回环地址


很多人以为「本机地址不会走代理」,实际不是。curl 的行为是:只要环境变量里存在 http_proxy / https_proxy / all_proxy,它对任何 http(s) URL 都会先连代理,包括 http://127.0.0.1 和 http://localhost。是否直连只由 NO_PROXY 决定,而 NO_PROXY 默认是空的。


于是链路变成:curl → 代理(127.0.0.1:14542)→ 代理尝试访问 127.0.0.1:9222。注意后一个 127.0.0.1 是代理进程自己所在主机的回环,如果代理跑在容器、WSL、远程跳板上,它看到的 127.0.0.1 跟你不是同一台机器,连不上就回 502。就算代理在本机,很多代理也会拒绝转发回环地址,同样回 502。


所以 502 这个状态码特别有迷惑性:它看起来像「后端服务挂了」,实际含义是「代理连不上上游」。真正的判据是服务端没有任何访问日志——服务没崩,是流量没到。


怎么快速确认


第一,直接打印环境变量:


  env | grep -i proxy


如果 HTTP_PROXY / http_proxy 有值而 NO_PROXY 是空的,基本就锁定了。注意大小写两套变量都要看,curl 两套都认,且小写优先。


第二,绕开代理再请求一次:


  curl --noproxy '*' http://127.0.0.1:9222/health


如果这一下通了,结论就确定了:不是服务的问题,是代理的问题。


第三,看 curl 的详细过程:


  curl -v http://127.0.0.1:9222/health


走代理时输出里会先出现 Trying 127.0.0.1:14542... 然后 CONNECT 或直接 GET 到代理端口;直连时才是 Trying 127.0.0.1:9222。这一步能把「以为直连、其实走了代理」直接照出来。


三种修法,按推荐顺序


1)补 NO_PROXY(最省事,一次配好长期有效)


  export NO_PROXY=localhost,127.0.0.1,::1,.local

  export no_proxy=$NO_PROXY


要点:只写域名不够,必须带 127.0.0.1 和 ::1;很多工具只认小写那一份,两份都设最稳;用 CIDR 或 127.0.0.0/8 在部分工具里不生效,老老实实列地址更可靠。


2)只给这一条命令关代理


  curl --noproxy '*' ...


适合临时排查、写进脚本给不特定环境跑。缺点是容易忘,一换成 wget、httpie、Node 的 http 模块就又不生效了——它们各自读环境变量的逻辑并不完全一样。


3)改脚本里的请求方式


如果代码里用的是 axios、requests 这类库,它们默认也会读环境变量。要么在初始化时显式传 proxy: false(axios)或不设 proxies(requests 用 trust_env=False),要么统一走 NO_PROXY。这一步比在命令行加参数更彻底,因为定时任务、CI 里通常没人会记得加。


两个容易连带踩到的点


一是「502 是真故障」的误判。看到 502 先别急着查后端进程,先确认流量有没有到后端:后端日志有没有记录、端口用 ss -lntp 看是不是真在 listen。两者只要有一个不成立,问题就在链路上,不在服务里。


二是 IPv6。localhost 在不少系统上优先解析成 ::1,服务只监听了 127.0.0.1 就会出现「curl localhost 不通、curl 127.0.0.1 通」的怪现象。这跟代理无关,但症状相似,排查时一起看一眼比较省时间:ss -lntp 里能看到监听的是 0.0.0.0、127.0.0.1 还是 [::]。


小结


127.0.0.1 不通、返回 502、后端零日志,这三件事同时出现,九成是代理环境变量把回环流量带走了。判断只需要一条 curl --noproxy '*',修法优先补 NO_PROXY,脚本内部再单独关一次,别指望命令行参数能覆盖所有调用方。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。