LINUX MTU/MSS(1500/1460)那些事:原理、排查与实战
前两天有同事跑过来问我:同一台服务器,网页访问都正常,但从这台机器往远端上传大文件总是到一半就卡住,小文件又没事。他第一反应是带宽不够,我让他用带DF标志的大包ping了一下对端,结果很快出来了——这是典型的MTU问题。这类问题在Linux服务器运维里太常见了,尤其是在跨运营商、跨机房、走隧道或者PPPoE拨号的场景下。MTU和MSS这两个参数,一个是二层和三层边界的硬限制,一个是TCP协议栈里的软协商,1500和1460之间那40字节的差额,背后藏着的是IP头和TCP头的基本结构。这篇文章会把它们彻底讲透,并给出可复现的排查命令和修改方法,适合刚接触网络基础的学生、Linux运维新手,以及被“大包不通小包通”折磨过的同行。
1. 先搞懂1500和1460差的那40个字节去哪了
1.1 一个数据包从网卡出去的完整旅程
要理解MTU,必须先建立一个分层视角。当你在Linux里执行一次TCP发送,应用层数据先落到TCP层,TCP会加上一个TCP头;接着落到IP层,IP会加上一个IP头;最后落到网卡驱动,网卡会把这个完整的三层报文封装进以太网帧,再通过物理链路发出去。
MTU的全称是Maximum Transmission Unit,它的准确定义是“接口在不用分片的情况下,能够承载的最大IP数据报长度”。注意这里说的是IP数据报,也就是IP头加上IP载荷的总长度,不包含以太网帧头和帧尾。这就是为什么你看到接口MTU是1500,但同样的数据包到了抓包软件里,Frame长度却显示1518——那多出来的18字节,是14字节的以太网头(源MAC6字节、目的MAC6字节、Type字段2字节)加上4字节的Frame Check Sequence帧校验序列。
换句话说,MTU是三层概念里的上限,而1500这个经典数值,来源于以太网v2标准对帧载荷长度的约束。之所以定在1500,是兼顾了信道占用时间、错误重传代价和内存管理效率的折中结果,这个数值从80年代一直沿用到今天,已经成了绝大多数网络设备默认三层载荷上限。
1.2 TCP头加IP头等于40字节,这是1460的由来
那1460又是怎么来的?1500减去40,这40字节通常是20字节的IP头加20字节的TCP头。20字节的IP头是IPv4最基础的变长头部,不携带任何Option选项;20字节的TCP头同样也是最标准形态,没有时间戳、没有SACK选项,只带最基本的序列号、确认号、窗口、标志位等字段。
MSS的全称是Maximum Segment Size,属于TCP的选项字段,在TCP三次握手阶段,双方通过SYN报文里的MSS选项告诉对方:我这边能接收的TCP载荷最大是多少。计算方式就是本端接口MTU减去IP头长度再减去TCP头长度。如果本端MTU是1500,那么MSS通常就是1460。
这里有个容易绕晕的点:MSS不是新加限制,而是TCP为了“不给IP层添麻烦”主动把段变小。因为IP层一旦需要对数据包做分片,就很有可能导致性能下降甚至丢包后重传效率急剧降低。TCP宁可在一开始就把单个数据段控制在一个完美的尺寸内,让IP层不必分片。
1.3 这套换算关系在不同场景下怎么变
搞懂“40字节损耗”之后,各种变体就都能推导了。如果接口MTU是1492(典型的PPPoE场景),那TCP MSS就是1492减40等于1452。如果走GRE隧道,外层IP头加GRE头通常要吃掉24字节,内层数据就得缩水到1476,TCP MSS就变成1436。如果是IPv6环境,基础IP头是40字节,所以同样是1500的MTU,IPv6的MSS是1500减40(IPv6头)再减20(TCP头)等于1440。
我用表格把这个对应关系列出来,照着查就行:
| 场景 | 接口MTU | TCP MSS推荐值(基础IP头+TCP头) |
|---|---|---|
| 标准以太网 / IPv4 | 1500 | 1460 |
| 标准以太网 / IPv6 | 1500 | 1440 |
| PPPoE拨号 / IPv4 | 1492 | 1452 |
| GRE隧道内层 / IPv4 | 1476 | 1436 |
| 标准VLAN标签影响(802.1Q头4字节,实际帧载荷仍为1500) | 1500(L3不变) | 1460,但二层帧上限需考虑帧长为1522 |
记住一点:这些都是“典型值”,MSS最终是在握手时协商出来的,取收发两端看到的路径上较小值。真正决定能否传通的,是整条链路上最小的那个MTU值,也就是路径MTU。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 大包不通小包通:MTU问题的典型故障画像
2.1 PMTU黑洞是怎么产生的
PMTU黑洞这说法听起来玄乎,其实捅破就一层窗户纸。假设你内网服务器MTU是1500,要走PPPoE链路出去,PPPoE这段链路MTU只能到1492。当1500字节的IP报文到达PPPoE链路时,路由器发现包太大,按照协议它有两种选择:要么分
