月度归档:2024年06月

在 RouterOS 中配置 MSS Clamping 解决部分网站图片无法加载的问题

  • 协议: IPv4 & IPv6

现象

  • 手机访问阿里系应用有问题,如支付宝、淘宝、盒马,加载很久,也可能很久也加载不出来
  • 开代理科学上网后正常,但按理说大多请求应该还是走的 Direct 规则
  • 怀疑是 IPv6 的问题,于是起了 SmartDNS 的 force-AAAA-SOA yes,BAN 掉了所有的 v6 解析后,有所改善!

PMTU黑洞

换成自己用 RouterOS 拨号之后,经常发现有的图片加载不出来,是因为在RouterOS中没有正确配置MTU及MSS,导致部分包被丢弃,也就是传说中的 PMTU 黑洞。

最常见的就是微信公众号图片、淘宝预览图、B站预览图始终加载不出来。

所谓 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防火墙的mangle表

/ip/firewall/mangle
add action=change-mss chain=forward comment="IPv4 MSS clamp to PMTU" \
    new-mss=clamp-to-pmtu out-interface="<你的PPPoE出口>" passthrough=yes \
    protocol=tcp tcp-flags=syn

/ipv6/firewall/mangle
add action=change-mss chain=forward comment="IPv6 MSS clamp to PMTU" \
    new-mss=clamp-to-pmtu out-interface="<你的PPPoE出口>" passthrough=yes \
    protocol=tcp tcp-flags=syn

参考