Xray-core icon indicating copy to clipboard operation
Xray-core copied to clipboard

Add Datagram transport

Open yuhan6665 opened this issue 11 months ago • 32 comments

yuhan6665 avatar Jan 13 '25 04:01 yuhan6665

This is a early draft for Datagram transport, a new Unreliable protocol that does NOT handle packets loss retransmission. The code is a reborn of previous removed QUIC transport. (without additional setting like "security" and "header") Future planned improvement including adding FEC.

CC @RPRX @Fangliding

yuhan6665 avatar Jan 13 '25 04:01 yuhan6665

生成 .pb.go 先用和 main 一致的吧

纯 QUIC 的话我感觉 TLS+ALPN H3 这种配置方式更合适

这个怎么识别它要传输的是 UDP,以及 H3 好像也能 datagram,试试直接加进 XHTTP?

RPRX avatar Jan 13 '25 13:01 RPRX

datagram是不可靠的吧 所有ray里的协议期望的都是可靠数据流 除了部分“原生UDP协议”(socks ss) 这些协议调用UDP连接的时候会绕过transport组件 至于整合进xhttp问题是类似的 ray的transport只暴露给上层可靠数据流的传送接口 多一个“不可靠数据”也没地可用 还得改结构 以及HTTP datagram的规定不符合xhttp的模型(不允许通过GET/POST发送)

Fangliding avatar Jan 13 '25 13:01 Fangliding

  • proto 改回去了
  • 之前讨论过 https://blog.cloudflare.com/unlocking-quic-proxying-potential/ 最后一个图 看文章的意思是 不可靠连接也可以代理 TCP 不知道实际使用的效果是不是差点意思 Datagram 本身不限制 UDP 所以我目前打算不限制
  • 我研究了 HTTP Datagram 结论是似乎没必要 因为 Datagram 就是要“想发就发” HTTP 要等待 Settings Frame 我认为不需要。也没有必要与 XHTTP 合并 因为特性不一样
  • “原生UDP协议”(socks ss) 这块 将来可以再改改

yuhan6665 avatar Jan 13 '25 14:01 yuhan6665

图里的示例是未终结TCP的情况(MASQUE直接处理三层IP包) 在这种情况下可靠性是双端的TCP程序保证的所以可以这么用(类比L3 VPN) 但是Xray处理的是四层流量终结了TCP所以自己也得可靠不能用不可靠tunnel传输

Fangliding avatar Jan 13 '25 15:01 Fangliding

图里的示例是未终结TCP的情况(MASQUE直接处理三层IP包) 在这种情况下可靠性是双端的TCP程序保证的所以可以这么用(类比L3 VPN) 但是Xray处理的是四层流量终结了TCP所以自己也得可靠不能用不可靠tunnel传输

Ok I see. In that case probably Datagram is only suitable for UDP proxy for us at the moment.

yuhan6665 avatar Jan 13 '25 15:01 yuhan6665

话说是不是重叠了,这里已经有一个想发就发的 UDP 协议了 (mkcp) ,既然是 ray 系专属 kcp 所以不需要考虑外部兼容性的话给 mkcp 加个 no-ack-comfirm 可能更简单一些。

ll11l1lIllIl1lll avatar Jan 13 '25 16:01 ll11l1lIllIl1lll

话说是不是重叠了,这里已经有一个想发就发的 UDP 协议了 (mkcp) ,既然是 ray 系专属 kcp 所以不需要考虑外部兼容性的话给 mkcp 加个 no-ack-comfirm 可能更简单一些。

That's interesting comparison. Note that Datagram also does DTLS ~~and Mux~~ out-of-box.

yuhan6665 avatar Jan 13 '25 16:01 yuhan6665

话说是不是重叠了,这里已经有一个想发就发的 UDP 协议了 (mkcp) ,既然是 ray 系专属 kcp 所以不需要考虑外部兼容性的话给 mkcp 加个 no-ack-comfirm 可能更简单一些。

KCP去掉ACK重传那不是等于TLS去掉加密 主要目的都给去掉了

Fangliding avatar Jan 13 '25 17:01 Fangliding

也许,它可以用于代理 h3,没有“流中流”(两层流控)问题

xqzr avatar Jan 14 '25 15:01 xqzr

也许,它可以用于代理 h3,没有“流中流”(两层流控)问题

yes, not sure what it actually behave but the plan is to carry normal UDP and QUIC traffic

yuhan6665 avatar Jan 14 '25 15:01 yuhan6665

又读了一下 RFC https://datatracker.ietf.org/doc/rfc9297/ 之前理解错了 Mux 是由 HTTP Datagram 提供的 所以目前实现的 QUIC Datagram 是没有 Mux 我再研究一下估计还是得改成 HTTP Datagram

yuhan6665 avatar Jan 15 '25 03:01 yuhan6665

这个与 VLESS/XUDP 层面配合的话可以实现传输 unreliable UDP,或者 TUN TCP,IP 包 ICMP 之类的,也需要给 VLESS 加料

之前频道对线我有提过想给 XHTTP H3 加个 datagram,这是 QUIC/Hy/TUIC 有的功能,我看了下 H3 也有,应该能加

能藏在 Nginx 后面、直连能用就行,不追求过 CDN,然后再给 Nginx QUIC 改个 gentle 发包,表现上应该不输 Hy/TUIC

RPRX avatar Jan 15 '25 13:01 RPRX

就是说我觉得不是 QUIC datagram 有没有 mux 的问题,而是不加个伪装站的话一个主动探测就没了,所以应该搞 H3 datagram

之前把 QUIC、HTTP 传输层删了也是同理,前者没伪装站,后者没 header padding https://github.com/XTLS/Xray-core/issues/3272#issuecomment-2585736479 ,都太假了,没必要

RPRX avatar Jan 15 '25 13:01 RPRX

datagram只是提供一个传输不可靠数据的方法 没有提供代理方案(不像h3 connect) 但是作为一个代理协议这部分肯定是自己处理的(比如xudp 如果真的可以实现的话) 这倒是问题不大 主动探测和padding都问题非常小 QUIC本身非常灵活 隔壁hy就是用h3鉴权 后续切换到自有协议 甚至鉴权和请求都可以同时发起 只要鉴权请求先到就行了 鉴权失败转发到伪装站 这个auth包随便padding 包括QUIC本身也提供了padding还有一些把流量打乱的方法

Fangliding avatar Jan 16 '25 05:01 Fangliding

我觉得既然现在这些 QUIC 代理都是服务端 quic-go 特征,我们搞个差异化的能藏到 Nginx 后面更好,提供它们没有的价值

没 padding 的问题,只要有设计当然就不是问题,但是强制 padding 就成新协议了,没必要再继承 HTTP 传输层这种名字

QUIC 这块的话弄 fallbacks 或内置 Web,这是 REALITY 出现以前的思路,日后弄 REALITY QUIC 就覆盖了直接 QUIC 的需求

RPRX avatar Jan 16 '25 11:01 RPRX

关于 gentle 发包,这个是我想弄的与 brutal 相对的策略,合理积极探测网络上限、适度对抗丢包,而不是没达到想要的速率就使劲发包,整得跟饱和攻击一样,~~虽然饱和攻击的优点是利于对抗丢包~~,而且引入 brutal 要协议层面交换期望速率,但引入 gentle 不需要,至于为什么不弄 bbrv3 是因为懒得研究且懒得按它的标准去实现,我觉得自己弄个简单粗暴一点、适合代理用的就行

RPRX avatar Jan 16 '25 11:01 RPRX

我研究了一下 quic-go 和其 h3 的 EnableDatagrams,它可以被转译为 h2,Nginx 应该支持转发,只是不知道 ~~CF~~ CDN 是否支持

目前如果想做到 UDP 包走 XHTTP/3 datagram 是完全可行的,鉴于 UDP 可能被 Q 还可以允许配置为只让 UDP 包走 XHTTP/3

虽然路由也能做这件事,还有如果只想让少量 UDP 包走 XHTTP/3,还得把被代理流量的 UDP 443 禁了

RPRX avatar Mar 06 '25 14:03 RPRX

放h2里不变可靠流了 没意义了

Fangliding avatar Mar 06 '25 14:03 Fangliding

放h2里不变可靠流了 没意义了

Nginx 最多只支持 h2c 回源,意义在于它和 Xray 通信,CDN 同理,容易丢包的阶段是境内到境外段,这一段需要 datagram

RPRX avatar Mar 06 '25 14:03 RPRX

~~频道消息下面有个广告~~

RPRX avatar Mar 06 '25 14:03 RPRX

现在重点在于研究如何在 Xray 服务端构造出来能被 Nginx 转义为 H3 datagram 的 h2c 包,或许 @yin1999 有空研究下?

RPRX avatar Mar 06 '25 14:03 RPRX

放h2里不变可靠流了 没意义了

Nginx 最多只支持 h2c 回源,意义在于它和 Xray 通信,CDN 同理,容易丢包的阶段是境内到境外段,这一段需要 datagram

这扯有点远了 这个9297基本就是给后面的masque开绿灯而已 没有别的转发器支持他 不管是ng还是cf

"能被 Nginx 转义为 H3 datagram 的 h2c 包" 这怎么可能啊 ng压根不会发这种包不说 datagram frame 是quic的东西 h2完全没这样的东西 除非自己写个专有的包装格式再转发一下(很明显不太现实)

Fangliding avatar Mar 06 '25 14:03 Fangliding

我今天粗略看了下 9297,人家说的是 HTTP datagram 而不只是 h3,给出了 h2 的情况并指出丧失了“不可靠性”

RPRX avatar Mar 06 '25 14:03 RPRX

Nginx 最多只支持 h2c 回源,意义在于它和 Xray 通信

如果用 UDS(而不是 TCP)回源就不是“可靠”了吧🤔

xqzr avatar Mar 06 '25 14:03 xqzr

我今天粗略看了下 9297,人家说的是 HTTP datagram 而不只是 h3,给出了 h2 的情况并指出丧失了“不可靠性”

那还是老话 不支持这个frame会直接炸 image

Fangliding avatar Mar 06 '25 14:03 Fangliding

这倒不是大问题,h3 datagram 的格式和非 h3 时 capsule protocol 的格式都在 9297 中写明了,改代码很简单

毕竟我们还要 patch Nginx 让它支持别的 QUIC 拥塞控制,一个 patch 版的 Nginx 是不可避免的,这就是 XHTTP 接下来的方向

RPRX avatar Mar 06 '25 14:03 RPRX

目前进度:datagram 可以发了 大包通过 stream 也可以发了 但是测试遇到一个问题:在 MTU 临界值的包比如 1247 一开始是走 stream 的 后来似乎 quic-go 内部的 MTU 会增大 使得它开始尝试发 datagram 但是实际上会丢包 需要研究一下 quic-go

另外不用 h3 datagram 的原因是我们只需要一层 mux 目前 XUDP 带有 mux address global-id 一系列好东西 节省掉 h3 的 Quarter Stream ID 可以省点包长

yuhan6665 avatar Mar 10 '25 03:03 yuhan6665

如果实在想把 QUIC transport 加回来,可以是 TLS ALPN 有且只有 h3 的形式,我之前把 TCP 改成 RAW 就是为这种情况做铺垫

RPRX avatar Mar 10 '25 12:03 RPRX

Server:

            "protocol": "vless",
            "settings": {...},
            "streamSettings": {
                "network": "datagram",
                "security": "tls",
                "tlsSettings": {...}
            }

Client:

Outbound
    {
      "mux": {
        "concurrency": 10,
        "enabled": true,
        "xudpConcurrency": 10,
        "xudpProxyUDP443": "allow"
      },
      "protocol": "vless",
      "settings": {
        "vnext": [
          {...}
        ]
      },
      "streamSettings": {
        "network": "datagram",
        "security": "tls",
        "tlsSettings": {...}
      },
      "tag": "datagram"
    },
Routing
     {
        "network": "udp",
        "outboundTag": "datagram"
      },

yuhan6665 avatar Mar 17 '25 03:03 yuhan6665