MTU + ~798 字节的 POST 丢失

Hal*_*aar 5 networking ip tcp mtu

我有一个非常奇怪的问题,某些数据包没有到达目标主机。当我们传输比 MTU 稍大的 POST 时,就会发生这种情况。我们可以用这个脚本重现它:

#!/usr/bin/python

import urllib2

magic_length = 2297
logurl = 'http://www.example.nl/'
data = (magic_length - len(logurl)) * 'X'
headers = {'content-type': 'application/x-www-form-urlencoded', 'User-Agent': 'Fake'}
request = urllib2.Request(logurl, data, headers)                                        
handler = urllib2.build_opener(urllib2.HTTPHandler())                                   
answer = handler.open(request, timeout=5)
Run Code Online (Sandbox Code Playgroud)

发送方没有收到 ACK 并进行重传。接收方永远不会看到它。

这取决于您运行脚本的位置以及 POST 的位置。我的家庭连接失败了(顺便说一句,几个月以来我遇到了 AJAX POST 无法通过的问题;因为我有一个新的调制解调器)。

如果我将发送机器的 MTU 减少 100,它会再次工作。但是,如果我也减少magic_length100,它会再次失败。第一个理论是我的 ADSL 层(如 PPPoA)添加了标头并导致数据包被错误地拆分,但当时似乎并非如此。

也许 MTU 发现出了问题。有些人可能会阻止所有ICMP?这是从我家到 google 的 traceroute 的第一部分:

traceroute to google.com (74.125.133.102), 30 hops max, 60 byte packets
 1  dsldevice.lan (192.168.2.254)  0.453 ms  0.547 ms  0.636 ms
 2  195.190.243.7 (195.190.243.7)  29.836 ms  29.947 ms  29.986 ms
 3  nl-zl-dc2-git-cr02.kpn.net (213.75.64.237)  37.004 ms  37.153 ms  37.204 ms
 4  nl-rt-dc2-ice-ir02.kpn.net (213.75.64.236)  37.261 ms  37.300 ms  37.339 ms
 5  72.14.198.161 (72.14.198.161)  38.351 ms  38.395 ms  38.405 ms
 6  209.85.254.92 (209.85.254.92)  37.976 ms  38.103 ms  37.972 ms
 7  209.85.253.247 (209.85.253.247)  38.612 ms 72.14.238.153 (72.14.238.153)  33.709 ms 209.85.253.249 (209.85.253.249)  36.890 ms
 8  209.85.240.158 (209.85.240.158)  41.052 ms  41.104 ms 209.85.244.102 (209.85.244.102)  41.164 ms
 9  209.85.249.12 (209.85.249.12)  38.392 ms 209.85.249.14 (209.85.249.14)  38.247 ms  38.851 ms^C
Run Code Online (Sandbox Code Playgroud)

如果我 ping 213.75.64.237,我得到(我从来没有真正看到“数据包过滤”作为对 STDOUT 的响应......):

PING 213.75.64.237 (213.75.64.237) 56(84) bytes of data.
From 213.75.64.237 icmp_seq=1 Packet filtered
Run Code Online (Sandbox Code Playgroud)

其余的我可以ping通。

这个答案似乎很相似。但是,我的脚本没有设置 DF(不分段)标志(编辑:更正,tcpdmp 确实显示在 POST 请求上设置了该标志),当我运行时,我也看不到 ICMP 请求返回给我脚本主机上工作。另外,数据包已经被发送方拆分,发送第二个数据包失败。

我该如何进行?ISP 的 NOC 很难达到,所以我需要有证据证明发生了什么。他们不会帮我弄清楚...

编辑:为了确认或否认 ICMP 类型 4(需要分段)假设,我这样做了:

$ ping -c 1 -M do -s 1472 host
PING host (1.2.3.4) 1472(1500) bytes of data.
1480 bytes from host (1.2.3.4): icmp_req=1 ttl=50 time=33.8 ms
Run Code Online (Sandbox Code Playgroud)

这有效,但我有点困惑。“(1500)”是否表示总片段大小?我假设是这样,因为 1480 字节 + 20 字节 IP 标头是 1500 字节。

如果我将 ping 的大小增加一:

$ ping -c 1 -M do -s 1473 host
PING host (1.2.3.4) 1473(1501) bytes of data.
From pannekoek.lan (192.168.2.5) icmp_seq=1 Frag needed and DF set (mtu = 1500)
Run Code Online (Sandbox Code Playgroud)

因此,这意味着两台主机之间的路径确实允许 1500 字节的数据包,并且不会发生碎片问题。看来我又回到了原点。

再次编辑:我发现了一些重要的东西。问题只是某些大小的数据包没有到达。它发生在我的调制解调器和 ISP 的第一个网关之间:

$ for i in `seq 1025 1030`; do ping -c 1 -M do -s $i 195.190.243.7; done
PING 195.190.243.7 (195.190.243.7) 1025(1053) bytes of data.
1033 bytes from 195.190.243.7: icmp_req=1 ttl=254 time=31.2 ms  <- works

--- 195.190.243.7 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 31.273/31.273/31.273/0.000 ms
==========================
PING 195.190.243.7 (195.190.243.7) 1026(1054) bytes of data.

--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss   
==========================
PING 195.190.243.7 (195.190.243.7) 1027(1055) bytes of data.

--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1028(1056) bytes of data.

--- 195.190.243.7 ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1029(1057) bytes of data.

--- 195.190.243.7 ping statistics --- 
1 packets transmitted, 0 received, 100% packet loss, time 0ms <- packet loss
==========================
PING 195.190.243.7 (195.190.243.7) 1030(1058) bytes of data.
1038 bytes from 195.190.243.7: icmp_req=1 ttl=254 time=31.1 ms <- works

--- 195.190.243.7 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 31.177/31.177/31.177/0.000 ms
Run Code Online (Sandbox Code Playgroud)

我想我必须说服他们这是他们的问题。

小智 1

在从 A 点到 B 点的线路上的某个地方,路由器配置了较低的 MTU,这就是问题所在。您是否尝试过进行跟踪以查看 ICMP 数据包到底在哪里丢失?