为什么你的IPv6的网络连接慢或经常超时?

最近有个前同事问我,他们App与后台连接在宽带Wi-Fi网络情况下,经常会出现连接IPv6网络的问题,但是切换回4G/5G网络又会恢复正常,我给的解决方案简单粗暴,直接关闭服务端的IPv6协议栈,但这背后的真实原因是什么呢?你有了解吗?

MTU

先了解个基础概念——什么是MTU?,不了解的可以点击去了解下,简单的理解就是指你每次通讯能够发送的最大字节数,做过蓝牙或者Wi-Fi通讯开发的肯定都知道近端通讯一般都会有 MTU 协商过程,从而来确保两端都按照能够承受的最大字节数来传输,从而提高传输效率。

为什么我家的光猫 MTU 的值有1500,1480, 1492 这几种?以太网单包最大载荷是1500,但你家光猫设置的1480或者1492其实跟你的网络运营商环境有关,如果你是通过光猫PPPoE宽带拨号上网的,大部分的值是1492,PPPoE协议本身需要占用协议头6字节+协议 ID 2字节,剩余的有效载荷就是1492字节了。那为什么有些运营商会设置1480呢?这就和运营商的配置策略有关了,因为有可能运营商中间节点设备的 MTU 值本身就是小于1500,所以在光猫设备上直接配置 1480 ,这样有点类似于留有一定的余量,尽量保证传输过程中少拆包或者不拆包。

那什么是 PMTU? 刚刚说到 MTU 的时候,你可能忽略了中间节点路由器和防火墙的影响,在你的设备和目标服务器之间的路径上可能存在 MTU < 1500 的链路,那么这条路径上最小的 MTU 值就是整条路径的 PMTU 值。

PMTU数据黑洞

终端设备在发包时,也可以设置 DF ( Don't Fragment )标记来告诉路由器不要分片。这时中间路由器会丢掉超过 MTU 的包,回复一条 ICMP Fragmentation Needed 消息。发送者收到这个包后,下次就会发小一点的包,这个过程叫做 PMTU Discovery 。现实中可以看到 HTTPS ( TLS )的流量大都是带 DF 标记的。

然而,互联网上有大量的中间设备为了所谓的“安全”或者没有正确配置,不回应 ICMP Fragmentation Needed 包,这使得访问某些网站时如果某个包的大小超过了 PMTU,会被无声地丢弃,直到 TCP 协议发现超时丢包进行重传,这非常缓慢。遇到这种情况,我们可以说你和目标服务器的路径上存在 PMTU 黑洞。

IPv4是如何解决

其实IPv4也没有解决这个问题,只是因为多数家用路由器默认对 IPv4 下的 TCP 开启了 MSS (maximum segment size) Clamping ,这其实是针对 PMTU 黑洞的一种变通解决办法,简单来说就是 TCP 握手时有个 MSS 字段决定单个 TCP 包的最大尺寸,你家的路由器可以通过嗅探 TCP 握手包,把 MSS 值自动改小,从而使最终的三层 IP 包的尺寸( MSS+TCP 头大小+IP 头大小)不超过某个特定的值。

IPv6为什么无法解决

IPv6 不支持分片,换句话说可以理解为 IPv6 下所有的包都是带 DF 标记的。中间路由器在遇到包尺寸大于 MTU 的情况时,应该回应 ICMPv6 Packet Too Big 消息。同样的,由于种种原因,某些中间设备可能会直接丢包而不回应 ICMPv6 Packet Too Big 消息,直到 TCP 协议发现超时丢包进行重传。而且目前很多光猫、家用路由器对 IPv6 的优化很差,不支持对 IPv6 下的 TCP 包进行 MSS Clamping,这就导致访问 IPv6 网站时,若路径中存在 PMTU 黑洞,则打开很慢甚至出现超时。

如何解决IPv6慢或超时

如果你是一个网络爱好者,你如果想要理想的体验 IPv6,那需要把光猫改为桥接模式,并使用 OpenWRT 或者 RouterOS 这类对 IPv6 支持较好的路由器,我在上一篇文章中特地提到了配置 IPv6 的 MSS Clamping ,从而解决 IPv6 慢的问题。

如果你是一个双栈网站或者网络服务提供商,那么建议你现阶段关闭 IPv6 协议栈,或者在特定条件下开启,防止 IPv6 的 PMTU 黑洞对现有业务造成影响。

标签:IPv6, PMTU, 数据黑洞