一、为什么 GUI 能上网,终端却不走 Clash
在 macOS 与 Linux 上,「系统代理」或图形界面里勾选「自动代理」主要影响遵守系统网络栈的应用:例如 Safari、Chrome(在多数安装方式下)、以及部分 Electron 应用。它们会读取系统级的 HTTP/HTTPS 代理或 PAC 脚本,因此一旦 Clash 在本机把系统代理指到 127.0.0.1:端口,你往往感觉「已经翻墙成功」。
但终端里的 curl、git、npm、pip 等程序是另一套世界:它们通常不会自动继承 macOS「网络」偏好设置里的代理,也不会因为你在 Clash 菜单里打开了 TUN 就一定走内核转发路径——具体取决于是否启用了真正的全局 TUN、路由表是否覆盖该进程、以及工具自身是否使用系统代理 API。最常见的情况是:没有任何环境变量,工具就按默认策略直连,于是出现「浏览器秒开 GitHub,终端 git clone 卡死」的割裂体验。
因此,把问题归因为「节点不稳」之前,请先确认:终端进程是否明确被告知要经由本机 Clash 端口出网。这与我们在 macOS 系统代理与网络扩展 一文中讨论的「GUI 与内核扩展权限」是互补关系——那边解决的是系统代理是否下发成功,本文解决的是Shell 与 CLI 如何用环境变量与 Git 配置对齐同一端口。
env | grep -i proxy。若输出为空或仍是旧公司代理,说明当前 Shell 并未加载你期望的 Clash 设置,应先修正配置文件再测 npm / git。
二、确认本机 Clash 的混合端口与监听地址
打开你所用的 Clash 客户端(如基于 Mihomo 的各平台 GUI),在设置或配置文件中查看 混合端口(Mixed Port)。社区里常见默认值为 7890,也可能被改成 7897、10808 等——以后文中举例一律把 7890 换成你的真实端口。
若代理 URL 指向本机,主机名应写 127.0.0.1 或 localhost。在同一台机器的终端里跑 CLI,这是正确做法:流量从本机进程发到本机环回地址上的 Clash 入站,再由 Clash 按规则转发到上游节点。若你在 Docker 容器、远程 SSH 会话或另一台电脑上操作,则不能把 127.0.0.1 当作「运行 Clash 的那台机器」,而要换成对当前环境可达的宿主机 IP(与 Linux 本机部署 Clash 或远程场景下的网络边界有关)。
少数用户只开放了独立的 HTTP 端口与 SOCKS 端口而未使用混合端口,也可以分别设置 http_proxy 指向 HTTP 入站、all_proxy 指向 SOCKS5。为简化叙述,下文以最常见的「混合端口同时提供 HTTP 与 SOCKS」为前提。
127.0.0.1 而你需要从局域网其他设备连入,需另行开启「允许局域网连接」或等效选项;纯本机终端场景下保持监听环回即可,不必强行改为 0.0.0.0。
三、http_proxy、HTTPS_PROXY、ALL_PROXY 怎么写
绝大多数 CLI 与库会读取以下环境变量(名称大小写在不同程序中可能同时生效,建议成对设置小写与大写):
http_proxy/HTTP_PROXY:明文 HTTP 代理,形如http://127.0.0.1:7890。https_proxy/HTTPS_PROXY:HTTPS 流量使用的代理;在 Clash 混合端口场景下通常与 HTTP 填同一个 URL 即可。all_proxy/ALL_PROXY:「兜底」代理,常见写法为 SOCKS5,例如socks5://127.0.0.1:7890。部分工具只认这一项。
若访问公司内网、Docker 桥接网段或本地 registry,应设置 no_proxy / NO_PROXY,列出无需走代理的主机或后缀,例如 localhost,127.0.0.1,.local,.corp.example,避免内网流量误送进 Clash 导致超时。
代理 URL 中不要遗漏协议前缀(http:// 与 socks5:// 语义不同)。若 Git 走 SSH 协议([email protected]:...),环境变量里的 HTTP 代理不会加密隧道 SSH,需要改用 HTTPS 克隆、配置 core.sshCommand 走 ProxyCommand,或使用远程转发——这超出本文范围,只需记住:「设置了 http_proxy 但仍在用 SSH URL」时现象仍会像「没代理」。
四、写入 zsh / bash 配置并持久生效
在 macOS 上,默认登录 Shell 多为 zsh,请编辑 ~/.zshrc;若使用 bash,则编辑 ~/.bashrc 或 ~/.bash_profile(视发行版与启动方式而定)。在 Linux 桌面或服务器上,同样根据实际 Shell 选择对应文件。
在文件末尾追加类似以下内容(端口替换为你的混合端口):
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export all_proxy="socks5://127.0.0.1:7890"
export ALL_PROXY="$all_proxy"
export no_proxy="localhost,127.0.0.1,::1"
export NO_PROXY="$no_proxy"
保存后执行 source ~/.zshrc(或相应文件),或重新打开终端窗口。使用 IDE 集成终端时,注意 IDE 是否在独立环境中启动、是否继承了登录 Shell 配置;若仍无变量,可在 IDE 设置中显式配置环境变量或改为从终端命令行启动 IDE。
五、用 curl 与 env 做连通性自检
在设置完环境变量后,先不要急着跑 npm install,而用 curl 验证「到 Clash 入站端口的 TCP 连接」与「经代理访问外网」两步:
curl -I http://127.0.0.1:7890:若连接被立即接受或返回非连接超时,说明本机端口可达(具体 HTTP 状态码因内核实现而异,不作为成败唯一标准)。curl -fsSL https://www.google.com/generate_204或访问你确信需代理才能打开的 HTTPS 地址:若成功,说明https_proxy链路基本可用。
也可显式指定代理参数对照: curl -x http://127.0.0.1:7890 -I https://example.com。若带 -x 成功而不带失败,则问题集中在环境变量是否导出、是否被后续脚本覆盖。
| 现象 | 优先检查项 |
|---|---|
| curl 带 -x 通,不带不通 | 当前 Shell 未加载 http_proxy/https_proxy;或进程由 systemd/cron 启动且未继承环境变量 |
| 127.0.0.1 端口拒绝连接 | Clash 未启动、端口变更、或客户端崩溃;用系统监视器确认进程与监听 |
| 经代理后仍 TLS 报错 | 节点或规则问题;尝试在 Clash 中切换策略组;与「终端未走代理」区分 |
六、Git 专用代理与环境变量
Git 会读取 http_proxy 等环境变量,但许多用户更愿意用仓库级或全局配置固定下来,避免与其他工具冲突:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
若希望通过 SOCKS5 并让域名解析发生在代理侧(适合部分网络环境),可使用 socks5h://127.0.0.1:7890(注意 h 表示远程解析)。取消设置时使用 git config --global --unset http.proxy 等命令。
当你使用 HTTPS 远程地址 克隆私有仓库或访问 GitHub 时,上述配置与规则分流、节点选择共同决定体验;终端侧首先要保证请求确实到达 Clash,而不是仍直连被 RST 或限速。
七、npm、yarn、pnpm 与代理
npm 会读取 http_proxy / https_proxy 环境变量。也可显式配置:
npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890
yarn(经典版)可使用 yarn config set proxy;pnpm 同样尊重环境变量。若仍失败,请区分「代理已通但 registry 被墙」与「完全未走代理」:前者可尝试合规镜像源与 TLS 错误日志,后者回到 curl 与 env 复查。
企业内网常对 npm 使用私有 registry,此时务必把该域名加入 no_proxy,否则安装包请求会无谓绕一圈代理甚至失败。
八、macOS 与 Linux 上的常见坑
macOS
从「启动台」打开的终端与从第三方终端启动的会话一般都加载 .zshrc,但某些自动化工具只加载 .zprofile。若变量时有时无,可将 export 语句同步到登录 Shell 会加载的文件,或使用 launchctl setenv 为 GUI 子进程设定环境(需谨慎,避免全局污染)。
Linux:sudo 与降权
执行 sudo npm install 时,默认会重置环境变量,导致 http_proxy 丢失。可改用 sudo -E 保留环境,或在本机开发场景下避免对全局 npm 使用 sudo。使用 systemd 服务或 CI 脚本时,应在单元文件或流水线中显式写入 Environment=,而不是假设交互式 Shell 已配置。
远程与容器
SSH 到远程 Linux 服务器时,远程 Shell 的 127.0.0.1 指向远程自己,除非你做端口转发,否则不能把代理指到「你笔记本上的 Clash」。容器内同理:要么在容器里跑 Clash 侧车,要么把宿主机的监听地址以 Docker 网关 IP 等形式传入。
九、TUN 与环境变量:什么情况下仍要配
开启 TUN 模式 后,内核路由可能把大量 IP 包送入 Clash 虚拟网卡,此时许多程序「无需感知」传统 HTTP 代理也能出国。但现实并不绝对:部分静态编译的二进制、特定语言运行时或只认代理变量的工具,在路由或 DNS 策略不覆盖时仍会直连。
实践上,开发者往往同时保留 TUN 与一套清晰的 http_proxy / HTTPS_PROXY / ALL_PROXY:TUN 负责系统级默认路径,环境变量保证 npm、git、curl 在复杂拓扑下行为可预期。若你确认全局 TUN 已覆盖所有目标地址,可在测试通过后简化配置,但首次排障不建议跳过环境变量层。
十、小结
Clash 在 macOS 与 Linux 上把浏览器救活,并不代表终端自动受益。终端代理的核心是:为 Shell 与 CLI 明确设置 http_proxy、HTTPS_PROXY、ALL_PROXY 与合理的 no_proxy,并在 Git、npm 等工具层按需补强专用配置。先对齐本机混合端口,用 curl 验证,再跑业务命令,能避免大量无效试错。
相比其他同类工具,Clash 在规则分流与多平台客户端上的一致性较好;把环境变量与客户端里的策略组、DNS 设置放在同一心智模型下维护,长期成本更低。若你尚未安装或希望使用维护活跃的客户端,可从本站获取安装包并导入订阅,再结合 配置文档 完成系统代理与 TUN 的基础设定,然后按本文把终端链路一并打通。