开启 IPv6 后网速变得很慢?可能是 PMTU 黑洞的问题

2021-09-05 22:23:38 +08:00
 raysonx

发现最近经常有人提到开启 IPv6 连接速度慢的问题。目前国内确实存在支持 IPv6 的服务器、CDN 节点不够多,IPv6 国际带宽比 IPv4 带宽小的问题,但也不至于会打开国内网站都卡。通常情况下遇到这个问题说明你到目标服务器的链路上存在 PMTU 黑洞。

关于 PMTU 黑洞

MTU (Maximum transmission unit) 是一条链路上可以通过的三层数据包的最大尺寸(包含 IP 包头)。以太网上默认的 MTU 是 1500 字节,但是你和目标服务器之间的路径上可能存在小于 MTU 1500 的链路。这条路径上最小的 MTU 值就是整条路径的 PMTU 值。路由器在转发包时,超过 MTU 大小的包会被分片( Fragmentation ),也就是一个大包会被分切为多个不超过 MTU 的小包进行传输,传输效率会下降。

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

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

此外,IPv6 不支持分片,换句话说可以理解为 IPv6 下所有的包都是带 DF 标记的。中间路由器在遇到包尺寸大于 MTU 的情况时,应该回应 ICMPv6 Packet Too Big 消息。同样的,由于种种原因,某些中间设备可能会直接丢包而不回应 ICMPv6 Packet Too Big 消息,直到 TCP 协议发现超时丢包进行重传。。。

为什么 IPv4 没有这个问题

其实 IPv4 也有这个问题,我不只一次见网友说自己搭的软路由访问某些网站非常慢,而换回硬路由就正常。这是因为多数家用路由器默认对 IPv4 下的 TCP 开启了 MSS (maximum segment size) Clamping (使用 OpenWRT 软路由的朋友们可以在防火墙设置中找到 MSS Clamping 开关)。MSS Clamping 是针对 PMTU 黑洞的 Workaround,简单来说就是 TCP 握手时有个 MSS 字段决定单个 TCP 包的最大尺寸。路由器可以通过嗅探 TCP 握手包,把 MSS 值改小,使最终的三层 IP 包的尺寸( MSS+TCP 头大小+IP 头大小)不超过某个特定的值。

总结

现在国内 ISP 一般都是通过 PPPoE 虚拟拨号建立 WAN 口连接的。Ethernet 的默认 MTU 是 1500,但是 PPPoE 隧道有 8 个 bytes 的开销,所以 PPPoE 虚连接的 MTU 就是 1500-8=1492,减掉 IPv4 包头( 20 字节)和 TCP 包头( 20 字节),可以得知 IPv4 下需要把 MSS 设为 1452 以下。

IPv6 的包头是 40 字节,所以 IPv6 下需要把 MSS 设为 1432 以下。

这时问题来了,目前很多光猫、家用路由器对 IPv6 的优化很差,不支持对 IPv6 下的 TCP 包进行 MSS Clamping,这就导致访问 IPv6 网站时,若路径中存在 PMTU 黑洞,则打开很慢。

我前段时间帮朋友配置 IPv6 时发现了很多光猫、家用路由器的固件问题,使得国内使用 IPv6 的体验不太理想。我打算抽空专门开一个帖子去讨论这些问题,声讨那些垃圾厂家。目前来看,要想在国内比较理想地体验 IPv6,你需要把光猫改为桥接模式,并使用 OpenWRT 或者 VyOS 这类对 IPv6 支持较好的软路由。

33030 次点击
所在节点    宽带症候群
65 条回复
guanyin9cn
2021-09-07 00:28:57 +08:00
更正下,上面贴的是 v4 的

v6

[root@x6 /mnt/jffs2/hw/bin] # ip6tables-save | grep MSS
-A PREROUTING -i ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m tcpmss --mss 1392:65535 -j TCPMSS --set-mss 1392
guanyin9cn
2021-09-07 00:31:35 +08:00
@Unclev21x

dnsmasq 里添加一行。

address=/电台域名 /::
tankren
2021-09-07 09:23:01 +08:00
@xiaooloong #7 本来就是要手动设置 MTU 和 MSS 的啊 默认是 1500 全都放 1492 就可以,WAN 的 ipv6 用 track interface,然后 RA 设置 Assisted
tankren
2021-09-07 09:24:32 +08:00
@xiaooloong #7 2.5.1 改的那个 bug 是对于 IPV6 MSS 的设置值减的是 IPV4 的 40 不是 60 原来要设置成 1472 才没问题
Unclev21x
2021-09-07 09:38:36 +08:00
@guanyin9cn 谢谢。我晚上回去就试试。
但我还是有些不明白。路由器开启科学上网(手机不开启)+IPv6 的情况下,手机拿到的 IPv6 地址是公网地址,这个时候访问电台,无法收听。打开 https://ifconfig.co/这个网站,显示的是 IPv6 地址。ping 这个域名的时候,解析出来的地址也是 IPv6 地址。接着,我在手机上也打开小火煎,之后就可以收听了。刷新 https://ifconfig.co/ ,显示的 IPv4 地址了。所以我就怀疑 IPv6 没有走代理(不知道是不是因为代理服务器不支持 IPv6 )。
Exin
2021-09-07 15:08:20 +08:00
学习了,讲得好清楚
Danswerme
2021-09-07 20:00:45 +08:00
感谢楼主分享,因为 IPv6 下打不开简书,本来我都把 IPv6 关掉了。想起来你提到的 MTU 的问题,刚才到家后用 wireshark 抓包看了下,发现其中有一条是这样的:`tcp previous segment not captured`。
然后在防火墙里把 MSS 改成 1420,果然就恢复正常了,再次感谢楼主。

分享下 RouterOS 里修改 MSS 的脚本: `/ipv6 firewall mangle add chain=forward out-interface=pppoe
-out1 protocol=tcp tcp-flags=syn action=change-mss new-mss=1420`
raysonx
2021-09-07 21:33:45 +08:00
@Danswerme 感谢分享 RouterOS 的设置命令
PublicDNS
2021-09-09 01:40:54 +08:00
erx 用户

set firewall options mss-clamp6 interface-type pppoe
set firewall options mss-clamp6 mss 1420
littlewing
2021-09-09 17:17:33 +08:00
@Danswerme 我也是 IPv6 打不开简书,然后没找到原因,感谢
darrh00
2021-09-09 23:54:03 +08:00
讨论过好多次了吧?

https://www.v2ex.com/t/688028
raysonx
2021-09-10 11:40:50 +08:00
@PublicDNS 感谢分享。
xPKK1qofAr6RR09O
2021-11-15 21:28:28 +08:00
routeros 似乎只需要设置 ipv6 > nd 里面的 mtu 值就行了
microka
2021-11-24 01:26:23 +08:00
@Danswerme #27 非常感谢,刚给 RouterOS 开启了 IPv6 ,发现无法访问简书,按照您的指导操作完马上可以了!
Danswerme
2021-11-24 10:13:02 +08:00
@microka 客气了,也要谢谢楼主的分享,能帮到大家就是最好的。
microka
2021-12-12 11:26:50 +08:00
由于 MikroTik hAP ac² 不支持 IPv6 fasttrack ,换为尝试华为 B610-4E 光猫路由拨号一体,只设置了 PPPoE MRU 1492 ,可正常访问知乎和简书,用 Chrome F12 看到访问知乎是走 v6 ,简书走 v4 。
pengkaiwei
2022-01-11 10:10:29 +08:00
请问老毛子 padavan 怎么 操作 MTU Clamping
droidmax61
2022-11-02 19:52:23 +08:00
@pengkaiwei 设置自动 mss 没用,我是手动指定 mss
azure2023us
2023-01-26 21:58:40 +08:00
某为光猫,只有 v4 ,v6 的没有
```
WAP(Dopra Linux) # iptables-save | grep mss
-A PREROUTING -i ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
-A PREROUTING -i ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN,ACK -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
-A POSTROUTING -o ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
-A POSTROUTING -o ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN,ACK -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
WAP(Dopra Linux) # ip6tables-save | grep mss
```

按照 v4 的套下

```
# firewall iptables
# v6 pmtu
ip6tables -t mangle -A PREROUTING -i ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
ip6tables -t mangle -A PREROUTING -i ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN,ACK -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
ip6tables -t mangle -A POSTROUTING -o ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
ip6tables -t mangle -A POSTROUTING -o ppp257 -p tcp -m tcp --tcp-flags SYN,RST,ACK SYN,ACK -m tcpmss --mss 1412:65535 -j TCPMSS --set-mss 1412
```
lerry
2023-04-25 22:33:54 +08:00
赞,正好用的 ros ,都准备把 ipv6 禁用了。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/800024

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX