我可以通过 ssh 访问服务器 A,并且可以从服务器 A 访问服务器 B,该服务器运行 gitlabs 并包含我需要访问的存储库。当我通过 ssh 连接到服务器 A 时,我可以git clone http://serverB/path/to/repo.git
成功运行。使用ssh://
或git://
代替http://
不起作用。(错误分别是“似乎不是 git 存储库”和“无法连接到服务器 B”。)
如果我建立这样的隧道:
ssh username@serverA -L 3333:serverB:80 -N
以下两次 git clone 尝试均失败:
git clone http://localhost:3333/path/to/repo.git
失败并显示:“致命:未找到存储库”
git clone localhost:3333/path/to/repo.git
提示我输入 serverB 的密码,然后失败并显示“fatal: 3333/path/to/repo.git 似乎不是 git 存储库”。当然不是!我尝试指定 localhost、端口 3333,但显然被解释为 serverB 上的相对路径。
有办法解决这个问题吗?这种方法从根本上来说有什么问题吗?
答案1
为什么不起作用
http://localhost:3333/path/to/repo.git
这会失败,因为 URL 的主机名不同(localhost
vs server2
),因此服务器使用不同的配置。
所有 HTTP 客户端都会将请求的主机名发送到服务器,服务器可以根据该名称从多个配置(虚拟主机)中进行选择。这就是托管服务提供商可以共享同一 IP 地址的网站数量(通常是数百个)。
localhost:3333/path/to/repo.git
失败的原因是不是HTTP URL,或者实际上是任何 URL。(Git 不是 Web 浏览器,http://
默认情况下不假设。)
相反,它是一个 rcp 样式的 SSH 地址,形式为[user@]host:path
。您可能之前已经看到过它[email protected]:foo/bar.git
,其中ssh@
前缀实际上只是一个 SSH 用户名。
Git 将其视为与ssh://[user@]host[:port]/path
URL 等效,只是 rcp 样式的地址根本没有端口字段。
该怎么办
Git 使用的 HTTP 客户端 curl 支持ssh -D
动态隧道提供的 SOCKS 代理。
使用以下命令设置动态(SOCKS)隧道:
ssh username@serverA -D 1080 -N
配置 Git 以使用它作为代理:
全局(或每个存储库):
git config [--global] http.proxy socks5://localhost:1080
对于单个命令:
git -c http.proxy=socks5://localhost:1080 clone http://serverB/repo.git
socks5
和协议socks4
在客户端执行 DNS 解析,而socks5h
和socks4a
通过 SOCKS 将所有主机名传递到 SSH 服务器。