IP 分片、MTU 与 MSS
更新时间:2026-09-17。网络协议域·传输层(兼跨网络层)。分片是偶发"小包能通、大包卡死/握手成功但传数据超时"的根因之一。
一、三个概念
| 概念 | 所在层 | 含义 | 典型值 |
|---|---|---|---|
| MTU(Maximum Transmission Unit) | 链路层/IP | 一个帧/IP 包在该链路上一次能承载的最大字节(含 IP 头及载荷) | 以太网 1500 |
| MSS(Maximum Segment Size) | TCP | 一个 TCP 段能承载的最大数据(不含 IP/TCP 头) | 1500−20 IP−20 TCP = 1460 |
| IP 分片 | IP 层 | 包大于出接口 MTU 时拆成多个 IP 分片 | — |
记忆:MSS = MTU − 20(IP头) − 20(TCP头) = 1460(不带选项的 IPv4)。IPv6 头 40 字节,MSS 相应为 1440。TCP 在三次握手时用 MSS 选项协商,之后按段大小发送,尽量不让 IP 层分片。
二、IP 分片怎么分、为什么危险
当一个 IP 数据报大于出接口 MTU 且没置 DF(Don't Fragment,不分片)位,路由器/主机把它拆成多个带相同 ID、不同 offset 的分片,到终点再重组:
- 任一分片丢失,整个原始包都无法重组(IP 不重传);TCP 会重传整个段,UDP 则整份数据报废——一个丢包被放大成整包丢失。
- 分片可能被防火墙/ACL 丢弃(只放行首片、或禁止碎片以防分片攻击)。
- 重组要在终点缓存,带来延迟与资源消耗/DoS 面。
- 只有首片含 TCP/UDP 端口,非首片对无状态设备难以做 L4 过滤。
所以 TCP 的设计目标是用 MSS 把每段控制在路径 MTU 内,从源头避免 IP 分片;UDP 应用也应把报文压在安全尺寸内。
三、DF 位与 PMTU 路径 MTU 发现
TCP 段通常置 DF=1(不许分片)。若包对某条链路太大,路由器不能分片又必须丢弃,就回一个 ICMP:
ICMP Type 3 Code 4: Destination unreachable / Fragmentation needed and DF set
(附带该链路 MTU)发送方据此调小段,重复探测直到整条路径通行——这就是 PMTUD(Path MTU Discovery)。
PMTUD 黑洞
问题在于很多网络错误地屏蔽了 ICMP(防火墙只放行业务端口)。于是:"需要分片且 DF"的 ICMP 反馈回不来,发送方一直按大 MTU 重传、小包(如握手、短请求)正常、大包(TLS 证书、POST 数据)全部卡住或超时——称为 PMTU blackhole(黑洞)。经典症状:
- TCP 连接能建立、小请求正常,一发大报文/握手到 TLS 证书阶段就挂起;
- 隧道(PPPoE 1492、VPN、VXLAN/GRE、容器 overlay MTU 变小)环境高发。
应对:
- MSS clamping:在网关上把 TCP SYN 里的 MSS 选项改写为更小值(
iptables ... --clamp-mss-to-pmtu,或按隧道 MTU 固定如 1380/1400),让两端按较小 MSS 发送。 - 不要一刀切封禁所有 ICMP,至少放行 fragmentation-needed(Type3/Code4)。
- 现代有 DPLPMTUD / PLPMTUD(用大包探测而非依赖 ICMP,TCP 与 QUIC 都采用)缓解黑洞。
四、自己探测 MTU
# Linux:-s 指定载荷,-M do 等价置 DF;1472 载荷 + 28(IP20+ICMP8) = 1500
ping -M do -s 1472 10.0.0.1 # 若通,路径 MTU >= 1500
ping -M do -s 1473 10.0.0.1 # 超过,应收到 "Frag needed" 或不通
# 逐步减小直到通,反推可用 MTU = 能通的最大 -s + 28
tracepath 10.0.0.1 # 直接报告 pmtu(如 pmtu 1480 说明隧道)
ip route get 10.0.0.1 # 看缓存的 mtu# 查看/设置接口 MTU(隧道/overlay 常需调小以匹配底层)
ip link show eth0
ip link set dev tun0 mtu 1400
sysctl net.ipv4.ip_no_pmtu_disc # 0 启用 PMTUD五、隧道与容器里的 MTU 减法
每封装一层,外层都额外占字节,内层 MTU 必须相应减小,否则触发分片或黑洞:
| 封装 | 常见额外开销 | 内层 MTU 参考 |
|---|---|---|
| PPPoE | 8 | 1492 |
| GRE / IPIP | 20+ | ~1476 |
| VXLAN | 50 | 1450 |
| WireGuard | ~60 | ~1420–1440 |
容器(Docker/Flannel/Calico)、VPN、云上 overlay 最容易因 MTU 不一致出现"能 ping 通但大请求挂起",排查时先对齐各层 MTU 或做 MSS clamping。QUIC/HTTP3 规定初始 UDP 载荷不超过 1200 字节,正是为了天然规避常见隧道的分片。
相关阅读
UDP 大包分片整包丢失见 UDP 协议,TCP 用 MSS 配合cwnd/拥塞控制发送,弱网与限速可结合 tc netem 复现。
总结
MTU 是链路单包上限(以太网 1500),MSS 是 TCP 单段数据上限(1500−40=1460);TCP 置 DF 位、靠 PMTUD 收 ICMP fragmentation-needed 动态适配以避免 IP 分片,而分片一旦丢一片整包报废;ICMP 被封会造成"小包通、大包卡"的 PMTUD 黑洞,用 ping -M do/tracepath 探测、MSS clamping 和对齐隧道 MTU 解决。