Clash Fake-IP 模式下 Git SSH 连接失败

问题现象

执行 git fetch --all 报错:

1
2
Connection closed by 198.18.0.35 port 22
fatal: Could not read from remote repository.

排查过程

1. 确认 remote 地址

1
2
git remote -v
# origin  git@github.com:ZJNU-Lab-29202/detection-saas.git

使用的是 SSH 协议。

2. 排查 DNS 解析

1
2
3
nslookup github.com
# Name:   github.com
# Address: 198.18.0.35

198.18.0.35 不是 GitHub 真实 IP,属于 198.18.0.0/15 保留段。这是 Clash Fake-IP 模式 的典型特征——DNS 返回虚拟 IP,由 Clash 透明代理接管流量。

3. 确认 Clash 运行状态

1
2
3
ss -tlnp | grep 789
# LISTEN  *:7890   # HTTP 代理
# LISTEN  *:7891   # SOCKS5 代理

Clash (mihomo) 正在运行,HTTP 代理端口 7890,SOCKS5 端口 7891,均开启了 Basic 认证。

4. 尝试 SSH ProxyCommand

~/.ssh/config 中为 github.com 添加 ProxyCommand:

1
2
3
Host github.com
    HostName github.com
    ProxyCommand ncat --proxy-type http --proxy 127.0.0.1:7890 --proxy-auth kerolt:xxxxxx %h %p

ncat 能成功建立 CONNECT 隧道(exit 0),但 SSH 握手阶段被远端关闭:

1
2
debug1: Local version string SSH-2.0-OpenSSH_10.2
kex_exchange_identification: Connection closed by remote host

结论: Fake-IP 模式下,即使通过 HTTP CONNECT 代理转发 SSH 流量,也无法完成完整的 SSH 握手。Clash 对 SSH 流量的透明代理处理存在问题。

解决方案

方案一(推荐):改用 HTTPS + Git 代理

1
2
3
4
5
6
7
8
9
# 1. 配置 git 全局 HTTPS 代理(含 Clash 认证)
git config --global http.proxy http://kerolt:<password>@127.0.0.1:7890
git config --global https.proxy http://kerolt:<password>@127.0.0.1:7890

# 2. 将 remote 从 SSH 改为 HTTPS
git remote set-url origin https://github.com/<owner>/<repo>.git

# 3. 验证
git fetch --all

注意: GitHub 已不支持密码认证,push 时需要 Personal Access Token (PAT)。可以配置:

1
git config --global url."https://<TOKEN>@github.com/".insteadOf "https://github.com/"

方案二:Clash 切换为 Redir-Host 模式

在 Clash 配置中将 fake-ip 改为 redir-host,让 DNS 返回真实 IP,SSH 就能正常走透明代理。但这可能影响其他依赖 Fake-IP 的功能。

方案三:使用 SOCKS5 代理工具

安装 connect-proxysocat 等工具替代 ncat,部分工具对 SOCKS5 代理的 SSH 转发支持更好。

核心原因总结

环节说明
Clash Fake-IPDNS 返回虚拟 IP 198.18.0.x,依赖透明代理接管流量
SSH 协议不是 HTTP,无法被 HTTP 代理直接转发
CONNECT 隧道可以建立 TCP 隧道,但 SSH 握手阶段被阻断
HTTPS 方案Git over HTTPS 是标准 HTTP 流量,Clash 代理完美支持
使用 Hugo 构建
主题 StackJimmy 设计