PMTU,说到网络上的 PMTU 所能实现的功能,网工对它的原理自然是如数家珍,不熟悉的可能就感觉高大上了,觉得路径 MTU 能自动发现了,自然端到端数据包传输就能避免数据包分片了。可是理想很丰满,现实很骨干,PMTU 的想法自然是极好,但是受限于复杂的环境因素,PMTU 实际上有时并无法很好地实现。
本篇简单介绍一个 PMTU 的案例,一来主要是在实际环境中比较少见,要么全程一路畅通,要么路径 MTU 问题造成丢包连接中断,二来就是能拿到实际数据包。。。不容易~
PMTU(Path MTU Discovery),简单来说路径 MTU 发现是用来确定端到端路径中最小 MTU(Maximum Transmission Unit)的大小。又是最小,又是最大,还是用图说话比较清楚。
每一段都会有一个 MTU 也就是最大传输单元的限制,而端到端传输中间可能会经过很多个具有不同 MTU 限制的节点,这样如果设置不分片 DF(Don’t Fragment)标志的长度为 1500 字节的数据包就会在 MTU 1200 处被丢包,同样长度为 1100 字节的数据包也会在 MTU 1000 处被丢包。
如何自动探测路径中的最小 MTU ?也就是如何找到图示中最小的一个 MTU 值 1000,就需要 PMTU 来实现,它通过在 IP 报头中设置有不分片 DF(Don’t Fragment)标志来探测路径中的 MTU 值, 如果路径中设备的 MTU 值小于此报文长度,并且发现 DF 标志,就会发回一个 Internet 控制消息协议 (ICMP,类型3、代码4需要分片的消息 ICMP_FRAG_NEEDED),消息中包含它可接受的 MTU 值。这样发端应用会主动降低 MTU,所发送出来的数据包就能满足中间路径最小 MTU 的要求。
回到说开篇提到的 PMTU 实际上并不能很好地实现,简单的原因就是它太依赖 ICMP ,如果中间设备不回复 ICMP 或者 ICMP 消息被中间安全设备阻断,种种原因造成源端无法接收到 ICMP 消息,那么自然也无法判断出最小 MTU 值,拿 TCP 连接来说,可能不断尝试进行数据包重发,仍无法得到响应就断开连接了。
数据包跟踪文件基本信息如下:
λ capinfos PMTU.pcapng
File name: PMTU.pcapng
File type: Wireshark/... - pcapng
File encapsulation: Ethernet
File timestamp precision: microseconds (6)
Packet size limit: file hdr: (not set)
Number of packets: 5908
File size: 6296 kB
Data size: 6104 kB
Capture duration: 14.336218 seconds
First packet time: 2022-07-14 12:54:13.944957
Last packet time: 2022-07-14 12:54:28.281175
Data byte rate: 425 kBps
Data bit rate: 3406 kbps
Average packet size: 1033.18 bytes
Average packet rate: 412 packets/s
SHA256: ...
RIPEMD160: ...
SHA1: ...
Strict time order: False
Capture hardware: Intel(R) Core(TM) ...
Capture oper-sys: 64-bit Windows 7 Service Pack 1...
Capture application: Dumpcap (Wireshark) 3.2.18 (v3.2.18-0-gddf8072b7671)
Number of interfaces in file: 1
Interface #0 info:
Name = \Device\NPF_{...}
Description = 无线网络连接
Encapsulation = Ethernet (1 - ether)
Capture length = 262144
Time precision = microseconds (6)
Time ticks per second = 1000000
Time resolution = 0x06
Operating system = 64-bit Windows 7 Service Pack 1...
Number of stat entries = 1
Number of packets = 5908
λ
通过 Wireshark v3.2.18 捕获,数据包捕获数量 5908 个,捕获持续时间为 14.3 秒,平均速率 3406 kbps,捕获系统为 Win7 SP1。会话信息中仅有一条流,该跟踪文件可能已经经过一番过滤了。
专家信息整体看起来也很正常,Warning 信息数量很少可忽略不计。
数据包跟踪文件实际展开如下:
主要分析如下:
No.7 数据包为 ICMP 报文,为类型 3 、代码 4 表示需要分片的消息(Fragmentation needed) ,消息中包含它可接受的 MTU 值为 1410;之后的 IPv4 首部、TCP 首部以及 HTTP 数据为 No.6 原始数据包的部分信息,相关信息可与 No.6 一一对应。
其中需要注意的是 TCP payload 大小 508 字节,这样使得 No.7 整个数据包为 590 字节,减去 14 字节 Ethernet 首部长度后,实际 No.7 数据包的 MTU 为 576,而 576 是广域网所规定的一个最小 MTU 标准值。
No.9 1424 字节长度(1370 + 20 + 20 + 14),此后的 No.11-12 同样为 1424 字节长度。Client Seq 230 -> 1600 -> 2970 -> 4340 ,Server 在 No.13 ACK num 4340。至此完成 PMTU 系统实现、数据交互,连接之后恢复正常。
需要注意的是,因为 Client No.6 实际由于 MTU 问题未正常发送到 Server ,Client 重新根据新的 MTU 进行了数据包调整发送的缘故,Wireshark 在此处的判断逻辑并没那么智能,会由于 No.6 Seq 误判断 No.9 为乱序、No.11为重传等,实际上并不是,可以通过忽略 No.6-7数据包的方式重新观察,如下,一切正常。
日常工作中,由于 MTU 的限制,可能带来的问题远比想象的要复杂,但只要掌握了基础知识和原理,从容应对,那么问题就不会是问题了。