如何判断 Windows XP 中使用的 MTU

and*_*ers 23 networking tcpip ip windows-xp mtu

我遇到了一个非常奇怪的问题,我在尝试访问网页时随机收到“与服务器的连接已重置”错误(根据 Windows 网络诊断工具的 HTTP 错误 12031) - 无论网页是否出现这种情况都会发生我正在尝试访问外部互联网,或者即使它来自在 localhost 上运行的本地 Apache 实例。它会影响我们本地网络(以太网,不是无线)上的所有计算机,所有这些计算机都运行 Windows XP。

有人向我建议,这可能与网络流量上使用的 MTU 有关。如果我进行Ping 测试以找出可以通过未分段的最大数据包,我可以使用 1492 字节的包(+28 字节用于标头?)来 ping 本地主机,并且可以使用 1462 字节的包来 ping 我们的路由器(包含 28 字节标头时为 1490 字节)。如果我尝试像 Google 一样在外部 ping 某些东西,我将无法通过大于 1430(带有标题的 1458)获得任何东西。

我尝试按照各种说明使用此 MTU 设置更新 Windows XP 注册表,更新HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{AdapterID}\MTU. 我试过没有尽头的替代值:最明显的正确值似乎是 1490,但我也试过 1462、1458、1430 等等。当我重新启动计算机以使更改生效时,它似乎工作了几分钟(很难确定,因为它总是随机而不是一致的)但它永远不会持续很长时间。

最初,当我尝试将 1430 作为值时,在正常工作几分钟后,Ping 测试的结果将减少 28 字节 - 突然间我发现我只能将 1402 字节的数据包发送到 Google。如果我将 MTU 注册表设置更新为 1402,当我重新启动并等待几分钟时,它会是 1374,然后是 1346,等等。网络上的其他计算机不受影响(仍然是 1430)并删除 MTU 设置从注册表将恢复正常(并且仍然损坏)。

我发现诊断所有这些最困难的事情是很难判断我是否在使用正确的注册表设置。因此,最简单的问题是:如何判断 Windows 尝试使用的 MTU 设置?

此外,如果有人有任何想法如何判断 MTU 为何不断下降 28,这也很有用(例如,是否有 Windows 日志文件在某个地方会在值更改时记录某些内容?)

最后,如果有人能明确地告诉我如何判断我应该尝试使用什么 MTU 设置,那就太好了!

Ian*_*oyd 64

对于 Windows 7、Windows Vista 和 Windows XP,各种接口的 MTU 可从 Windows 本身使用netsh.

Windows 7、Windows Vista

要在 Windows 7 或 Windows Vista 上显示当前MTU,请从命令提示符:

C:\Users\Ian>netsh interface ipv6 show subinterfaces

       MTU  MediaSenseState   Bytes In  Bytes Out  Interface
----------  ---------------  ---------  ---------  -------------
      1280                1   24321220    6455865  Local Area Connection
4294967295                1          0    1060111  Loopback Pseudo-Interface 1
      1280                5          0          0  isatap.newland.com
      1280                5          0          0  6TO4 Adapter
Run Code Online (Sandbox Code Playgroud)

对于 IPv4 接口:

C:\Users\Ian>netsh interface ipv4 show subinterfaces

       MTU  MediaSenseState   Bytes In  Bytes Out  Interface
----------  ---------------  ---------  ---------  -------------
      1500                1  146289608   29200474  Local Area Connection
4294967295                1          0      54933  Loopback Pseudo-Interface 1
Run Code Online (Sandbox Code Playgroud)

注意:在此示例中,我的本地连接IPv6接口具有如此低的 MTU (1280),因为我使用隧道服务来获得 IPv6 连接

您还可以更改MTU(Windows 7、Windows Vista)。从提升的命令提示符:

>netsh interface ipv4 set subinterface "Local Area Connection" mtu=1492 store=persistent
Ok.
Run Code Online (Sandbox Code Playgroud)

使用 Windows 7 Service Pack 1 进行测试

视窗 XP

netshWindows XP的语法略有不同:

C:\Users\Ian>netsh interface ip show interface

Index:                                  1
User-friendly Name:                     Loopback
Type:                                   Loopback
MTU:                                    32767
Physical Address:                       

Index:                                  2
User-friendly Name:                     Local Area Connection
Type:                                   Etherenet
MTU:                                    1500
Physical Address:                       00-03-FF-D9-28-B7
Run Code Online (Sandbox Code Playgroud)

注意: Windows XP 要求启动路由和远程访问服务,然后才能查看有关接口(包括 MTU)的详细信息:

C:\Users\Ian>net start remoteaccesss
Run Code Online (Sandbox Code Playgroud)

Windows XP 不提供从内部更改 MTU 设置的方法netsh。为此,您可以:

使用 Windows XP Service Pack 3 进行测试

也可以看看


简短讨论 MTU 是什么,28 个字节来自哪里。

您的网卡(以太网)的最大数据包大小为1,500 bytes

+---------+
| 1500    |
| byte    |
| payload |
|         |
|         |
|         |
+---------+
Run Code Online (Sandbox Code Playgroud)

TCP/IP的 IP 部分需要 20 字节的标头(12 字节标志,4 字节用于源 IP 地址,4 字节用于目标 IP 地址)。这会在数据包中留下更少的可用空间:

+------------------------+
| 12 bytes control flags | \
| 4 byte from address    | |- IP header: 20 bytes
| 4 byte to address      | /
|------------------------|
| 1480 byte payload      |
|                        |
|                        |
|                        |
+------------------------+
Run Code Online (Sandbox Code Playgroud)

现在一个 ICMP (ping) 数据包有一个 8 字节的报头(1 字节type、1 字节code、2 字节checksum、4 字节附加数据):

+------------------------+
| 12 bytes control flags | \
| 4 byte from address    | |
| 4 byte to address      | |- IP and ICMP header: 28 bytes
|------------------------| |
| 8 byte ICMP header     | /
|------------------------|
| 1472 byte payload      |
|                        |
|                        |
|                        |
+------------------------+
Run Code Online (Sandbox Code Playgroud)

这就是“缺失”的 28 个字节所在的地方——它是发送 ping 数据包所需的标头大小。

当您发送 ping 数据包时,您可以指定要包含多少额外的有效负载数据。在这种情况下,如果包含所有 1472 个字节:

>ping -l 1472 obsidian
Run Code Online (Sandbox Code Playgroud)

然后生成的以太网数据包将充满鳃。将填充 1500 字节数据包的每个最后一个字节:

+------------------------+
| 12 bytes control flags | \
| 4 byte from address    | |
| 4 byte to address      | |- IP and ICMP header: 28 bytes
|------------------------| |
| 8 byte ICMP header     | /
|------------------------|
|........................|
|........................|
|. 1472 bytes of junk....|
|........................|
|........................|
|........................|
|........................|
+------------------------+
Run Code Online (Sandbox Code Playgroud)

如果您尝试再发送一个字节

>ping -l 1473 obsidian
Run Code Online (Sandbox Code Playgroud)

网络必须将 1501 字节的数据包分割成多个数据包:

Packet 1 of 2
+------------------------+
| 20 bytes control flags | \
| 4 byte from address    | |
| 4 byte to address      | |- IP and ICMP header: 28 bytes
|------------------------| |
| 8 byte ICMP header     | /
|------------------------|
|........................|
|........................|
|..1472 bytes of payload.|
|........................|
|........................|
|........................|
|........................|
+------------------------+

Packet 2 of 2
+------------------------+
| 20 bytes control flags | \
| 4 byte from address    | |
| 4 byte to address      | |- IP and ICMP header: 28 bytes
|------------------------| |
| 8 byte ICMP header     | /
|------------------------|
|.                       |
| 1 byte of payload      |
|                        |
|                        |
|                        |
|                        |
|                        |
+------------------------+
Run Code Online (Sandbox Code Playgroud)

这种碎片化将在幕后发生,最好是在您不知情的情况下发生。

但你可以刻薄,告诉网络数据包不允许分片:

>ping -l 1473 -f obsidian
Run Code Online (Sandbox Code Playgroud)

-f标记的装置不分段。现在,当您尝试发送不适合网络的数据包时,您会收到错误消息:

>ping -l 1473 -f obsidian  

Packet needs to be fragmented but DF set.
Run Code Online (Sandbox Code Playgroud)

数据包需要分片,但设置了不要分片标志。

如果沿线的任何地方需要对数据包进行分段,网络实际上会发送一个 ICMP 数据包,告诉您发生了分段。你的机器得到这个 ICMP 数据包,被告知最大的大小是多少,并且应该停止发送太大的数据包。不幸的是,大多数防火墙会阻止这些“路径 MTU 发现”ICMP 数据包,因此您的机器永远不会意识到数据包正在被分段(或者更糟糕的是:因为无法分段而被丢弃)。

这就是导致网络服务器无法工作的原因。您可以获得最初的小(<1280 字节)响应,但无法通过较大的数据包。并且网络服务器的防火墙配置错误,阻止了 ICMP 数据包。所以网络服务器没有意识到你从未收到过数据包。

IPv6 中不允许对数据包进行分段,每个人都必须(正确地)允许 ICMP mtu 发现数据包。


小智 8

@ian 我不太确定是否netsh实际显示了当前使用的 MTU。在我的 Windows XP Pro SP3 机器上,我执行netsh interface ip show interface并报告相关接口的 MTU 值为1500. 然后我添加了以下注册表项:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\EnablePMTUDiscovery
    value: 0

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{ID}\MTU 
    value: various (e.g. 1200)
Run Code Online (Sandbox Code Playgroud)

微软表示设置EnablePMTUDiscovery为 0 会将 MTU 设置为 576。

设置MTU注册表项手动设置 MTU。我为MTU条目尝试了几个值(每次都重新启动)。

在这两种情况下——添加第一个条目,然后添加第二个条目——netsh仍然报告 MTU 为 1500。使用 ping 测试确认(或至少建议)注册表中配置的 MTU 值实际上正在使用。

另外,当我第一次在我的机器上尝试这个时,路由和远程访问服务被禁用,所以我无法按照您的说明启动它。我通过转到“控制面板”>“管理工具”>“计算机管理”>“服务和应用程序”>“服务”来启用它。我将“启动类型”从禁用更改为手动。然后我也从该对话框启动了该服务。

我也不确定 KB283165 是否一定是更改 MTU 的正确说明。这些说明不是仅在运行 Windows PPPoE 客户端时才相关吗?如果通过路由器连接到互联网,其中路由器是 PPPoE 客户端(如我的情况),这些说明将不相关,对吗?

KB900926:MTU 大小小于 576 的 WAN 链接的推荐 TCP/IP 设置(方法 2 和 3)中,我遵循的说明导致我对注册表进行了上述更改。


编辑@ian

看起来你是对的。配置为 1,200,但netsh报告1500.

在此处输入图片说明

>ping -l 1173 -f obsidian

Packet needs to be fragmented but DF set.
Run Code Online (Sandbox Code Playgroud)

所以我猜原始问题的答案是,在 Windows XP 上,您必须使用带有不分段标志的试错法来查找您可以发送的最大数据包。然后你就有了你的 MTU。