开发者Git与SSH走Clash代理全链路工作流指南
开发者日常遇到的 GitHub 拉取失败、SSH 超时、npm 下载缓慢,往往不是代码问题,而是终端流量没有正确进入代理。本文以 Clash 为核心,整理 Git、SSH、Homebrew 及包管理器的完整配置思路,帮助你建立稳定可复用的开发网络工作流。
先建立开发代理的完整链路
开发环境里的代理问题,通常不是“Clash 没有启动”这么简单。浏览器能打开页面,只能证明浏览器遵守了系统代理;Git、SSH、Homebrew、npm、pip、Docker 等工具各自有独立的网络实现,有些读取系统代理,有些只读取环境变量,还有一些完全不看系统设置。结果就是网页访问正常,但终端里的 git clone 超时、SSH 握手卡住、Homebrew 更新极慢,或者 npm 一直停在下载阶段。
要让开发流量稳定进入 Clash,需要先分清三层关系。第一层是 Clash 的入站端口,通常是 127.0.0.1:7890 的 mixed-port,同时接受 HTTP 与 SOCKS5 请求;第二层是应用自身的代理设置,例如 Git 的 http.proxy、npm 的 https-proxy;第三层是操作系统或 TUN 接管,用于覆盖那些没有代理选项、也不读取环境变量的程序。
推荐的工作方式是:日常浏览与普通命令优先使用规则模式,终端工具通过明确的 HTTP 或 SOCKS5 代理连接,SSH 单独配置 ProxyCommand;当某个工具完全不支持代理,再启用 TUN 作为兜底。这样每一层职责清楚,关闭代理、切换节点或更换客户端时,不会因为大量硬编码配置而难以恢复。
先确认 Clash 端口
以下示例假设 Clash 或 mihomo 的本地 mixed-port 是 7890。如果客户端显示的是 7897、7891 或其他端口,必须把命令中的端口全部替换为实际值。不要把订阅服务商的远程端口当成本地代理端口。
Clash 基础设置:端口、规则与 TUN
打开 Clash Verge、Clash Verge Rev、Mihomo Party 或其他 mihomo 客户端,先进入设置页确认代理端口。常见字段包括 mixed-port、port 与 socks-port。开发工具使用 mixed-port 最方便,因为同一个端口同时兼容 HTTP 代理和 SOCKS5 代理。如果配置只开放了 HTTP 端口,SSH 的 SOCKS5 转发命令可能无法工作;如果只开放 SOCKS5 端口,部分只支持 HTTP CONNECT 的工具又会失败。
本机开发环境通常不需要开放局域网访问。建议保持 allow-lan: false,监听地址使用 127.0.0.1 或客户端默认的本机地址。只有需要让手机、虚拟机或局域网其他设备共享代理时,才考虑打开局域网访问,并同步设置防火墙规则。开发机一旦把代理端口暴露给整个局域网,同网设备可能在未授权的情况下使用你的节点。
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1
mode: rule
规则模式下,Git 的 HTTPS 请求是否代理取决于目标域名命中哪条规则;SSH 连接通常只看到目标主机名和端口,不会自动继承 Git 的 HTTP 代理设置。因此,不能因为浏览器或 Git HTTPS 已经正常,就推断 SSH 也已经进入代理。对开发者而言,最容易验证的顺序是先测试本地端口,再测试环境变量,最后分别验证 Git、SSH 和包管理器。
如果某个命令行工具不支持代理参数,或者它使用 UDP、任意端口连接,可以开启 TUN。mihomo 的典型配置如下:
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
TUN 会通过虚拟网卡接管更多系统流量,但也会带来权限、路由冲突和局域网访问问题。Windows 通常需要服务模式或管理员权限;macOS 需要允许网络扩展;Linux 需要相应的网络权限。开启 TUN 后,仍然建议保留 Git 和 npm 的显式代理配置,因为显式配置更容易诊断,也能避免工具在 TUN 关闭后突然恢复为直连。
终端环境变量:统一覆盖常见工具
环境变量是开发工作流的第一层统一入口。许多 CLI 会读取 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 与 NO_PROXY;变量名通常不区分大小写,但为了兼容不同语言生态,建议大小写版本同时设置。HTTP 代理地址写成 http://127.0.0.1:7890,SOCKS5 代理建议使用 socks5h://127.0.0.1:7890。其中 socks5h 的 h 表示由代理端解析域名,避免应用先在本地 DNS 解析目标。
在 macOS、Linux 或 Windows PowerShell 中,可以按当前终端会话设置:
# macOS / Linux
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5h://127.0.0.1:7890
export NO_PROXY=localhost,127.0.0.1,::1,.local
# Windows PowerShell
$env:HTTP_PROXY="http://127.0.0.1:7890"
$env:HTTPS_PROXY="http://127.0.0.1:7890"
$env:ALL_PROXY="socks5h://127.0.0.1:7890"
$env:NO_PROXY="localhost,127.0.0.1,::1,.local"
设置后可以先用一个只返回请求信息的测试命令确认变量已经生效:
curl -I --proxy http://127.0.0.1:7890 https://example.invalid
上面的地址仅用于说明命令结构,实际测试应替换为你能够访问的目标。更实用的判断方式是查看 Clash 日志:执行命令时,日志里应出现对应域名的连接记录。如果日志完全没有新请求,说明工具没有读取该变量、命令没有走这条链路,或代理端口填写错误。
NO_PROXY 不宜写得过宽。把整个后缀、所有内网地址甚至全部域名加入其中,会让本应代理的请求绕过 Clash。一般保留本机回环地址、局域网域名和内部开发域名即可。企业环境还可能需要加入内部 Git 服务、制品库或数据库地址,但应按实际网段逐项添加。
Git 代理配置:分别处理 HTTPS 与 SSH
Git 常见的远程地址有两种。HTTPS 地址会使用 HTTP 或 HTTPS 代理配置;SSH 地址则由 OpenSSH 负责连接,不会读取 Git 的 http.proxy。因此,先查看远程地址类型,是排查拉取失败的关键:
git remote -v
git config --get remote.origin.url
HTTPS 仓库:配置 Git 的 http.proxy
如果远程地址以 https:// 开头,可以为当前用户设置全局代理。这里使用 HTTP 形式连接 Clash mixed-port,因为 Git 的 HTTP 传输由 libcurl 处理,兼容性通常比直接填 SOCKS5 更好。
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
# 查看当前配置
git config --global --get-regexp 'http\..*proxy'
# 取消全局代理
git config --global --unset http.proxy
git config --global --unset https.proxy
如果只希望某一个代码托管域名经过代理,可以使用按域名匹配的配置,避免公司内部 Git 服务被送到外部节点:
git config --global http.https://code.example.invalid.proxy http://127.0.0.1:7890
git config --global https.https://code.example.invalid.proxy http://127.0.0.1:7890
实际使用中,全局代理最容易造成的副作用是:访问内网仓库、局域网制品库或本地测试服务也被代理。可以给内部地址设置空代理,或者使用环境变量的 NO_PROXY。如果公司仓库需要自签名证书,不要直接关闭 Git 的 SSL 校验;应先安装正确的企业根证书,否则代理与证书错误会混在一起,留下安全隐患。
SSH 仓库:使用 ~/.ssh/config 转发
SSH 远程地址常见形式是 [email protected]:team/project.git。Git 的代理字段对它不起作用,需要让 OpenSSH 通过 Clash 的 SOCKS5 入站建立 TCP 连接。macOS 与 Linux 通常自带 nc,可以在 SSH 配置中使用 -X 5 和 -x 参数:
Host code.example.invalid
HostName code.example.invalid
User git
Port 22
IdentityFile ~/.ssh/id_ed25519
ProxyCommand nc -X 5 -x 127.0.0.1:7890 %h %p
ServerAliveInterval 30
ServerAliveCountMax 3
配置文件路径是 macOS、Linux 下的 ~/.ssh/config,Windows OpenSSH 一般使用 C:\Users\你的用户名\.ssh\config。文件权限过宽时,OpenSSH 可能拒绝读取私钥或配置。Linux 与 macOS 可执行:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519
Windows 上如果系统没有可用的 nc,可以使用 OpenSSH 的 ProxyCommand 配合已安装的代理转发工具,或者直接开启 TUN 让 SSH 按系统路由连接。不要随意从网络复制来路不明的可执行文件。无论采用哪种方案,先用详细日志确认 SSH 是否确实经过代理:
ssh -vT [email protected]
日志中如果只停在 Connecting to ... port 22,通常是 TCP 连接没有建立;如果已经出现密钥协商、主机指纹或认证提示,说明代理转发至少已经生效,后续应转向检查密钥、账号权限或远端仓库权限。代码托管服务有时关闭 22 端口,可在服务允许的前提下使用 443 端口,但必须以对方提供的 SSH 入口为准:
Host code-ssh-443.example.invalid
HostName code-ssh-443.example.invalid
User git
Port 443
IdentityFile ~/.ssh/id_ed25519
ProxyCommand nc -X 5 -x 127.0.0.1:7890 %h %p
Homebrew、npm 与其他包管理器
包管理器的问题往往表现为“解析正常但下载慢”或“某一个依赖始终失败”。这类工具可能访问多个域名:索引地址、压缩包地址、二进制发布地址并不一定相同。只给主站配置代理,不代表所有依赖下载地址都能访问;需要同时查看工具当前的 registry、镜像和代理设置。
Homebrew:使用环境变量与诊断命令
Homebrew 在 macOS 与 Linux 上通常能读取终端代理环境变量。建议在当前会话中设置,先完成更新和安装验证,再决定是否写入 shell 配置文件:
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5h://127.0.0.1:7890
brew update
brew config
brew doctor
brew config 可以帮助确认 Homebrew 的版本、系统架构和相关路径,brew doctor 则用于发现权限、路径或环境异常。如果 brew update 通过,但安装某个 formula 仍失败,重点查看失败日志中的实际下载地址是否命中 Clash 规则。公式仓库、预编译 bottle 和源码依赖可能走不同域名,应根据日志逐项处理,不要盲目把所有流量切换到全局模式。
Homebrew 的仓库地址也可能使用 Git HTTPS 或 SSH。若仓库采用 HTTPS,前面设置的 Git 代理会生效;若采用 SSH,必须同时完成 SSH 的 ProxyCommand 配置。包管理器的下载代理与 Git 仓库代理是两套设置,一个正常不代表另一个正常。
npm:区分 registry、proxy 与 NO_PROXY
npm 可以通过配置文件或命令设置代理。建议先查看现有值,避免旧的失效代理覆盖环境变量:
npm config get registry
npm config get proxy
npm config get https-proxy
npm config get noproxy
npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890
npm config set noproxy "localhost,127.0.0.1,::1"
npm ping
npm view npm version
如果 npm 使用的是企业内部 registry,不要仅因为公共包下载慢就随意更换 registry。内部 registry 可能要求登录、特定证书或只能在办公网络访问。此时应把内部地址加入 noproxy,公共依赖是否经过 Clash 则根据网络策略决定。需要恢复 npm 默认代理时,可以删除对应配置:
npm config delete proxy
npm config delete https-proxy
npm config delete noproxy
pnpm、Yarn、pip、RubyGems 等工具的行为也有差异。多数 Python 工具读取 HTTP_PROXY 与 HTTPS_PROXY;Docker CLI 需要单独配置客户端代理;容器内部是否能访问宿主机的 127.0.0.1 还取决于容器网络,容器里的回环地址并不是宿主机地址。遇到容器下载失败时,不能直接把宿主机的 127.0.0.1:7890 原样复制进容器,应使用宿主机网关地址、Docker Desktop 的特殊主机名或在容器网络中明确暴露代理服务。
验证与排查:从端口到具体工具
配置完成后不要直接执行大型项目安装。按照从底层到上层的顺序测试,每一步只验证一个问题,可以迅速定位故障是在 Clash、DNS、代理协议、SSH 认证还是包管理器自身。
- 确认 Clash 客户端正在运行,当前配置已激活,代理端口与本文示例一致,并且日志窗口可以看到新连接。
- 确认本地端口可连接。macOS、Linux 可执行
nc -vz 127.0.0.1 7890;Windows PowerShell 可执行Test-NetConnection 127.0.0.1 -Port 7890。 - 使用
curl -v -x http://127.0.0.1:7890 https://example.invalid测试 HTTP CONNECT。若日志无记录,先检查端口;若有记录但连接失败,检查节点和规则。 - 执行
git ls-remote测试仓库访问。HTTPS 地址检查 Git 代理,SSH 地址检查ssh -vT与~/.ssh/config。 - 最后运行
npm ping、brew update或项目的依赖安装命令,观察失败时的具体域名与错误类型。
| 现象 | 优先检查项 | 处理方向 |
|---|---|---|
| 浏览器正常,Git HTTPS 超时 | Git 是否配置 http.proxy | 检查 git config --show-origin --get-regexp proxy,清理失效旧值 |
| Git HTTPS 正常,SSH 卡在连接阶段 | SSH 是否配置 ProxyCommand | 执行 ssh -vT,确认 SOCKS5 转发与端口 |
| SSH 已认证,执行 clone 仍失败 | 仓库权限与远程路径 | 检查公钥、账号、项目权限和仓库地址 |
| npm ping 成功,安装依赖失败 | 实际 tarball 下载域名 | 查看 npm 日志,确认下载域名也命中规则 |
| 所有工具都无法连接 | 节点、模式、DNS 与 TUN | 先切换可用节点,再关闭 TUN 做对照测试 |
| 只有内网服务异常 | 全局代理或 NO_PROXY | 把内网域名和网段加入例外,避免送入外部节点 |
日志排查时,不要只看“连接失败”四个字。connection refused 通常表示本地端口没有监听或端口被防火墙拒绝;timeout 可能是节点不可用、规则走错或远端端口被阻断;407 Proxy Authentication Required 表示代理要求认证,本地 Clash mixed-port 一般不应凭空出现这一错误;certificate verify failed 则属于证书链、系统时间或中间代理证书问题,不应通过关闭 TLS 校验来掩盖。
避免多层代理叠加
Clash 系统代理、终端环境变量、Git 独立代理、TUN 和其他 VPN 同时开启时,请求可能经过两层甚至三层转发。排查时先只保留 Clash,再逐项开启 Git 或 npm 配置。尤其不要把指向另一个本地代理端口的旧环境变量遗留在 shell 配置文件中。
可复用的日常工作流与安全边界
稳定配置不等于所有请求永远走代理。更合理的开发工作流是按目标拆分:公共代码托管、公共包索引和外部文档按规则进入代理;公司 Git、内网制品库、数据库、测试域名保持直连;本地服务使用 localhost 或 127.0.0.1 访问。这样既减少节点流量,也避免内网凭据和代码经过不必要的外部出口。
- 统一端口。让桌面客户端、shell 环境变量和 Git 配置使用同一个可记录的本地端口,切换客户端时只需修改一个值。
- 显式区分协议。HTTP 仓库使用
http.proxy,SSH 仓库使用ProxyCommand;不要用一种配置推断另一种配置已经生效。 - 为内网设置例外。通过
NO_PROXY、npm 的noproxy和 Clash 规则分别保护内网目标,例外范围尽量精确。 - 限制配置文件权限。SSH 私钥、订阅链接、代理认证信息和 npm token 都属于敏感凭据,不要提交到仓库,也不要放进公开日志。
- 切换节点后重新验证。不同节点的 DNS、IPv6、TCP 端口和访问区域可能不同,节点切换成功不代表所有开发服务都同样可用。
如果团队需要统一开发环境,可以把非敏感的代理初始化脚本放进个人 dotfiles,但不要把订阅地址、账号密码或私钥写进脚本。脚本中只保留本地端口变量,并提供明确的开启和关闭命令。关闭时应同时清理 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 以及 Git 的全局代理,否则终端可能继续尝试连接已经停止的本地端口。
# 关闭当前 shell 的代理变量
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY http_proxy https_proxy all_proxy
# 清理 Git 全局代理
git config --global --unset http.proxy
git config --global --unset https.proxy
完成一次完整配置后,建议记录四项信息:Clash 实际 mixed-port、Git HTTPS 代理命令、SSH Host 配置位置、包管理器是否使用独立 registry。以后更换 Clash 客户端或迁移电脑时,按这张清单恢复,比重新猜测“哪个工具应该自动走代理”更可靠。
常见问题
Git 配置了代理,为什么 SSH clone 还是超时?
Git 的 http.proxy 只影响 HTTP 和 HTTPS 传输,不影响 OpenSSH。SSH 地址需要在 ~/.ssh/config 中为对应 Host 设置 ProxyCommand,让 SSH 通过 Clash 的 SOCKS5 端口连接。使用 ssh -vT 查看详细日志,先区分连接阶段失败还是密钥认证失败。
HTTP 代理和 SOCKS5 代理应该选哪一个?
Git HTTPS、npm 和多数包管理器优先使用 http://127.0.0.1:7890 形式的 HTTP 代理;SSH 和支持通用套接字转发的工具可使用 socks5h://127.0.0.1:7890。关键不是协议名称更“高级”,而是工具是否支持该协议以及 Clash 是否在对应端口启用了入站服务。
开启 TUN 后,还需要配置 Git 和 npm 代理吗?
建议保留。TUN 适合接管不支持代理的应用,显式配置则便于查看工具状态、控制内网例外和在 TUN 关闭时继续使用。两者同时存在时,应确认没有指向其他代理端口的旧配置,避免重复转发。
npm 能 ping 通,但某个依赖仍然下载失败怎么办?
npm ping 主要验证 registry,依赖安装还会访问实际 tarball 地址。打开详细日志,找出失败的下载域名,检查该域名是否命中 Clash 规则、是否被加入 noproxy,以及当前节点是否能访问对应区域。不要只重复执行安装命令。