◆

GitHub SSH 拉取代码慢用 443 端口加速

2023-02-02 01:370

我们用 SSH 协议拉 github 代码时,默认连的是 github.com 的 22 端口。这个端口在国内的网络环境里很容易被中间设备干扰,典型表现不是连不上,而是能握手、能进入 Receiving objects 阶段,然后速度掉到几 KB/s 甚至彻底卡死。因为 SSH 不像 HTTPS 那样会走系统代理,所以哪怕我们开着代理、浏览器打开 github.com 飞快,git clone 还是慢。

GitHub 官方为这种情况准备了一个备用入口 ssh.github.com,监听在 443 端口上。走的仍然是 SSH 协议,只是换了个几乎不会被拦的端口号,不需要改仓库地址,也不需要改成 HTTPS 拉取。下面记录我切换的完整过程,以及中间踩到的一个容易误判的坑。

场景

在公司使用 ssh 拉取 github 代码很快,但是在家中却不行。

同一个仓库、同一台电脑,只是换了出口网络,git clone 从几 MB/s 变成个位数 KB/s。这基本可以排除仓库本身和本地磁盘的问题,问题出在链路上:公司出口对 22 端口的 SSH 流量放行得比较干净,家用宽带这一段则会被干扰。

尝试修改配置

文件位置 /Users/miofly/.ssh/config

这是 SSH 客户端的用户级配置文件,git 走 SSH 拉代码时会读它。文件没有默认内容,不存在就自己新建,权限建议是 600(chmod 600 ~/.ssh/config),权限过于开放时 ssh 会拒绝加载。

修改上述文件的配置,如果不存在就创建一个。我的配置如下

Host github.com
  User git
  Port 22
  Hostname ssh.github.com
  # 注意修改路径为你的路径
  IdentityFile "/Users/miofly/.ssh/id_rsa"
  TCPKeepAlive yes

逐行说明这几个字段的作用:

  • Host 是匹配规则,我们在命令行里写的主机名命中它,后面的配置才会被应用;
  • HostName 是真正去连的地址,它可以和 Host 不一样,这正是端口转换能生效的关键;
  • User git 指定登录用户,GitHub 的 SSH 一律用 git 这个用户,认证靠密钥而不是密码;
  • IdentityFile 指定私钥路径,只有一把默认密钥时可以省略,多账号多密钥时必须写清楚;
  • TCPKeepAlive yes 让客户端定期发送保活包,避免长时间传输大仓库时被中间的 NAT 设备静默断开。

上面这份配置仍然写着 Port 22,所以只是把目标域名换成了 ssh.github.com,端口没变,链路上被干扰的那一段并没有绕开。

上面的方式突然拉取又变慢了,改了个 Host 和 Port,感觉和 Host 可能没关系,具体什么原因未知,使用 443 端口拉取又正常了。

Host ssh.github.com
  User git
  Port 443
  Hostname ssh.github.com
  # 注意修改路径为你的路径
  IdentityFile "/Users/miofly/.ssh/id_rsa"
  TCPKeepAlive yes

更通用的写法

上面这份配置的 Host 写的是 ssh.github.com,意味着只有当我们把仓库地址也写成 git@ssh.github.com:xxx/yyy.git 时才会命中。已有仓库的 remote 里存的通常是 git@github.com:xxx/yyy.git,那就匹配不上,改了等于没改。

想让所有已存在的仓库都自动走 443,把 Host 写成 github.com,靠 HostName 做地址替换:

Host github.com
  HostName ssh.github.com
  User git
  Port 443
  IdentityFile "/Users/miofly/.ssh/id_rsa"
  TCPKeepAlive yes

这样我们不用动任何仓库的 remote,git 照旧解析 github.com,ssh 在实际建连时把它换成 ssh.github.com:443。

验证是否生效

改完先单独测一次连通性,不要直接拿大仓库试:

ssh -T git@github.com

看到 Hi <用户名>! You've successfully authenticated 就说明密钥和端口都没问题。想确认它究竟连到了哪个地址和端口,加 -v 看握手细节:

ssh -Tv git@github.com 2>&1 | grep -i 'connecting to'

输出里应该出现 Connecting to ssh.github.com port 443。如果显示的还是 github.com port 22,说明 Host 没匹配上,检查缩进和拼写。

几个边界情况

443 端口只对 github.com 这套官方入口有效,gitlab.com 之类的服务有各自的备用端口,不能照抄。公司内网如果对 443 做了 HTTPS 深度检测,也可能拦下这种伪装在 443 上的 SSH 流量,这时反倒是走 HTTPS 加代理更稳。

另外这个方案和给 git 配 HTTP 代理是两条互不相干的路:git config --global http.proxy 只影响 https:// 开头的远程地址,对 SSH 远程完全无效。SSH 想走代理得在 ~/.ssh/config 里配 ProxyCommand,和这里的换端口属于二选一,一般换端口就够了,配置更少也更不容易出错。

💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVEGitHub SSH 拉取代码慢用 443 端口加速加载中