[2022.03] GitHub 加速终极教程
阅读完此文后,建议读者阅读我在 V2EX 发表的 **[这篇帖子](https://www.v2ex.com/t/843383)** ,评论区有其他网友分享的很好的意见值得参阅 :)
本文意图解决使用 GitHub 访问(https) 或者 git clone(https or ssh)慢的问题。在此分享我的方法,我所了解的 GitHub 加速最佳方案。
前提是,你的木弟子应该还行,木弟子越好,GitHub 体验越好
很多文章没有讲全面,只讲了 http proxy,而没有讲 ssh proxy。事实上大部分程序员使用 GitHub 都会使用 SSH keys(普通用户可能就不会了),在本机生成 rsa
公私钥(其他的类型还有 dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk),然后把公钥内容拷贝、设置进 GitHub。
所以程序员 clone 一个仓库一般是 ssh clone 而不是 https clone
$ git clone git@github.com:xxx/yyy.git
如果你不配置 ssh 代理或者没有透明代理之类的网络环境(其实还有一些代理工具,不过更加小众),直接硬拖到本地大概率是很慢的。如果使用 http 代理,如果木弟子质量好,其实也还行
$ git clone https://github.com/xxx/yyy.git
但这样不如 ssh clone 稳定。下面我们来设置 http proxy 和 ssh proxy。
设置 Http Proxy
$ git config --global http.proxy socks5://127.0.0.1:7890
因为 git 底层使用 libcurl 发送 http 请求,而 libcurl 的代理使用 socks5:// 时会在本地解析 DNS,实际使用中我们希望 DNS 也在远程(也就是可以访问 google 的代理节点)解析,所以使用 socks5h ,即
$ git config --global http.proxy socks5h://127.0.0.1:7890
h 代表 host,包括了域名解析,即域名解析也强制走这个 proxy。另外不需要配置 https.proxy
,这些 git server 都会配置 http redirect to https。
推荐使用 socks5 代理,因为 socks5 包含 http(s)。而且 socks5 代理工作在 osi 七层模型中的会话层(第五层),https/http 代理工作在 osi 七层模型的应用层(第七层), socks 代理更加底层。所以就没必要配置 git config --global http.proxy http://127.0.0.1:7890
了。
RFC1928 中有下面这段话
The protocol described here is designed to provide a framework for
client-server applications in both the TCP and UDP domains to
conveniently and securely use the services of a network firewall.
The protocol is conceptually a "shim-layer" between the application
layer and the transport layer, and as such does not provide network-
layer gateway services, such as forwarding of ICMP messages.
这段话是说 “该协议在概念上是应用层和传输层之间的“填充层”,因此不提供网络层网关服务,例如转发 ICMP 消息。” 看上去是没有明确表示是表示层(第 6 层)和传输层(第 4 层)之间的第五层,但是这个“填充层” SOCKS 条目的 wikipedia 中有补充是会话层(第 5 层)。见 https://en.wikipedia.org/wiki/SOCKS
SOCKS performs at Layer 5 of the OSI model (the session layer, an intermediate layer between the presentation layer and the transport layer). A SOCKS server accepts incoming client connection on TCP port 1080, as defined in RFC 1928.
好了,说回来。但这样配置的话会使本机所有的 git 服务都走了代理,假如你在良心云上(国内主机)部署了自己的 gitea,服务地址 https://gitea.example.com
,那么可以只配置 GitHub 的 http proxy,即
$ git config --global http.https://github.com.proxy socks5://127.0.0.1:7890
这样做实际上是修改了 ~/.gitconfig
文件,添加了如下内容
1[http "https://github.com"]
proxy = socks5://127.0.0.1:7890
设置 SSH Proxy
Linux & macOS
配置文件在用户家目录下的 .ssh/config 其中 nc
程序位于 /usr/bin/nc
12345$ cat ~/.ssh/config
Host github.com
Hostname ssh.github.com
IdentityFile /xxx/.ssh/github_id_rsa
User git
Port 443
ProxyCommand nc -v -x 127.0.0.1:7890 %h %p
nc 就是 netcat,引用一段描述
netcat is a simple unix utility which reads and writes data across network connections, using TCP or UDP protocol. It is designed to be a reliable "back-end" tool that can be used directly or easily driven by other programs and scripts. At the same time, it is a feature-rich network debugging and exploration tool, since it can create almost any kind of connection you would need and has several interesting built-in capabilities. Netcat, or "nc" as the actual program is named, should have been supplied long ago as another one of those cryptic but standard Unix tools.
译文: netcat 是一个简单的 unix 实用程序,它使用 TCP 或 UDP 协议跨网络连接读取和写入数据。 它被设计成一个可靠的“后端”工具,可以直接使用或由其他程序和脚本轻松驱动。 同时,它还是一个功能丰富的网络调试和探索工具,因为它几乎可以创建您需要的任何类型的连接,并且具有几个有趣的内置功能。 Netcat,或实际程序命名的“nc”,早就应该作为另一种神秘但标准的 Unix 工具提供。
Windows
Win 下与之对应的 netcat 程序是 connect.exe
,程序位于 Git 安装路径 C:\Program Files\Git\mingw64\bin
,win 下推荐使用 Git Bash,路径也是 Linux style
因为 connect 程序内置在 Git 中,只要是正常安装 Git 的电脑环境都有这个程序,在 Git Bash 终端输入 connect
即可知晓程序路径在 C:\Program Files\Git\mingw64\bin\connect.exe
12345$ connect
connect --- simple relaying command via proxy.
Version 1.105
usage: C:\Program Files\Git\mingw64\bin\connect.exe [-dnhst45] [-p local-port]
[-H proxy-server[:port]] [-S [user@]socks-server[:port]]
[-T proxy-server[:port]]
[-c telnet-proxy-command]
host port
Win 下的配置写法如下
12345$ cat ~/.ssh/config
Host github.com
Hostname ssh.github.com
IdentityFile /c/users/xxx/.ssh/github_id_rsa
User git
Port 443
ProxyCommand connect -S 127.0.0.1:7890 %h %p
补充信息
Q&A 1
为什么 hostname 是 ssh.github.com
,为什么要用 443 端口,ssh 默认不是 22 端口么?
因为有些木弟子对于 22 端口做了限制,要么禁止了,要么有些抽风,这时经常会遇到如下错误
kex_exchange_identification: Connection closed by remote host
所以如果 22 端口不畅就使用 443,安全稳定可靠。ps: 22 端口时 hostname 请填 github.com
。这部分请扩展阅读 此文 。
Q&A 2
如果代理设置了用户名和密码基础认证呢?比如 clash 的 config.yaml
中就可以添加如下配置以增加 http 基础认证
1authentication:
- "USERNAME:PASSWORD"
那么写成 ProxyCommand nc -v -x USERNAME@127.0.0.1:7890 %h %p
执行命令的时候终端会让输入密码。
经测试,写成 ProxyCommand nc -v -x USERNAME:PASSWORD@127.0.0.1:7890 %h %p
不行,会把 USERNAME:PASSWORD
识别成用户名。不用输入密码的方案我暂时没找到。
至于网页访问 GitHub,借助木弟子访问已然是日常,要么浏览器扩展 SwitchyOmega
,要么系统代理,要么直接使用 Clash 的分流策略等等。我的习惯还是使用 Switchy Omega。
这样配置之后 git clone https://github.com/xxx/yyy.git
或者 git clone git@github.com:xxx/yyy.git
以及 git pull
、git push
等等操作都很快了,除非科学的工具或节点不行。
难免有误,欢迎大家补充和斧正。

windows下配置
~/.ssh/config
如下:Host github.com Hostname ssh.github.com Port 443 User git ProxyCommand "E:\Git\mingw64\bin\connect.exe" -S 127.0.0.1:7890 %h %p
使用的代理软件是clash,开启rule模式可以在浏览器上访问github网站。
您好,我采用的是您的ssh代理方案,并
ssh -T git@github.com
能得到Hi xxx! You've successfully authenticated, but GitHub does not provide shell access.
。但是在push 项目(接近一个G)时仍然卡在Writing objects: 12% (184/1517)
,尝试了网络上git config --global http.postBuffer 524288000
,还是不行。请问有啥解决方案或者思路吗?万分感谢
我猜想可能是push没有走代理?
127.0.0.1:7890
的7890 是http/https 还是 http/https/socks5?多种协议合并到了 7890服务的吗?我把 http/https 和 socks 放在不同的端口服务的。比如 7891 专门服务 socks5。你这个情况 push 应该走了代理,因为执行
ssh -T git@github.com
返回了认证成功。不放心的话可以执行ssh -vT git@github.com
观察输出,应该有Authenticated to ssh.github.com (via proxy) using "publickey".
从这句可以看到是通过 proxy 连接到的ssh.github.com:443
看你的日志,因为git传输数据过大,1G的项目,问题应该出在梯子节点不稳定,换个香港或者日本或者新加坡俄罗斯这些物理距离近一些的节点试试看。美国节点太绕了。
万分感谢您的快速回复。
我使用的clash 中主页展示的是
端口 更新混合端口 mixed=http+socks 新端口 7890
但是我在yaml配置文件中开头看到的是:
port: 7890
socks-port: 7891
redir-port: 7892
allow-lan: false
mode: Rule
log-level: silent
并且在文件中搜索
mixed
没匹配到结果我这个到底是分开的还是混合的啊?
求教,万分感谢。
其实这有点本末倒置了。你的问题出在节点而不是clash的配置。让 socks5 单独使用一个端口并没有多大的提升,要想http/socks分开服务,clash 主界面就能设置的。另外节点用的不是 socks 协议,节点一般是 ss/ssr/trojan/v2ray那些协议。
总之你的问题在节点,和clash怎么配置关系不大,你就现在这样的配置即可,关键在找到最优节点,或者更换机场,你的机场提供的节点都太差了。
clash 页面上显示的应该是对的。你看的 yaml 配置文件不一定是当前 clash 主配置引用的 yaml 配置文件。可以在本地用 curl 检查一下实际服务的端口是什么。
通过
curl -x http://localhost:7890 http://www.google.com -v
检查本地 7890 是否有开启 http 代理。通过
curl --socks5 localhost:7891 http://www.google.com -v
检查本地 7891 端口是否有开启 socks5 代理。检查返回即可,如果 google 服务器有返回 html 内容或者有 http 状态码(比如给你301了)说明目标代理工作正常。
通过您给定的方法,我注意到7890有http,但是7891没有socks 。但是7890有socks(也就是我的clash是http和socks共用端口)。我想知道如何配置clash才能像您说的那样将两个协议的端口分开?
我使用的梯子节点是shadowsocks,这个节点使用的是socks协议吧,那假设我成功将http和socks 协议的端口分开了,我的config文件应该如何配置?
期待您的回复,打扰了
SSH Proxy 配置中的 nc 命令有参数不对,按上面的配置实际还是直连 ssh.github.com 并没有通过代理
Host github.com Hostname ssh.github.com IdentityFile /xxx/.ssh/github_id_rsa User git Port 443 #ProxyCommand nc -v -x 127.0.0.1:7890 %h %p 就改为 ProxyCommand nc -v --proxy-type socks5 --proxy
Host github.com Hostname ssh.github.com IdentityFile /xxx/.ssh/github_id_rsa User git Port 443 #ProxyCommand nc -v -x 127.0.0.1:7890 %h %p 改为 ProxyCommand nc -v --proxy-type socks5 --proxy 127.0.0.1:7890 %h %p
我的配置是能工作的,我在多台机器上测试过提交,也能看到是走代理的节点连上的 ssh.github.com
不过你的命令看起来更具体,似乎也行
感谢,感谢😁,今天代码一直提交不上,用代理 ssh 方式成功了,还好我之前收藏了该文章,今天遇到这个问题,直接照着您的文章操作就解决了。
🍻️🍻️🍻️
感谢,我是在电脑新增了ssh配置后无法正常连接了?
使用 ssh 访问 GitHub 的体验真的很流畅丝滑。包括了网页和终端。
非常感谢你大佬,我被这个问题折磨了一天到处搜解决方法快崩溃了!你的方法解决了我的问题,再次感谢!?
非常开心能帮上忙
也许能试试通过https的方式访问仓库,然后通过github的personal access token来进行验证。之后通过git-credential-manager这个项目来对自己的token进行保存连接试试,因为用的是http所以代理的问题也很容易解决了,个人用起来还蛮方便的。
٩(ˊᗜˋ*)و如果是因为密钥交换的安全性问题就当我没说啦~(感觉Github的PAT应该也蛮安全的)
蛮好的,这也是一种方法,有空我试试看,多谢OωO
2022-03-28 21:18:32 更新
本条评论可以忽略了,直接写
connect
就能解决问题。不知道为什么办公室电脑这样做不行,晚上回家拿台式机测试,不论是 PowerShell 还是 Git Bash 这样写都能正常执行 git 命令。所以 win 下 正确的写法是:
$ cat ~/.ssh/config Host github.com Hostname ssh.github.com IdentityFile /c/users/xxx/.ssh/github_id_rsa User git Port 443 ProxyCommand connect -S 127.0.0.1:7890 %h %p
本条评论我就不删我自己了……
======
经过测试发现 Git Bash 对于路径中含有空格的可执行程序有 bug,可参考这个 issue
如果要想在 windows 上使用
connect.exe
通过代理 clone ssh 协议下的 GiHub 项目,那么就改成 win 的路径风格(如果路径中有空格就把整个路径用英文双引号包裹),然后使用cmd
或powershell
clone 吧,git bash 我还没找到一个好的方案。$ cat ~/.ssh/config Host github.com Hostname ssh.github.com IdentityFile c:\users\xxx\.ssh\github_id_rsa User git Port 443 ProxyCommand "C:\Program Files\Git\mingw64\bin\connect.exe" -S 127.0.0.1:7890 %h %p
这样 git clone 是可以的。
我甚至使用了软链接(Git Bash 中是可以创建软链接的)
$ ln -s /c/Program\ Files/Git/mingw64/bin/connect.exe /d/ssh-connect
然后 ProxyCommand 中使用 /d/ssh-connect 还是不行。沮丧 ?️