1. 问题描述
在使用 ssh -vT git@github.com 测试连接时,进程卡死(Hang)在本地版本发送阶段,无法完成握手。
典型报错日志:
Plaintext
debug1: Executing proxy command: ...
debug1: Local version string SSH-2.0-OpenSSH_9.6p1...
# (在此处无限卡顿,最终超时或 Connection closed)
2. 根本原因分析 (Root Cause)
即使代理网络连通性正常(手动测试 nc 或 connect 显示 Connected),SSH 依然可能失败,主要原因有两个:
- 工具兼容性问题 (
nc):- Ubuntu 默认的
nc(netcat-traditional) 不支持 BSD 风格的-X(协议) 和-x(代理) 参数。 - 即便手动运行成功,
nc在作为ProxyCommand管道运行时,常因缓冲机制(Buffering)导致数据流无法及时回传给 SSH 客户端,造成“假死”。
- Ubuntu 默认的
- 端口干扰 (Port 22 Blocking):
- 某些代理环境或防火墙会对标准 SSH 端口 (22) 进行 DPI (深度包检测) 或流量干扰。
- 表现为:TCP 连接能建立(Connected),但数据包无法正常往返,导致 SSH 握手无法完成。
3. 最终解决方案 (Best Practice)
核心策略:
- 弃用
nc,改用专为 SSH 代理设计的connect-proxy工具(更稳定)。 - 弃用端口 22,改用 GitHub 提供的
ssh.github.com:443(伪装成 HTTPS 流量,抗干扰能力极强)。
步骤一:安装工具
确保系统安装了 connect-proxy(Ubuntu/Debian 标配工具):
Bash
sudo apt update
sudo apt install connect-proxy
步骤二:配置 ~/.ssh/config
直接覆盖或修改对应 Host 配置:
Code snippet
Host github.com
# 1. 强制使用 SSH over HTTPS 的专用域名
HostName ssh.github.com
# 2. 强制使用 443 端口,绕过防火墙/ISP 对 22 端口的限制
Port 443
User git
# 3. 身份验证文件
IdentityFile ~/.ssh/ranger_secret
IdentitiesOnly yes
# 4. 代理命令 (ProxyCommand)
# -S: 指定 SOCKS5 代理
# 使用绝对路径 /usr/bin/connect 避免环境变量问题
# %h %p: 自动填充上面的 HostName (ssh.github.com) 和 Port (443)
ProxyCommand /usr/bin/connect -S 10.0.3.233:10809 %h %p
4. 排查过程回顾 (Troubleshooting Log)
| 阶段 | 尝试方案 | 结果 | 结论 |
|---|---|---|---|
| P1 | 使用 nc -X 5 -x ... |
卡死在 Local version string |
Ubuntu 版 nc 参数不支持或管道流处理有问题。 |
| P2 | 手动运行 nc -v ... |
成功 (Succeeded) | 证明网络和代理 IP 是通的,问题出在非交互式运行环境或端口数据流。 |
| P3 | 尝试 ncat |
报错 command not found |
ncat (Nmap工具) 需额外安装,非首选。 |
| P4 | 尝试 connect (Port 22) |
连接建立但 SSH 仍卡死 | 工具没问题了,但 Port 22 数据链路存在“黑洞”或干扰。 |
| P5 | 切换 Port 443 + connect | 成功 | 确认为端口干扰问题,443 端口完美解决。 |
5. 关键知识点 (Key Takeaways)
- GitHub 的隐藏入口:GitHub 官方允许通过
ssh.github.com的443端口进行 SSH 连接。如果你在公司内网、由于防火墙限制无法访问 22 端口,这是标准解法。 - ProxyCommand 的调试:当 SSH 卡住时,不要只看 SSH 的 log。先用终端手动运行 ProxyCommand 中的命令(如
connect -d ...),看能否建立 TCP 连接。 - 工具选择:在 Linux 上配置 SSH 代理,优先使用
connect-proxy或ncat,尽量避免使用nc(版本变种太多,坑多)。