求助 QUIC 协议走 Wireguard 代理不通的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
jinliming2
V2EX    程序员

求助 QUIC 协议走 Wireguard 代理不通的问题

  •  
  •   jinliming2
    jinliming2 2024-09-19 23:28:42 +08:00 2821 次点击
    这是一个创建于 388 天前的主题,其中的信息可能已经有所发展或是发生改变。

    环境

    电脑 --- 路由器 --- 跳板服务 --- 目标服务器

    电脑 IP:10.10.*.*

    路由器 Wireguard IP:192.168.69.1

    要访问的远程服务器 IP:17.*.*.*

    问题

    电脑在内网,路由器上配置了 Wireguard ,Wireguard 另一端跳板服务在公网。现在内网的电脑想通过 Wireguard 访问到公网的服务器的 QUIC 协议的服务。

    现在情况是,如果不走 Wireguard ,电脑通过路由器是可以正常访问到目标服务的,没有问题。但是配置走了 Wireguard ,就无法正常访问了。

    conntrack 和 Wireshark 抓包的结果:

    看起来是电脑在发送 QUIC 请求,服务端返回了响应包,但是电脑对收到的每个响应包都会回一个 ICMP Port unreachable 的响应,导致连接立即被中断 DESTROY 。

    尝试排查

    因为 QUIC 协议是基于 UDP 的,所以我拿 Node.JS 简单写了个测试程序,在服务器上监听 UDP 端口,做一个 echo 服务,电脑上给服务端发 UDP 请求,服务端给返回多个响应包:

    服务端:

    import dgram from 'node:dgram'; const server = dgram.createSocket('udp4'); server.bind(443); server.addListener('message', async (msg, rinfo) => { console.log(`Received ${msg.length} bytes from ${rinfo.address}:${rinfo.port}: ${msg}`); for (let i = 0; i < 5; ++i) { // 延迟 1 秒 await new Promise(r => setTimeout(r, 1e3)); server.send(Buffer.concat([msg, Buffer.from(i.toString())]), rinfo.port, rinfo.address, (error, bytes) => { console.log('send to', rinfo.address, rinfo.port, error, 'bytes', bytes); }); } }); 

    客户端:

    import dgram from 'node:dgram'; const socket = dgram.createSocket('udp4'); socket.addListener('message', (msg, rinfo) => { console.log(`Received ${msg.length} bytes from ${rinfo.address}:${rinfo.port}: ${msg}`); }); socket.send("asd", 443, " [脱敏,远端 IP ] "); 

    结果是正常的,电脑上运行客户端代码,会用一个随机端口给服务器的 443 发请求,服务端收到的包显示远端 IP 是 Wireguard 远端的 IP ,表示数据包确实是走 Wireguard 转发到服务端的,然后服务端回复给 Wireguard 远端的 5 个包也都能正常被内网的电脑收到。


    目前没有其他头绪了,来求助问一下,还有什么方向可以排查的吗?可能是什么问题呢?

    5 条回复    2024-09-23 03:24:29 +08:00
    cnbatch
        1
    cnbatch  
       2024-09-19 23:33:48 +08:00
    可能是 WireGuard 的 MTU 值不够小
    RobinHuuu
        2
    RobinHuuu  
       2024-09-20 07:52:14 +08:00 via Android
    使用 ping 排查 mtu 问题
    pagxir
        3
    pagxir  
       2024-09-20 11:28:10 +08:00 via Android
    如果全部遵守规范的话,那就只可能是 17 的那个机器没有 quic 服务,或者没在这个 IP 上运行 quic 服务,或者是防火墙不允许。
    qilme
        4
    qilme  
       2024-09-20 13:01:54 +08:00 via Android
    是否有哪个环节用了 http/socks5 代理,这两个不支持 quic
    jinliming2
        5
    jinliming2  
    OP
       2024-09-23 03:24:29 +08:00
    @cnbatch @RobinHuuu 经过排查,不是 MTU 的问题,但是感谢提供 ping 的思路,通过 ping 发现具体的问题了。

    通过 ping ,发现只有 icmp_seq 序号为偶数( 0 、2 、4……)的 ping 包才能收到响应,而奇数的包都是超时。就去排查 nftables 规则,发现问题所在:

    我给指定服务器做转发,是在 nat 的 prerouting 链上判断目标地址为 17 服务器的包打上 meta mark ,然后在 ip rule 里匹配 fwmark lookup 表,default 路由到 Wireguard 的 wg0 出口。

    看了下文档,nat 链只在第一个包会命中,后续包就跳过了。因为有 conntrack 跟踪数据包信息,所以 UDP 包也是只在第一个包会命中,后续包不会命中,导致只有第一个握手包发给了 Wireguard ,后续包都从物理网卡直接出去了,导致了 conntrack 同一个内网 IP + 端口对应不同的出口,触发了 conntrack 的 destroy ,所以服务端响应的包就找不到 NAT 回复的目标了。

    我自己写的 UDP 测试程序之所以没问题,是因为每次电脑端每次发送都是用的随机 UDP 端口发一个包,conntrack 只跟踪第一个包,所以正常。如果给客户端代码也加上 bind ,使用相同端口来请求,就会发现和 ping 一样的,一次通,一次不通,分别是 conntrack 的 NEW 和 DESTROY 。

    解法是在 meta mark set 的同时加上 ct mark set meta mark 给 conntrack 也打上标记,然后加了个 filter prerouting 的 mangle 链,匹配 ct mark 也设置上 meta mark set 就好了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5266 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 05:44 PVG 13:44 LAX 22:44 JFK 01:44
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86