ping 配合 DF 位快速测出真实 MTU 的实战指南 1. MTU 这件事坑通常藏在哪一层很多网络故障排查到最后都会落到一个看起来不起眼的数字上MTU。它的全称是 Maximum Transmission Unit中文叫最大传输单元指的是链路层一次能承载的 IP 报文最大长度。以太网默认 1500 字节这个数字几乎所有网卡出厂就设好了于是大多数人一辈子都不会去动它。可一旦链路上多了一层封装——宽带拨号、VLAN 标签、三层隧道、专线互联、跨地域组网——1500 就不再成立而设备两端的配置往往还停留在出厂默认值故障就这么埋下了。这个问题最让人抓狂的地方在于小包全通大包全挂。你 ping 网关是通的DNS 解析正常TCP 三次握手也能完成网页却一直转圈SSH 能登录一执行ls就卡住文件传到 80% 突然断掉。很多新手第一反应是网断了第二反应是服务器挂了重启设备、换网线、打电话找运营商折腾一整天最后发现只需要把 MTU 从 1500 改成 1492。这篇内容想解决的问题很具体改完 MTU 之后怎么用最短的时间确认它到底对不对。答案就是ping命令配合 DFDont Fragment不分片标志做探测一行命令加几轮二分两三分钟就能得出结论不需要抓包不需要装任何额外软件。适合谁看刚接手网络运维的新人、自己折腾家用宽带的玩家、写自动化部署脚本需要做链路自检的开发者以及那些改完配置不确定有没有生效的老手——最后这类人其实最多因为改配置容易验证配置难。1.1 一个数据包跑完全程要脱几层外衣理解 MTU 的第一课是把一个包有多大这件事拆成两层来看。上层应用产生的数据加上 TCP 或 UDP 头、IP 头构成 IP 报文IP 报文再被塞进链路层的帧里帧头和帧尾还要占位置。MTU 约束的是 IP 报文这一层的总长度上限不包括以太网帧头那 14 字节和帧尾的 4 字节校验。这个界定很重要因为不少人在交换机上看到的帧长度和路由器上配置的mtu 值根本不是一回事对着两个数字比来比去自然会绕晕。举个直白的例子。你在浏览器里请求一个页面服务器发回来的 TCP 段里有效载荷最多 1460 字节因为要扣掉 20 字节 IP 头和 20 字节 TCP 头1500 − 40 1460。这 1460 就是常说的MSSMaximum Segment Size最大报文段长度。它和 MTU 是父子关系MSS MTU − 40IPv4 场景。懂了这层关系你后面看到改 MTU 顺手要调 MSS就不会觉得突兀。注意MSS 是 TCP 层协商出来的值只在 SYN 包里传递双方各报各的最终取小。它不是你想设多少就设多少也不是设置完就一定生效——中间设备如果做 MSS clamping会强行改写这个值。真正的麻烦在于链路上每一跳的 MTU 可能不一样。你的网卡 1500家用路由器 LAN 口 1500WAN 口因为拨号封装变成 1492运营商接入设备可能是 1492骨干网又是 1500对端服务器网卡 1500。一个 1500 字节的包出发时合法走到拨号那一段就超标了。这时候设备有两个选择分片或者丢弃。IPv4 默认允许分片但分片会带来性能损耗和安全风险所以现代网络实践中普遍在关键报文上打DF 标志明确告诉途经设备这个包不许拆拆不了就退回来告诉我。1.2 常见链路的 MTU 对照表我在排查时习惯先查一张表把可能的封装开销列出来往往一眼就能锁定嫌疑值。下面这些是实际环境里出现频率最高的几档链路类型典型 MTU被吃掉的字节说明标准以太网15000最常见也是默认值PPPoE 宽带拨号14928PPPoE 头 6 字节 PPP 协议字段 2 字节带单层 VLAN 标签14964802.1Q 标签 4 字节带双层 VLAN 标签14928QinQ 场景两层标签叠加IP-in-IP 三层隧道148020外层再套一个 20 字节 IP 头GRE 隧道147624外层 IP 20 GRE 头 4再叠加一层加密封装1420 上下60 至 80加密头 认证尾具体看算法存储网络大帧9000—需整条链路端到端一致否则更糟这张表不是让你背而是让你在测出结果后能对上号。比如你测出来最大可通 1464后面会讲怎么算一加 28 得 1492那就基本可以断定链路上有拨号封装如果测出来是 1452加 28 得 1480八成是套了一层 IP 隧道。数字对上了问题就定性了比盲猜快得多。1.3 为什么偏偏是 ping 能测出来有人会问抓包不是更准吗确实更准但抓包要求你能在两端同时抓还要会看 TCP 重传和 ICMP 差错报文门槛不低。ping的优势在于它足够可控你可以精确指定发送的数据长度可以强制不分片还能从返回的差错信息里直接读到中间设备报出来的 MTU 值。它把一个复杂的路径发现问题压缩成了一次发大包看反应的简单实验。更妙的是ICMP Echo 报文的结构极其简单20 字节 IP 头 8 字节 ICMP 头 N 字节数据。这个 8 字节的固定开销是后面所有计算的基石也是最容易算错的地方——很多人在 Linux 上ping -s 1500发现不通就断言 MTU 有问题其实他发的 IP 报文总长是 1528超了 28 字节不通才是正常的。ping的另一个价值是非侵入性。它不建立连接不传输业务数据对生产环境影响极小。在客户现场做排查你不太好意思直接跑压测工具但敲几行 ping 谁都不会有意见。我个人的习惯是任何一次涉及链路层参数的变更收尾动作一定是三轮 ping 验证一轮测小包通不通一轮测临界值一轮测临界值加 1 字节确认被正确拒绝。2. ping 测 MTU 的底层逻辑DF 位是关键如果不加任何参数直接 ping你测不出 MTU。因为默认情况下报文允许分片一个 3000 字节的包发出去中间设备拆成两半照样能到对端重组后正常回复你只会看到通什么都没发现。探测 MTU 的核心技巧就是把允许分片这个后路堵死让超标的包无处可逃必须原路返回报错。2.1 DF 标志与分片的博弈IP 头里有一个 3 位的标志字段其中一位就是 DFDont Fragment。置 1 表示此包不得分片置 0 表示随便拆。发送端置了 DF中途某台设备的出接口 MTU 装不下这个包时它的处理流程是丢弃然后回一个 ICMP Type 3 Code 4 的差错报文意思是目标不可达需要分片但 DF 已置位同时在这个 ICMP 报文里带上下一跳的 MTU 值。这个机制叫PMTUDPath MTU Discovery路径 MTU 发现。它的设计初衷很优雅发送端一开始按自己网卡的 MTU 发收到需要分片的回报就调小直到不再收到为止全程自动。但现实往往不优雅——很多防火墙出于安全策略直接丢弃所有 ICMP发送端永远收不到那个需要分片的通知于是傻乎乎地一直发大包一直丢一直重传。这就是业内说的PMTUD 黑洞症状是能连上但传不动数据。提示PMTUD 黑洞是握手成功但业务卡死的最常见原因之一。TCP 的 SYN 包很小几十字节就能过去握手看起来毫无问题一旦开始传数据满 MSS 的大包全被丢连接就僵在那里。我们手动用 ping 测 MTU本质上就是人工扮演一次 PMTUD故意发一个带 DF 的、指定大小的包看它能不能过去过不去就减小直到找到那个临界点。整个方法论就这么简单剩下的全是细节。2.2 那 28 个字节到底是怎么算出来的这是全文最需要记牢的一段。假设你在 Windows 上执行ping -f -l 1472 目标地址意思是发送 1472 字节数据且不分片。这 1472 是怎么来的IP 头固定 20 字节不含选项ICMP Echo 头固定 8 字节类型 1 代码 1 校验和 2 标识 2 序号 2数据部分 1472 字节合计20 8 1472 1500所以-l 1472对应的正是 MTU 1500 的满包。如果这个包能通说明整条路径的 MTU 至少是 1500如果不通说明某处小于 1500。反过来推算 MTU 的公式就是MTU 最大可通的数据长度 28。这个 28 是 IPv4 场景下的固定值务必刻在脑子里。测出 1464MTU 就是 1492测出 1452MTU 就是 1480测出 1472MTU 就是 1500。系统不分片参数指定数据长度示例命令Windows-f-l 长度ping -f -l 1472 目标Linux-M do-s 长度ping -M do -s 1472 目标macOS-D-s 长度ping -D -s 1472 目标这里有个巨坑必须提前说Linux 的ping -f不是不分片而是 flood 模式洪水ping需要 root 权限疯狂发包。我见过不止一个人照着 Windows 教程在 Linux 上敲ping -f -l 1472结果报参数错误或者把交换机打出一堆告警。Linux 上正确的写法是-M do-M后面接do、dont、want分别对应不分片、允许分片、尽量不分片。2.3 两种回显读懂了就成功一半命令敲下去回显是唯一的信息来源。三种典型输出要能一眼分辨。第一种成功。正常收到Reply from ...或64 bytes from ...说明这个尺寸能完整通过整条路径可以往上加。第二种本地拒绝。Windows 会显示需要拆分数据包但是设置 DF英文是 Packet needs to be fragmented but DF setLinux 本地回显类似ping: local error: message too long, mtu1500。注意看那个mtu1500——这是你本机网卡的 MTU不是你发包时指定的尺寸别被它误导。本地拒绝说明你发的包已经超过了自己网卡的 MTU纯属自己跟自己较劲得先把本机 MTU 调大或者把测试值调小。第三种远端或中途拒绝。Linux 上会出现From 198.51.100.1 icmp_seq1 Frag needed and DF set (mtu 1492)这个格式极有价值它直接告诉你哪一跳设备报的错、它认为的 MTU 是多少。看到这行基本等于答案已经送到手上了。Windows 上这条信息会显示为来自 ... 的回复: 需要拆分数据包但是设置 DF来源地址就是瓶颈设备。注意有些设备返回的mtu值并不精确只是它自己接口的值未必是整个路径的最小值。所以看到这个数字后仍然建议按这个值减 28再实测一次确认。3. 实操用二分法把真实 MTU 测出来理论讲完进入动手环节。整个流程分四步确认前提、二分查找、交叉验证、落地配置。走完一遍快的两分钟慢的十分钟取决于链路质量和 ICMP 放行情况。3.1 测试前的三条确认动手之前先花三十秒把三件事确认掉能省掉后面大量的困惑。第一确认你本机的 MTU 够大。Windows 上执行netsh interface ipv4 show subinterfaces看当前网卡的 MTULinux 上ip link show dev eth0或ip link show看mtu字段。如果本机 MTU 已经被设成 1400你却想测 1472 的包本地直接拒绝永远测不出来。很多人排查半天最后发现是自己电脑上早就改过 MTU 了。第二确认目标地址可 ping。先普通 ping 四个小包ping -n 4 目标或ping -c 4 目标全通再做后续测试。如果小包都 ping 不通问题不在 MTU在路由、ACL 或者目标主机禁 ICMP先解决那个。第三选对目标。目标要选在故障链路之后最好是对端网络里的设备。如果你怀疑的是总部到分支的专线 MTU 有问题那目标就得选分支内网的地址ping 同城公网地址测不出专线的问题。另外尽量选一个会回应 ICMP 的设备很多云主机默认禁 ping选它等于白测。3.2 二分查找的手工推演这里用文档保留地址做示例实际替换成你的目标 IP 就行。假设目标198.51.100.10怀疑链路上有拨号封装MTU 可能是 1492。第一步先发满包 1500 试试水ping -M do -s 1472 198.51.100.10Linux 回显Frag needed and DF set (mtu 1492)答案其实已经出来了。但为了严谨继续验证。第二步按提示值减 28发 1492 对应的大小ping -M do -s 1464 198.51.100.10通。说明 1492 这个尺寸能过。第三步试试 1465看是不是真的卡在边界ping -M do -s 1465 198.51.100.10不通回Frag needed and DF set。到这里就可以确认最大可通数据 1464真实 MTU 1464 28 1492。两分钟搞定。如果第一步就没有任何 ICMP 差错提示只是超时Request timed out那说明中途有设备把差错报文吞了。这时候不能靠提示值得老老实实做二分。手工二分的节奏是这样测 1472不通测 1400通取中间值 1436通取 1454不通取 1445通取 1449不通取 1447通取 1448不通收敛到 1447MTU 1447 28 1475。这个值很怪不对应任何标准封装这时候要怀疑是不是某台设备的接口被人手工改过或者链路质量导致的偶发丢包被误判成 MTU 问题。嫌麻烦可以写个循环几行脚本跑完#!/bin/bash target198.51.100.10 lo1200 hi1472 while [ $((hi - lo)) -gt 1 ]; do mid$(((lo hi) / 2)) if ping -M do -s $mid -c 1 -W 1 $target /dev/null 21; then lo$mid else hi$mid fi done echo 最大可通 payload: $lo echo 推算 MTU: $((lo 28))这个脚本的下界设 1200 是有讲究的IPv6 要求全链路最小 MTU 不低于 1280IPv4 的推荐最小值是 576把下界设成 1200 是一个比较保险的起点能覆盖绝大多数封装场景。如果 1200 都不通那就不是 MTU 问题了别有侥幸心理。提示-c 1 -W 1表示只发一个包、等一秒。二分时不要在同一个尺寸上反复发多包那会拖慢整个流程。但最终确认时一定要多发几个包比如-c 5因为偶发丢包会让你把临界值判小。3.3 crossover双向、多目标、跨时段单点单向测试出来的结果只能算初步结论。要让它变成可靠结论还得补三件事。一是双向测。网络常常是非对称的去程走专线、回程走公网的事一点不稀奇。从 A ping B 通了不代表 B ping A 也通。如果只能从一端发起测试那就至少要在业务侧和办公侧各测一次比对结果是否一致。二是多目标测。同一个对端网络里选两台不同网段的设备各测一遍。如果一台测出 1500、另一台测出 1492说明 1492 那台的接入路径上多了一层封装问题范围就缩小到了那一段。三是换时段测。白天链路拥塞时大包被丢的概率上升可能把 1500 误判成 1470。遇到结果飘忽不定的情况挑一个负载低的时段复测或者干脆多发几十个包看丢包率。统计意义上的偶发不通和 MTU 意义上的必然不通处理方式完全不同。我个人的习惯是准备一张小表格把每次测试的目标 / 尺寸 / 结果 / 时间记下来。听起来很啰嗦但当你测了七八个点、过了两天再回来看这份记录能救命。3.4 测准了之后配置落在哪里测出 MTU 只是第一步把它配到正确的位置才有意义。这里有三个位置要分清。位置一发起端的网卡。Windows 上netsh interface ipv4 show subinterfaces netsh interface ipv4 set subinterface 以太网 mtu1492 storepersistent注意接口名要写对用第一条命令查出来的那个名字。storepersistent保证重启后仍然生效不加这个参数重启就还原。Linux 上ip link set dev eth0 mtu 1492这条命令是临时的重启失效。要永久生效得写进网络配置文件不同发行版写法不一样用 NetworkManager 的可以nmcli connection modify 有线连接 802-3-ethernet.mtu 1492用 systemd-networkd 的在.network文件里加MTUBytes1492。位置二链路上的关键设备。如果是拨号封装的场景MTU 388 应该配在拨号接口上而不是配在电脑上。电脑配 1492、路由器拨号口还是 1500这个问题根本没解决——大包在路由器那里就已经被拆了或者被丢了。改 MTU 要改在封装发生的那一跳这是最容易搞错的地方。位置三TCP MSS。有些场景下你不方便改 MTU比如中间设备不归你管那就退而求其次做 MSS clamping在网关的转发策略里把经过的 TCP SYN 包里的 MSS 值强行改成MTU − 40。对端收到小的 MSS自然不会发大包问题一样能绕过去。代价是稍微牺牲一点效率但胜在改动范围小、风险可控。配置完一定要做闭环验证重新跑一轮二分确认临界值没变再跑一遍真实业务打开网页、传个文件、SSH 执行几条输出长的命令确认体感正常。只看 ping 通不通是不够的业务层的表现才是最终验收标准。4. 几个最容易翻车的细节参数和流程都不复杂真正让人栽跟头的是判断逻辑。下面这几条每一条我都在实际环境里踩过或者见别人踩过。4.1 ICMP 被丢测出来的可能是假数前半段一直在说ping 不通说明 MTU 不够但反过来不成立。ping 不通有很多原因MTU 只是其中之一。如果路径上某台设备无差别丢弃 ICMP你做二分得到的结果会是一个明显偏小的值甚至压根收敛不了。识别方法很简单小包比如 64 字节也 ping 不通但业务能正常跑那基本就是 ICMP 被拦了。这种情况下有两条路。第一条换一个允许 ICMP 的目标最好是同网段内的另一台设备绕过拦截点。第二条放弃 ping改用带路径 MTU 发现能力的工具比如traceroute在 Linux 下加--mtu参数或者用curl分块下载大文件观察是否卡在中途。抓包看 TCP 重传也是一个办法看到小包过、满 MSS 包反复重传就是典型特征。4.2 MSS 和 MTU 是两回事别互相替代见过太多人把这两个概念混为一谈配置的时候随手填。区别其实很清楚MTU 是链路层的容量上限管的是所有 IP 报文MSS 是 TCP 层的协商参数只管 TCP 连接。一个 UDP 应用不受 MSS 影响但它照样受 MTU 约束。反过来你把 MSS 调小了ICMP 大包照样过不去。换算关系再强调一遍IPv4 下 MSS MTU − 40IPv6 下 MSS MTU − 60IPv6 头 40 字节 TCP 头 20 字节。1492 的 MTU 对应 1452 的 MSS1480 对应 1440。配置的时候如果只改了一个另一个没跟着动很容易出现部分应用好了、部分应用还是卡的诡异现象。注意抓包看到的 MSS 值是双方协商的结果不是本地配置的直接映射。如果看到实际生效的 MSS 比你配的小说明中间有设备做了 clamping这时候别去改本地配置改了也没用。4.3 二层 MTU 和三层 MTU 不是一个数交换机上配的 MTU 和路由器上配的 MTU含义经常不一样。有的厂商接口下的mtu指三层 IP 报文长度不含二层头有的指二层帧长度含 14 字节头甚至 4 字节 FCS还有的区分mtu和ip mtu两个命令。同一个 1500在不同厂商的设备上可能差 18 个字节。做端到端一致性配置时务必查清楚每台设备的口径。用大帧Jumbo Frame9000 字节那一档的场景尤其要注意只要有一台设备的二层 MTU 没跟上整个传输就会退化成小包或者直接丢包性能反而比不用大帧更差。4.4 别为了省事把 MTU 一路调小新手容易走另一个极端既然 1500 有问题那就全部改成 1400反正小一点总没错。短期内确实能治好故障代价是每个包能装的有效数据少了 7%加上 TCP 头开销实际吞吐下降更明显同时分片和重组的次数增加设备 CPU 负担上升。在低带宽链路上这个损失可能直接让业务体验变差。正确做法是测出真实值按真实值配不多不少。测出 1492 就配 1492不要配 1480 求个保险。真担心波动那就把 MSS clamping 作为兜底手段而不是无脑压低 MTU。5. 常见问题速查与排查实录把上面这些内容压缩成一张表出问题时对着看比翻文档快。5.1 症状与原因对照表现象最可能的原因先做什么小包通大包超时无任何提示ICMP 差错报文被中途丢弃换目标或改用 traceroute 辅助判断小包通大包返回 Frag needed (mtu X)链路存在封装X 即瓶颈值按 X − 28 实测确认本地直接报 message too long本机网卡 MTU 小于测试值先查本机 MTUTCP 握手成功传数据卡死PMTUD 黑洞满 MSS 包被丢做 MSS clamping 或调小 MTU网页首屏能开图片加载不出中等尺寸包被丢二分找出真实 MTU时通时不通无规律链路质量或拥塞非 MTU 问题多时段复测看丢包率部分目标正常、部分异常不同目标的接入路径封装不同按目标分别测试改完 MTU 依旧不通改错了位置没改在封装那一跳检查路由器和拨号接口配置5.2 三个实际场景的排查过程场景一新装宽带后网页打不开。某用户反馈路由器拨号成功后微信能发消息网页一直转圈手机连 WiFi 也一样。第一步 ping 网关通ping 公网地址小包通直接ping -M do -s 1472公网地址回Frag needed and DF set (mtu 1492)。到这里答案已经很清楚拨号链路 MTU 是 1492而路由器 WAN 口还是 1500。改完 WAN 口 MTU 后立刻恢复。这类问题在家用宽带里极其普遍尤其是换了新路由器、用了默认配置的情况。场景二跨地域专线传文件中断。两个办公点之间走专线小文件正常超过 1MB 的文件传到一半必断。先怀疑专线质量让运营商查了半小时线路指标正常。回头做 ping 测试-s 1472不通-s 1440通二分收敛到 1452MTU 1480。查配置发现中间有一段 IP 隧道封装吃掉了 20 字节。两端设备 MTU 都改成 1480 后传输恢复正常。这个案例的关键点是运营商的线路正常和你业务层的能通是两码事链路层指标好不代表 MTU 匹配。场景三云上主机 SSH 登录后卡死。能登录说明握手没问题敲ls就卡住说明输出数据的大包过不去。测试发现-s 1400能通-s 1420不通收敛到 1412MTU 1440。这个值对应典型的加密隧道封装。由于云平台侧不方便改最终在主机上把网卡 MTU 设为 1440同时在安全组策略里对 TCP MSS 做钳制双保险。遇到改不了对端的情况改自己能改的那一端同样能解决问题。5.3 我自己踩过的几个坑第一个坑是在错误的层上测。有次排查一个分支机构的访问慢问题我从核心交换机 ping 分支网关一路正常测出 MTU 1500就判断没问题。后来才发现故障主机走的是另一条 VLAN那条路径上多了一层标签。教训是测试点要尽量贴近故障主机而不是图方便从核心设备发起。第二个坑是把偶发丢包当成 MTU 边界。二分的时候只发一个包正好碰上链路瞬时拥塞误判成这个尺寸不通结果测出来的 MTU 比实际值小了一截。后来改成临界值附近每个尺寸发 5 个包全通才算通准确率立刻上来了。多花十几秒省下几小时。第三个坑是改完不验证业务。MTU 调好了、ping 通了就以为万事大吉结果用户反馈某个内部系统还是慢。查下来是那个系统的服务端 MSS 被人手工改死成 1460跟新的 MTU 对不上。任何网络参数变更验收标准都应该是业务可用而不是工具可用。最后分享一个效率技巧把常用的测试命令做成别名或者小脚本Windows 下存成.batLinux 下写进~/.bashrc。我自己的习惯是准备三个一个测临界值、一个跑二分、一个批量测多个目标。排查现场手忙脚乱的时候少打几个字符都是赚的。这套东西不复杂但真到了需要它的时候能让你在两分钟内给出结论而不是在客户面前一边查文档一边敲命令。