V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ppbaozi
V2EX  ›  宽带症候群

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

  •  
  •   ppbaozi · 285 天前 · 2835 次点击
    这是一个创建于 285 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先说说我对 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 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

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

    第 1 条附言  ·  284 天前
    发现 wg-quick 开启的隧道在配置未指定 mtu 时不一定默认用 1420

    会用默认出口路由的链接 mtu-80: https://zhuanlan.zhihu.com/p/532370376

    aws 日本的 vps 网口开了巨帧,wg 默认 mtu 是 9001 - 80 = 8921
    第 2 条附言  ·  284 天前
    1. 抓包发现,在pppoe下使用默认1420会出现ip分片。ipv6不能在链路之间被分片但可以在主机侧分片。当客户端和服务端能正确的发现pmtu(1492)时会对基于1420的wg数据包进行分片,使用1412就不会出现分片,这种情况不会影响连通性,但会折损一些速度

    2. mss只需要单向clamping是不对的,参考openwrt的历史bug。在PMTUD失效时,路由器两边的主机可能都不知道链路上有更小的mtu

    我遇到问题的场景:

    • 路由器wg口mtu设置为1412,只在出站方向clamp-mss-to-pmtu
    • 客户端使用默认mtu 1420连接路由器
    • 客户端访问部分网址可以握手可以发出client hello但收不到server hello,导致一直重传

    原因可能是客户端使用的mss是1420 - 60 = 1360 入站没有被clamp,服务器收到客户端mss 1360,服务器使用mss 1500 - 60 = 1440,被clamp到 1412 - 60 = 1352,客户端会用正确的1352来封包。服务器会用错误的1360来封包。1360的包会被路由器丢掉。

    mtu 都设置成相同的值 或者 双向 clamp-mss-to-pmtu 都可以解决问题

    8 条回复    2023-07-19 22:16:55 +08:00
    neroxps
        1
    neroxps  
       285 天前
    额,那个,wireguard 是 udp 协议吧? UDP 协议没法确定 mss 啊,收到就收到,收不到路由直接丢弃。这就解析了为何需要两端都必须配置对的 MTU
    ppbaozi
        2
    ppbaozi  
    OP
       285 天前
    @neroxps wg 协议不能,但是隧道内的 tcp 可以。只需要把隧道内的 tcp mms 到 1352 ,至少在传输 tcp 流量时 wg 的包不会超过 1412 ?
    yuchenr
        3
    yuchenr  
       285 天前
    需要,但我不知道如何确定最大值。
    我尝试过把 WireGuard 的 mtu 设置为 1340 和 1280 测试结果如下:
    1 、当使用 1340 时,IPv4 入站没问题。IPv6 入站 无法解析 DNS
    2 、当使用 1280 时,IPv4 和 IPv6 均无异常。
    maybeonly
        4
    maybeonly  
       285 天前
    当分片太大的时候,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
        5
    huangya  
       285 天前
    >然而,我在默认 1420 下用的一点毛病也没有 连日本 aws 能跑到 100M ,几乎没有断流的现象。所以这个点让我有点困惑,不知道需不需要调整,还是说 routeros 对 wireguard 是有处理的?

    你可以在 aws 那边抓下包看下有没有收到最大为 1500 的包。也可以看下解密之后的包(也就是脱掉 wg 层)的 mss(tcp 场景)是多少
    Love4Taylor
        6
    Love4Taylor  
       285 天前
    我记得没错的话 warp 为了兼容性 mtu 就给的小,好像是 1280
    wolfworks
        7
    wolfworks  
       285 天前
    @huangya 印象中 1420 的 MTU 已经考虑隧道里面跑 IPv6 的情况了 IPv6 的 IP 头比 IPv4 长 20 个字节 所以外面 PPPoE 哪怕是 1480 的 MTU ,内层 IPv4 按 1420 来的话,应该也不会触发分片
    lovelylain
        8
    lovelylain  
       285 天前 via Android
    要的,之前按网上搜到的设置 1400 ,后来又搜了一下,并通过带不分片参数的 ping 包做测试,pppoe 接口的 mtu1492 ,设置 wg 接口 mtu 大于 1412 ,走 ipv6 ,ping 包超过 1412 就没响应了,所以最终调整成了 1412 。
    另外还测了 wg over frp-tcp over frp-xtcp ,好像是 1452 还是多少,没弄明白为什么是这个数。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4863 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 03:55 · PVG 11:55 · LAX 20:55 · JFK 23:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.