“Linux-Linux” 互联网上出现数据包丢失,但“Windows-Linux” 不会出现数据包丢失(tl;dr:这是 MTU)

“Linux-Linux” 互联网上出现数据包丢失,但“Windows-Linux” 不会出现数据包丢失(tl;dr:这是 MTU)

我现在正在与互联网上机器之间的数据包丢失现象作斗争,头发变得越来越白。

查看下图。请注意,每当我使用“SSH”时,我都可以使用“HTTPS”;该协议也会出现同样的现象。

运行 Fedora 22 的 SSH 服务器位于“站点 A”(酒红色)。直到“最近”,我从未遇到过任何连接问题。

从运行 Fedora 22 或 Fedora 23 的 Amazon EC2 机器到“站点 A”的 SSH 连接运行良好(“Amazon EC2”框内以绿色显示的主机)

在我测试的任何 Fedora 系统(橙色框)上,从位于同一 AS 上的“站点 B”到“站点 A”的 SSH 连接都不起作用。然而它们使用 Windows 7 系统运行Putty。两种情况都涉及相同的(双启动)硬件。“站点 B”也有防火墙,但似乎没有起到任何作用:我曾尝试直接从 FritzBox 路由器设置连接,但它仍然不适用于 Fedora,但适用于 Windows。

问题如何体现:

当您使用 SSH 连接时,会进行初始数据包交换(如 tcpdump 所示)。但是,在发送了大约 20 个数据包之后,传出的数据包似乎不再到达任何地方;站点 A 没有返回任何确认。您永远不会看到密码提示。CTRL-C 可以正确重置连接,之后 Linux 仍会尝试发送一段时间内从未确认的数据包。

设置

我怀疑我的 ISP 出现了问题,特别是我怀疑 ISP 为了在站点 B 实现“固定 IP 地址”而实施了可疑的魔法,这是“最近”唯一发生变化的东西。

但是,我不明白为什么在网络方面,在 Windows 上 SSH 连接可以工作,而在 Linux 上却不行。我应该寻找什么?

答案1

您的数据包跟踪显示:

22:29:22.180852 IP (tos 0x0, ttl 64, id 52989, offset 0, flags [DF], proto TCP (6), length 1900)   
SITE_B_LAN_ADDR.54358 > SITE_A.SSH_PORT: Flags [P.], cksum 0x05c4 (incorrect -> 0xadce), seq 22:1870, ack 22, win 229, options [nop,nop,TS val 4294917498 ecr 71539420], length 1848

注意,数据包的长度为 1900 字节,并且设置了不分段选项。典型的 MTU 往往在 1400-1500 字节之间。

您可能收到了数据包过大的 ICMP 消息,但是您在站点 A 防火墙处丢弃了所有入站 ICMP 流量。

为了测试这一点,您必须在防火墙上对 icmp 和 tcp 22 进行数据包跟踪。

确保允许 ICMP 数据包过大消息进入站点 A。

或者,您可以尝试将站点 A 上的 Linux 机器上的 MTU 设置为小于网络 MTU 的大小。我大胆猜测,在 Fedora 上您启用了巨型数据包,但在 Windows 上您没有启用。

答案2

根据评论者的建议,我查看了是否是 MTU 问题导致的。

尝试从 Fedora 系统连接“站点 A”到“站点 B”时发现以下情况。在 Windows 系统上,一切运行正常 - wireshark 指示传出数据包的长度从未超过 1158 字节,因此不会触发此问题。

简而言之,如果我没看错的话:

  1. 小数据包的交换初步成功。
  2. 发送了一个长度为 1900 的数据包。我猜网卡会将其分解,因为本地网络的 MTU 是 1500。
  3. ISP 网络中地址为 10.10.80.7 的路由器告诉我们“请将数据包分段为 MTU 1492”。
  4. 好的!长度为 1492 的数据包已发送。
  5. ISP 网络中地址为 10.10.80.7 的路由器告诉我们“请将数据包分段为 MTU 1492”。
  6. 事情从此开始每况愈下。

看起来我必须向 ISP 开一张票(顺便说一下,该 ISP 是 POST Telecom Luxembourg,以防有人在 Google 上搜索类似的问题)。

它还建议采取补救措施。强制将 SITE_A 的 MTU 设置为 1000:

ip route add $SITE_A_IP via $GATEWAY_IP dev $ETHDEV mtu lock 1000

确实,这解决了问题。

參考信息

用于ping测试 MTU 行为:

ping -c $COUNT -M $MTUDS -s $PPLSZ $HOST

在哪里

  • COUNT=1“仅一次 ping”
  • MTUDS=do:MTU 发现策略是“禁止碎片,即使是本地碎片”,即设置“DF”(不碎片)位(为什么是“做”?不知道)。使用这个。
  • MTUDS=want:MTU 发现策略是“进行 PMTU 发现,当数据包大小较大时在本地进行分片”,即设置‘DF’位并在本地进行分片
  • MTUDS=dont:MTU 发现策略为“不设置‘DF’位”,即按需分段
  • PPLSZ=1464:ICMP ping 数据包有效负载大小(以字节为单位)。

用于tcpdump监控所有 ICMP 数据包以及来自和发往“站点 A”的数据包:

tcpdump -vvv -n -nn icmp or '(' host $SITE_A_IP ')'

但这有点难以阅读。

观察内核对于“站点 A”的 MTU 的看法。

watch ip route get to $SITE_A_IP

请注意,第一次 ping 失败后,低于默认值的 MTU 将以 600 秒的 TTL 进行缓存。

设想

假设最大 IP 数据包大小(以字节为单位)(即以太网有效负载的大小)为 1492(Amazon EC2 上就是这种情况),则有趣的 ping 有效负载大小将是 1465,因为用于 IP 和 ICMP 标头信息的 28 字节将给出 1493,一个字节超过了最大值。

然后ping -c 1 -M want -s 1465 $HOST_IP执行以下操作:

在第一次 ping 时,您会收到“需要碎片并设置 DF(mtu = 1492)100% 数据包丢失”的信息。tcpdump显示回显请求第 1 部分(长度 1493)已发出,目标网络的路由器发回“ICMP 不可达”,并请求将碎片缩小至 MTU 1492。内核路由缓存中出现 MTU=1492 的缓存条目。

在后续 ping 中,您将获得“已发送 1 个数据包,已接收 1 个数据包”的结果。tcpdump显示回显请求第 1 部分(长度 1492)和回显请求第 2 部分(长度 21,偏移量 1472)以及相应的回显答复(长度 1493)。

或者您可以使用 traceroute

# traceroute --mtu SITE_A 1500

数据包大小为 1500。Traceroute 告诉我们路由 10.10.80.7 的 MTU 为 1492

traceroute to SITE_A (SITE_A_IP), 30 hops max, 1500 byte packets
 1  gateway (192.168.10.1)  0.550 ms  0.536 ms  0.393 ms
 2  192.168.178.1 (192.168.178.1)  1.458 ms  1.485 ms  1.344 ms
 3  10.10.80.7 (10.10.80.7)  4.889 ms F=1492  2.968 ms  4.854 ms
 4  10.10.80.7 (10.10.80.7)  4.955 ms !F-1492  3.559 ms !F-1492  5.022 ms !F-1492

尝试 1492:同样的问题!

traceroute to SITE_A (SITE_A_IP), 30 hops max, 1492 byte packets
 1  gateway (192.168.10.1)  0.635 ms  0.554 ms  0.483 ms
 2  192.168.178.1 (192.168.178.1)  1.510 ms  1.504 ms  1.311 ms
 3  10.10.80.7 (10.10.80.7)  48.305 ms  17.436 ms  5.496 ms
 4  10.10.80.7 (10.10.80.7)  5.963 ms !F-1492  6.865 ms !F-1492  4.887 ms !F-1492

尝试 1491:同样的问题!

traceroute to SITE_A (SITE_A_IP), 30 hops max, 1491 byte packets
 1  gateway (192.168.10.1)  0.594 ms  0.650 ms  0.492 ms
 2  192.168.178.1 (192.168.178.1)  1.716 ms  1.782 ms  1.580 ms
 3  10.10.80.7 (10.10.80.7)  7.327 ms  7.385 ms  4.775 ms
 4  10.10.80.7 (10.10.80.7)  5.210 ms !F-1492  5.624 ms !F-1492  4.841 ms !F-1492

尝试 1490:我们成功了。那里肯定会有一些差一错误。

traceroute to SITE_A (SITE_A_IP), 30 hops max, 1490 byte packets
 1  gateway (192.168.10.1)  0.616 ms  0.688 ms  0.484 ms
 2  192.168.178.1 (192.168.178.1)  1.712 ms  1.853 ms  1.611 ms
 3  10.10.80.7 (10.10.80.7)  6.248 ms  7.008 ms  4.995 ms
 4  SITE_A_IP.dyn.luxdsl.pt.lu (SITE_A_IP)  12.441 ms !X  9.641 ms !X  9.576 ms !X

更多感兴趣的信息:

相关内容