共计 2578 个字符,预计需要花费 7 分钟才能阅读完成。
我一直以为,有些网络常识是可以带进棺材里的。
\n\n
比如家里只要是光猫改桥接、路由器拨号,WAN 口的 MTU 闭着眼睛填 1492 就完事了。从早年的 ADSL 电话线拨号,到百兆、千兆光纤,几十年来我一直这么干,从来没怀疑过。毕竟 1500 减掉 8 字节的 PPPoE 头,小学算术题,谁都知道。
\n\n
结果今天,这个用了几十年的老规矩,结结实实给我上了一课。
\n\n
\n\n
一、诡异的“半死不活”
\n\n
今天白天,家里的网络突然变得极度离谱。
\n\n
进 H3C 路由器后台看,PPPoE 挂着绿灯,公网 IP 拿得好好的,DNS 也是对的。手机上微信发文字秒回,在终端里 ping 百度、ping 阿里 DNS,延迟只有 8 毫秒,稳得一批。
\n\n
但只要你尝试动真格的,网络立马原形毕露:
\n\n
- \n
- 随便点开一个网页,进度条直接卡死在最左边,死活加载不出来;
- 微信文字能发,但别人发过来的图片点开就是个转圈的灰块;
- 跑 Speedtest 测速,刚准备起跑就报网络错误;NAS 上的几个 Docker 容器拉镜像全在超时重试。
\n
\n
\n
\n\n
这时候人的第一反应通常是什么?
\n 没错,玄学重启。
\n\n
我把光猫拔了电源等一分钟插上,没用;把 H3C 路由重启,没用;重新拨号换了个 IP 段,还是老样子。折腾了一圈,差点以为是电信机房炸了,或者光猫硬件老化抽风。
\n\n
\n\n
二、撕开表象:到底卡在什么地方?
\n\n
冷静下来一想, 小包通(Ping、文字消息),大包死(网页、图片、测速)——这不就是典型的报文长度超标、两头卡死了么?
\n\n
但我 WAN 口填的一直是 1492 啊,难道电信还能把它吃掉一块?
\n\n
干脆不用猜了,直接在 Linux 终端用 ping 抓现行。这里有个关键技巧:加上 -M do,意思就是“强制禁止分片”。告诉网络:这个包多大你就给我整包发出去,要是路上哪个设备塞不下,就地给我吐出来。
\n\n
我们知道 ICMP 载荷加上 IP 头和 ICMP 头(共 28 字节)就是总包长。既然以前是 1492,那我就发个 1464 试试(1464 + 28 = 1492):
\n\n
ping -c 2 -M do -s 1464 114.114.114.114
\n\n
回车刚敲下去,终端屏幕立马跳出来两行刺眼的报错:
\n\n
From 192.168.1.1 icmp_seq=1 Frag needed and DF set (mtu = 1420)\nping: sendmsg: Message too long
\n\n
192.168.1.1 就是我自家的 H3C 路由器。它直接把底裤给交了:mtu = 1420。
\n\n
好家伙,我的上限被死死焊在 1420 了!我填 1492,多出来的整整 72 个字节根本通不过!
\n\n
既然路由器说只能过 1420,那倒扣 28 字节,载荷应该是 1392。我马上拿 1392 验证:
\n\n
ping -c 2 -M do -s 1392 223.5.5.5
\n\n
1400 bytes from 223.5.5.5: icmp_seq=1 ttl=53 time=8.32 ms\n1400 bytes from 223.5.5.5: icmp_seq=2 ttl=53 time=8.50 ms\n--- 0% packet loss ---
\n\n
两包全过,零丢包,延迟 8ms。
\n 为了防炸胡,我手贱把载荷加了 1 字节(-s 1393,总长 1421):
\n\n
ping -c 2 -M do -s 1393 223.5.5.5\n# 瞬间再次拦截:From 192.168.1.1: Frag needed and DF set (mtu = 1420)
\n\n
多 1 个字节都不给过。1420 就是那道不可逾越的死线。
\n\n
\n\n
三、运营商到底背着我们干了啥?
\n\n
测到这里,真相其实已经大白了。
\n\n
(注:我家是标准的公网电信家庭宽带,光猫改了桥接、路由器直接拨号获取独立公网 IPv4,并不是那种没有公网的大内网。这里说的背刺,是指电信骨干与城域网汇聚层在推进“云宽带”改造。)
测到这里,真相其实已经大白了:不是我们家里设备坏了,是电信在底层网络架构里“疯狂加料”了。
\n\n
以太网的物理帧极限通常就是 1500 字节。以前电信的网络架构相对简单,1500 减去 PPPoE 的 8 字节,剩下的 1492 字节全给你用,天下太平。
\n\n
但这几年运营商大搞云宽带、集约化 BRAS 改造,城域网里为了做流量调度和隔离,套了各种各样的马甲:
\n 什么 QinQ(双层 VLAN,拿走 4 字节)、VXLAN(UDP 隧道,直接拿走 50 字节),还有各种 SRv6、MPLS 标签……层层包装下来,外层开销直接吃掉了几十个字节。
\n 外壳套得越厚,里面能留给用户的空间就越缩水。算下来,正好就只剩 1420 字节了。
\n\n
更恶心的是,按照标准协议,中间设备塞不下大包时,本该发个 ICMP 报文通知我们降速(分片)。但很多运营商为了防攻击,把这类 ICMP 报文直接在骨干网上静默丢弃了。这就导致了两端都在干瞪眼:我以为你收到了,你以为我还没发完,网络就这么彻底卡成了“黑洞”。
\n\n
\n\n
四、怎么改?别犹豫,直接 1420
\n\n
抓出这个 1420 之后,有人可能会问:既然极限是 1420,要不要保守一点设成 1400?
\n\n
我的建议是:没必要,直接填 1420。
\n\n
网络发包是有头开销的。MTU 设得太小,数据就被拆得越碎,协议头占的比例越高,千兆宽带的实际有效吞吐就越缩水。既然实测 1420 已经能 100% 零丢包整包通过,多留那 20 字节纯粹是自我阉割。
\n\n
修改起来也就两步:
\n\n
- \n
- 进路由器后台改 MTU:打开 H3C 路由器的 WAN 口 /PPPoE 设置,把那个万年不变的
1492改成1420,保存; - 确认 MSS 钳制 :现在的家用硬路由,你改了 WAN 口 MTU,它基本都会自动把 TCP MSS 钳制在 1380(1420 减去 IP 和 TCP 头的 40 字节)。如果是用 OpenWrt 软路由的朋友,在防火墙设置里把“MSS 钳制(Clamp MSS to PMTU)”打上勾即可。
\n
\n
\n\n
\n\n
五、折腾后的碎碎念
\n\n
改完保存生效的那一瞬间,原本转菊花的网页瞬间秒开,微信图片秒加载,测速软件直接把千兆跑满,那种畅快感终于回来了。
\n\n
折腾这一趟,最大的感触还是: 不要迷信过去的“黄金法则”。
\n1492 确实统治了网络很多年,但底层的网络基础设施一直在变。遇到怪毛病,少盲目重启,拿工具戳两下,比瞎猜半天管用得多。