在 RouterOS 中配置 MSS Clamping 解决部分网站图片无法加载的问题
换成自己用 RouterOS 拨号之后,经常发现有的图片加载不出来,网上一顿冲浪之后发现可能是在 RouterOS 中没有正确配置 MTU 及 MSS,导致部分包被丢弃,也就是传说中的 PMTU 黑洞。
症状
最常见的就是微信公众号的图片始终加载不出来,就像这样(自己当时没截图,借用知乎文章的图):
说来也很奇怪,我在 iOS 的微信上是能正常加载的,但是换到我妈的 Android 微信就会出现这样的情况,之前一直以为是我妈的手机出毛病了……
PMTU 黑洞
所谓 MTU,指的是一条链路上可以通过的三层数据包的最大尺寸(包含 IP 包头)。以太网默认的 MTU 是 1500 字节。但是从我的设备到目标服务器之间的路径上可能存在 MTU 小于 1500 的链路,那么这条路径上最小的 MTU,就是整条链路的Path MTU
(PMTU)。
路由器在转发包的时候,如果包的大小超过了 MTU,那么这个包会被分片(fragmentation)。而终端设备在发包时,也可以设置 DF 标志位(Don’t Fragment)来告诉路由器不要对这个包分片,此时如果这个包大小超过了 MTU,那么路由器就会丢掉这个包,并回复一条ICMP Fragmentation Needed
消息。发送者收到这个消息后,下次就会发送小一点的包。这个过程叫做 PMTU 发现(PMTU Discovery)。
但是互联网中有大量的设备因为各种原因,会配置为不回应ICMP Fragmentation Needed
消息,这使得大小超过 MTU 的包会被无声地丢掉,直到 TCP 协议发现超时丢包并进行重传。这种情况就是PMTU黑洞
。
此外,IPv6 包不支持分片,换句话说就是所有 IPv6 数据包全都带有 DF 标记。中间的路由器在遇到尺寸大于 MTU 的包的时候,应该回应ICMPv6 Packet Too Big
消息,而同样的,由于各种原因,某些中间设备可能会直接丢掉这个包而不返回这条消息,直到 TCP 协议发现超时而进行重传。
为什么用光猫或者硬路由拨号就没有这个问题
这是因为,多数家用路由器默认开启了一个叫MSS Clamping
的功能。这是针对 PMTU 黑洞的一个 workaround,简单来说就是在 TCP 握手时,服务器会通过一个字段告知客户端它愿意接收的 TCP 包的最大尺寸,这样客户端就可以限制自己发送的包的大小,保证不会超出服务端要求的尺寸。
在 RouterOS 中配置 MSS Clamping
配置非常简单,分别对 IPv4 和 IPv6 的防火墙 Mangle 表添加如下配置即可。
1 | # 将命令中 out-interface 参数的值替换成你的PPPoE接口的名字 |
参考文档
- 开启 IPv6 后网速变得很慢?可能是 PMTU 黑洞的问题 - V2EX
- ROS 修改 MTU 和 MSS 解决上网慢和页面显示不全问题
- 什么是最大分段大小 (MSS)? - CloudFlare