前言
PMTU,说到网络上的 PMTU 所能实现的功能,网工对它的原理自然是如数家珍,不熟悉的可能就感觉高大上了,觉得路径 MTU 能自动发现了,自然端到端数据包传输就能避免数据包分片了。可是理想很丰满,现实很骨干,PMTU 的想法自然是极好,但是受限于复杂的环境因素,PMTU 实际上有时并无法很好地实现。
本篇简单介绍一个 PMTU 的案例,一来主要是在实际环境中比较少见,要么全程一路畅通,要么路径 MTU 问题造成丢包连接中断,二来就是能拿到实际数据包。。。不容易~
PMTU 概念
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.1-3,Client 和 Server 之间的 TCP 三次握手连接,其中 SYN/ACK 中的 MSS 1400 说明服务器上最大的 MTU 为 1440 (1400+20 TCP 首部+20 IP 首部),也就是说双方最大传输数据包的长度为 1454 (1440+14 Ethernet 首部长度);IRTT 约为 103ms;支持 SACK;支持 WS;
- 数据包 No.3 ,Length 长度为 54,小于 60 ,说明该跟踪文件是在 Client 上直接捕获;
- 数据包 No.6 ,Client 发送了最大长度为 1454 的数据包;
- 数据包 No.7,从 192.168.191.69 节点返回了 ICMP 消息,提示 Destination unreachable(Fragmentation needed);
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 标准值。
- Client 在收到 No.7 之后,得知下一跳 MTU 为 1410,因此会调整 MSS 为 1370(1410-40),发送数据包 No.9;
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 的限制,可能带来的问题远比想象的要复杂,但只要掌握了基础知识和原理,从容应对,那么问题就不会是问题了。