网络-04 MTU 与 MSS
分段特指发生在使用TCP协议的传输层中的数据切分行为 分片特指发生在使用IPv4协议的网络IP层中的数据切分行为
1. 最大传输单元(Maximum Transmission Unit)
最大传输单元(Maximum Transmission Unit),即MTU,为数据链路层的最大载荷上限(即IP数据报最大长度),每段链路的MTU可能都不相同,一条端到端路径的MTU由这条路径上MTU最小的那段链路的MTU决定。
MTU是链路层中的网络对数据帧的一个限制,以以太网为例,MTU通常为1500字节,采用巨帧(Jumbo Frame)时可以达到9000字节。所谓的MTU,是二层协议的一个限制,对不同的二层协议可能有不同的值,只有二层协议为以太网(Ethernet)时,MTU一般才取1500字节,注意它不是物理链路介质的限制。直连两端的 MTU 如果配置不一致,较大的一端可能发送出对端无法接收的帧,形成单向丢包。
一个IP数据报在以太网中传输,如果它的长度大于当前链路MTU值,就要进行分片传输(这里指IP层分片),使得每片数据报的长度都不超过MTU。分片传输的IP数据报不一定按序到达,但IP首部中的信息能让这些数据报片按序组装。IP数据报的分片与重组是在网络IP层完成的。
2. 最大报文段长度(Maximum Segment Size)
最大报文段长度(Maximum Segment Size),即MSS,为TCP传输层的最大载荷上限(即应用层数据最大长度),TCP三次握手期间通过TCP首部选项中的MSS字段通知对端。MSS 是按方向通告的:“我通告 1460”表示“你发给我的 TCP 载荷不要超过 1460”,两个方向的值可以不同。与MTU的换算关系为:
MTU = MSS + TCP首部长度 + IP首部长度
故在以太网中(网络层以IPv4为例):
MSS = 以太网MTU - TCP首部长度 - IPv4首部长度 = 1500 - 20 - 20 = 1460字节
未携带 MSS 选项时,IPv4 TCP 使用 536 字节作为传统默认接收 MSS(IPv6 为 1220 字节)。现代系统正常握手都会携带 MSS 选项,工程中看到 536 往往意味着选项被中间设备删除或连接路径异常,而不是推荐配置。
一个应用程序如果要发送超过MSS大小的数据,就要进行分段传输(这里指TCP分段),使得每个报文段长度都不超过MSS。分片传输的TCP报文段不一定按序到达,但实现可靠传输的TCP协议中有处理乱序的机制,即利用报文段序列号在接收缓冲区进行数据重排以实现重组。TCP分段的重组是在TCP传输层完成的。
3. 为什么IP层会分片,TCP还要分段?
由于本身IP层就会做分片这件事情。就算TCP不分段,到了IP层,数据包也会被分片,数据也能正常传输。
既然网络层就会分片了,那么TCP为什么还要分段?是不是有些多此一举?
假设有一份数据,较大,且在TCP层不分段,如果这份数据在发送的过程中出现丢包现象,TCP会发生重传,那么重传的就是这一大份数据(虽然IP层会把数据切分为MTU长度的N多个小包,但是TCP重传的单位却是那一大份数据)。
4. 区别
有了前文的知识准备,不难得出结论:
TCP分段的原因是因为TCP报文段大小受MSS限制 IP分片的原因则是因为IP数据报大小受MTU限制
一个值得注意的是,在分片的数据中,传输层的首部只会出现在第一个分片中,IP数据报分片后,只有第一片带有传输层首部(UDP或ICMP等),后续分片只有IP首部和应用数据,到了目的地后根据IP首部中的信息在网络层进行重组,这一步骤对上层透明,即传输层根本不知道IP层发生了分片与重组。而TCP报文段的每个分段中都有TCP首部,到了目的地后根据TCP首部的信息在传输层进行重组。
5. PMTUD:路径上的最小 MTU 怎么发现
端到端路径可能经过以太网、VPN、隧道和公网链路,发送方事先不知道其中最小的 MTU。**路径 MTU 发现(PMTUD)**的思路是:
- IPv4 发送带 DF(Don’t Fragment)的包;
- 某一跳发现包太大,丢弃并返回 ICMP “Fragmentation Needed”;
- 发送方根据通知减小包大小并缓存该路径的 PMTU。
IPv6 中间路由器本来就不允许分片,包太大时返回 ICMPv6 Packet Too Big,因此 PMTUD 是 IPv6 正常工作的基础能力。
传统 PMTUD 依赖 ICMP。一些防火墙错误地屏蔽全部 ICMP 后,发送方收不到“包太大”的反馈,就会反复发送同样的大包,形成 MTU 黑洞。典型症状:
- TCP 三次握手成功;
- 小请求、小响应正常;
- 大响应、文件上传或 TLS 握手卡住;
- 抓包看到大段数据反复重传。
PLPMTUD 则由传输层逐步探测可用大小,不完全依赖 ICMP。现代 TCP 和 QUIC 都在向这种更健壮的探测方式演进。
6. 隧道为什么容易触发 MTU 问题
VPN、VXLAN、GRE、IPsec 等隧道会在原始包外再套一层首部。底层物理网络仍是 1500 MTU 时,留给内部数据包的空间会变小。
例如 VXLAN 外层通常增加约 50 字节:
物理 MTU 1500 - 外层以太网/IP/UDP/VXLAN 约 50 ≈ 内层 MTU 1450
这就是 K8s CNI 常把 Pod MTU 配成 1450 左右的原因。不同云厂商、IPv4/IPv6 和加密方式的开销不同,不能死记一个值,应查看实际 CNI/VPN 配置。
常见处置方式:
- 调小隧道内接口 MTU;
- TCP 网关做 MSS clamping,在握手时改小 MSS;
- 正确放行 PMTUD 所需的 ICMP/ICMPv6。
MSS clamping 只对 TCP 有效,UDP 和 QUIC 仍需要应用正确控制数据报大小或自行做路径探测。
7. Go 服务端需要注意什么
TCP 应用一般不应该按 MSS 自己切数据,Go 的网络栈和内核 TCP 会完成分段、重传和重组。应用真正要做的是:
- 使用长度前缀等方式定义消息边界,不把一次
Write当成一个网络包; - 处理短写和错误;
- 遇到“小响应正常、大响应超时”时,把 MTU 黑洞纳入排查范围。
UDP 不会替应用拆分消息。一条过大的 UDP 数据报可能在 IP 层分片,任意一个分片丢失都会导致整条数据报作废,而且非首片没有端口信息,更容易被 NAT/防火墙丢弃。公网 UDP 协议通常把单个数据报控制在约 1200 字节,QUIC 也把 1200 字节作为必须支持的最小 UDP 载荷。
Go 可以用 ReadMsgUDP 获得更多报文信息,但仅靠普通 ReadFromUDP 很难可靠判断缓冲区是否截断了超大数据报。因此接收缓冲区必须覆盖协议允许的最大消息,并在应用协议中设置明确的长度上限。
8. 本章面试题
MTU 和 MSS 的区别?换算关系是什么?
- MTU(最大传输单元)是链路层对一次可发送数据的限制,即 IP 数据报的最大长度。以太网通常为 1500 字节。
- MSS(最大报文段大小)是传输层 TCP 报文中 data 部分的最大长度。
换算:MSS = MTU - IP首部 - TCP首部 = 1500 - 20 - 20 = 1460 字节(以太网 + IPv4)。
MSS 在三次握手时通过 TCP 选项字段通告,表示“对方发给我的 TCP 载荷不要超过这个值”。它按方向生效,两个方向可以不同;发送端还会受自身接口和路径 MTU 限制。
分片和分段有什么区别?既然 IP 层会分片,TCP 为什么还要分段?
- 分段发生在传输层(TCP),受 MSS 限制;
- 分片发生在网络层(IPv4),受 MTU 限制。
TCP 仍要分段的原因是重传粒度:假设 TCP 不分段,一大份数据交给 IP 层被切成 N 个小片,只要其中任意一片丢失,TCP 就必须重传整个那一大份数据(因为 TCP 的重传单位是它自己的报文段,它不知道 IP 层切了几片)。
而 TCP 自己按 MSS 分段后,每段都不超过 MTU、IP 层无需再分片,丢一个段只重传那一个段。
IP 分片后,传输层首部在哪几个分片里?
只在第一个分片里。
IP 数据报分片后,只有第一片带有传输层首部(TCP/UDP/ICMP),后续分片只有 IP 首部 + 数据。到达目的地后在网络层完成重组,这个过程对上层完全透明——传输层根本不知道 IP 层发生过分片。
对比:TCP 分段后每个段都有完整的 TCP 首部,在传输层重组。
这也解释了一个实际影响:防火墙如果按端口过滤,非首片分片里没有端口信息,处理起来会有麻烦。
什么是 MTU 黑洞?怎么排查?
症状:小请求正常,大请求卡死超时。常见于 VPN、隧道、跨云专线。
原因:路径上某段 MTU 偏小,大包带 DF(Don’t Fragment)标志无法分片,路由器丢弃并回 ICMP “需要分片"报文——但如果防火墙拦了这个 ICMP,发送方永远收不到通知,只会一直重传同样大小的包。
验证:用禁止分片的 ping 逐步减小找临界值:
ping -M do -s 1472 <目标> # Linux,1472+28=1500
ping -D -s 1472 <目标> # macOS
处置:调小网卡 MTU,或在网关做 MSS clamping(iptables ... --clamp-mss-to-pmtu)。详见 网络-22。
IPv6 和 IPv4 的分片有什么不同?
IPv4 在 DF=0 时允许中间路由器分片;IPv6 禁止中间路由器分片。IPv6 路由器遇到过大的包会丢弃并返回 ICMPv6 Packet Too Big,由源主机降低大小。
如果 IPv6 确实需要分片,只能由发送端加入 Fragment 扩展首部。因此不能一刀切拦截 ICMPv6,否则 PMTUD 会失效并形成 MTU 黑洞。
xingliuhua