我使用不同的 git 存储库来从不同的上游来源(例如 GitHub.com、gitlab.com、自托管的 gitlab 等)克隆源代码版本,所有存储库都具有 SSH 密钥访问权限。git pull
始终有效,但在我使用以下方法创建新提交后
touch test && git add . && git commit -a -m "Test"
git push
在所有具有所有上游来源的存储库上都将始终超时。此后,涉及远程的所有其他 git 操作(git clone
、git pull
、...)也将超时,即使在具有不同 usptream 的其他存储库上也是如此。
但是,我默认使用 gpg 签名提交。如果我通过设置禁用该功能
git config --global commit.gpgsign false
删除我的具有新提交的本地存储库,再次克隆它们并创建新的未签名的提交,推动工作。
因此,这似乎与提交签名有某种关系。有什么想法吗?在我的另一台机器上,配置方式相同(相同的软件版本,相同的配置),推送签名的提交是可行的。
编辑:正如提交中所述,我使用未加密但提交消息较大的提交测试了这个问题,有趣的是,提交消息大小约为 4KB 时失败。所以这个问题可能与提交消息的大小有关?
编辑2:它奇怪地连接到我的网络接口的 MTU,如果我将其从 1500 降低到 500,一切正常。MTUgit push
为 1500 的失败会话的 Wireshark 转储如下所示:
有任何想法吗?
答案1
从您到 GitLab 服务器的路径上有一个 MTU 低于标准 1500 的链接。(这可能是任何路由器或最终服务器。)此外,
- 要么相关系统没有向您发送 ICMP“数据包太大”错误消息,
- 或者你的电脑没有收到它们(因为它们被中间的另一个路由器阻挡了),
- 或者您的计算机本身阻止/忽略它们(过度热心的 iptables)。
这会导致您的计算机在发送大型 IP 数据包(TCP 段)时卡住:它收不到 TCP ACK,但也没有收到 ICMP 错误指示,因此它所能做的就是不断重试。
(如果它有收到“数据包太大”ICMP 数据包,它会自动调整该特定目的地的 MTU 并以较小的片段重新发送数据包 - 这称为“路径 MTU 发现”。)
调查 PMTUD
将 MTU 重置为标准 1500,然后运行 Wireshark 或 tcpdump 捕获"icmp or icmp6"
数据包。在您再次尝试推送并且连接挂起后,数据包捕获应该会显示一些传入的 ICMP 数据包,或者只是传出的 TCP 重新传输。
如果您看到传入的 ICMP“数据包太大”响应,通常问题出在您自己的防火墙不必要地阻止了 ICMP。如果您不看到这个,问题出在更上游的某个地方。
(您也可以测试tracepath
GitLab 服务器,尽管此工具本身依赖于 ICMP,因此只有 PMTUD 已经在运行时它才会显示任何有用的信息。)
修复本地 ICMP 阻止
打开你的 iptables/nft 规则集,删除过于宽泛的“阻止所有 ICMP”规则(如果有)。(参见http://shouldiblockicmp.com/以获取需要允许的类型/子类型的列表。)
解决上行 MTU 问题的解决方法
在 Linux 上,除了基于 ICMP 的 PMTUD 之外,您还可以使用 TCP 级别的 MTU 发现:
sudo sysctl net.ipv4.tcp_mtu_probing=1
这并不依赖于任何错误响应,它只是告诉 TCP,每当它在发送大段后检测到数据包丢失时,它应该重新传输较小的段(而不是像以前一样重新发送)。 TCP 连接仍会挂起一两秒钟,然后调整其 MSS 并恢复。
您还可以使用 iptables“TCP MSS 钳制”使 TCP 连接从一开始就使用较低的最大段大小。