关于 pppoe 下 ipv6 的 wg 隧道需不需要优化 MTU

2023-07-19 15:20:29 +08:00
 ppbaozi

先说说我对 MTU 相关的理解

  1. MTU 指链路中能通过最大数据包的大小,通常指 ip 包,比如以太网能最大传输 1500 字节 ip 包,pppoe 因为 ppp 协议占掉 8 字节,所以最大能传输 1492 字节 ip 包

  2. 通常,ipv4 协议头 20 字节、ipv6 协议头 40 字节,tcp 协议头 20 字节,WireGuard 协议头 40 字节,此网站可以查阅

  3. wireguard 隧道的默认 MTU = 1500 - 40(最大 ip 头)- 40(wg 协议) = 1420 ,pppoe 下再 -8 = 1412

  4. TCP MSS 指链路中能传输的 tcp 有效载荷的大小,1500 - 20/40(ip 头) - 20(tcp 头) = 1460(ipv4) 或 1440(ipv6),pppoe 下 1452(ipv4) 或 1432(ipv6)

  5. ipv6 不支持数据包切片,且现阶段路由器基本都没有对 ipv6 默认加上 mss 钳制,所以在 pppoe 下需要手动加上 mss 钳制,一般按照 1432 设置就可以,也有人建议避免潜在麻烦直接设置到RFC 规范限制的最小 ipv6 包 1280 ,mss = 1280 - 60 = 1220 (有些人说设置到 1280 并不正确)

  6. mss clamping 原理:tcp 握手阶段,双边主机会在 syn 包中携带它所在链路能传输的最大 tcp 载荷信息,即 tcp-mss 信息,握手后用两边更小的那个 mss 来封装数据包。当双边主机都给出错误的 mss 信息时,通信就无法顺畅进行。例如常见的,假如双边主机都认为自己的链路 mtu 是 1500 ,当遇到遇到链路中间有 pppoe 或者其他隧道 mtu 更小的隧道时,通信就无法正常进行。mss clamping 就是修改握手数据包把双边通告的 tcp-mss 调整到能通过路由器的正确的大小。理论上只要一边是对的,就能正常通信。只需要单边 clamping

  7. 因此除了 mss clamping ,我觉得更好的方式是修改路由器 ra 宣告 的 mtu 值到 1492 (默认 1500 ),让内网的主机知道正确的链路 mtu 。我已经抓包证实,ra mtu 改到 1492 后,内网发出的所有 syn 包的 tcp-mss 全部都是 1432 。

以上我的理解如有不对的帮我指正

回到标题

  1. 根据上面第 3 条,wireguard 接口在 pppoe 下使用 ipv6 建立连接正确的 mtu 应该是 1412 ,所以不修改默认的 1420 ,连通性应该是有问题的。 我搜索了一下确实有人遇到问题
  1. 然而,我在默认 1420 下用的一点毛病也没有 连日本 aws 能跑到 100M ,几乎没有断流的现象。所以这个点让我有点困惑,不知道需不需要调整,还是说 routeros 对 wireguard 是有处理的?

  2. 如果修改的话,需要客户端和服务端一起修改,如果只改客户端(在路由器上)不加 mss clamping 反而会出现连通性问题。原因应该是路由器下的主机不知道有 wg 的存在发起 syn 还是基于 1492 的 mtu ,wg 服务端因为隧道就在主机上,他会用 1420mtu 握手,最终取小的 1420 进行通信。如果路由器客户端修改到了 1412 。他们协商的 1420 将无法通过路由器的接口。必须 clamping

以上,有没有大佬能答疑解惑

3856 次点击
所在节点    宽带症候群
8 条回复
neroxps
2023-07-19 15:39:28 +08:00
额,那个,wireguard 是 udp 协议吧? UDP 协议没法确定 mss 啊,收到就收到,收不到路由直接丢弃。这就解析了为何需要两端都必须配置对的 MTU
ppbaozi
2023-07-19 16:07:51 +08:00
@neroxps wg 协议不能,但是隧道内的 tcp 可以。只需要把隧道内的 tcp mms 到 1352 ,至少在传输 tcp 流量时 wg 的包不会超过 1412 ?
yuchenr
2023-07-19 16:15:00 +08:00
需要,但我不知道如何确定最大值。
我尝试过把 WireGuard 的 mtu 设置为 1340 和 1280 测试结果如下:
1 、当使用 1340 时,IPv4 入站没问题。IPv6 入站 无法解析 DNS
2 、当使用 1280 时,IPv4 和 IPv6 均无异常。
maybeonly
2023-07-19 16:16:36 +08:00
当分片太大的时候,v4 可以路由器帮你分片,但是 v6 就要求路由器给发送方返一个 icmpv6type2 ( too big ),要求源站分片后重发。
这样的话,即使 mtu 设置不正确,也可以最终送达才对,只是在最初建立连接的时候多花了不超过 1rtt 。

mtu 的那个所谓卡住的“bug”往往是这么发生的:
你的 syn 到了服务端,然后服务端返了 syn/ack 给你,再然后你 ack 过去。到这里都没问题。
接下来就有问题了。你发出去的第一个带载荷的数据包可以到达服务器(最多就是被路由之类的戳一下 too big ),但是服务器返回的包就没那么幸运了。
典型的场景是这样的:服务器那边的 ip 是个虚拟 ip ( vip ),然后负载均衡器( vs )没有正确转发给真实服务器( rs )(对于 dr/tun/nat ),甚至压根就不能转发( toa )。
或者比较少见的情况,服务器那边配置了防火墙,根本就没允许 icmpv6type2 过。
结果都是,服务器收不到 too big ,没机会调整分片大小重发,最后就卡住了。

直接喊 1280 是可以“通”的,因为 ipv6 要求的最小 mtu 就是 1280——所以诸多压根不能转发的 toa 实现就直接做成了强制 1280——但是能不能“好”就是另一回事了。

出现隧道的时候,就更复杂了。隧道外边和里边是两层,可能会有不同大小的 mtu 。如果外层都 1280 了里层怎么过啊?又得分片反而不是什么好事情。至于 Clamping ,其实在一边双向 clamping 也是可以的。

最后,mtu 对所有 ip 报文都适用,clamping 或者说 mss 只用于 tcp ,也就是说,一些其他场景还是需要 too big 。
huangya
2023-07-19 19:05:19 +08:00
>然而,我在默认 1420 下用的一点毛病也没有 连日本 aws 能跑到 100M ,几乎没有断流的现象。所以这个点让我有点困惑,不知道需不需要调整,还是说 routeros 对 wireguard 是有处理的?

你可以在 aws 那边抓下包看下有没有收到最大为 1500 的包。也可以看下解密之后的包(也就是脱掉 wg 层)的 mss(tcp 场景)是多少
Love4Taylor
2023-07-19 19:14:22 +08:00
我记得没错的话 warp 为了兼容性 mtu 就给的小,好像是 1280
wolfworks
2023-07-19 21:36:27 +08:00
@huangya 印象中 1420 的 MTU 已经考虑隧道里面跑 IPv6 的情况了 IPv6 的 IP 头比 IPv4 长 20 个字节 所以外面 PPPoE 哪怕是 1480 的 MTU ,内层 IPv4 按 1420 来的话,应该也不会触发分片
lovelylain
2023-07-19 22:16:55 +08:00
要的,之前按网上搜到的设置 1400 ,后来又搜了一下,并通过带不分片参数的 ping 包做测试,pppoe 接口的 mtu1492 ,设置 wg 接口 mtu 大于 1412 ,走 ipv6 ,ping 包超过 1412 就没响应了,所以最终调整成了 1412 。
另外还测了 wg over frp-tcp over frp-xtcp ,好像是 1452 还是多少,没弄明白为什么是这个数。

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

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

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

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

© 2021 V2EX