Files
v2ray_simple/docs/vless_v1.md
e1732a364fed 4964cb16c7 修订代码,文档;在allstate查询中输出tproxy信息;修复h2回落的一个bug
修复的bug:fb_h2c_PROXYprotocolAddrMap 的key应该为 wlc的raddr,而不是targetAddr。
2022-05-04 08:32:55 +08:00

5.8 KiB
Raw Blame History

vless v1 标准

本v1标准参考v0标准并着重针对addon和udp部分进行了一些改动。原v0标准请参考

https://github.com/v2ray/v2ray-core/issues/2636

v1的讨论 可以参考 vless_v1_discussion

本文为实际确定的具体标准,与讨论是有所不同的,讨论是非正式的, 有一些新想法, 在本标准中还未实现。

大家以本文为标准依据。

响应包包头的修改

v1部分不再具有 v0中所定义的响应包头部分。tcp响应 直接就为承载数据udp的话还是有特殊的定义请看下文。

因为响应包没有包头所以也不支持addon协商。如果服务端不支持 some addon or 不支持v0/v1的话应该无声地关闭底层连接而不返回任何响应。

addon 含义修改

对比v0的 addon第一字节为addon长度 剩余为 addon内容

v1发生变化 addon 第一字节 为addon类型指示, 剩余内容为响应类型的具体数据.

0 为无addon 1 为 udp_multi 标志. 开启此标志后, udp使用分离信道方式传输. 2 为 【多addon】标志, 此时第二字节为 addon的数量, 然后 第三字节 为 第一个addon的类型指示, 之后是第一个addon的数据块视addon类型而定, 比如 udp_multi标志就没有任何数据块然后是第二个addon的类型指示以此类推。

v1不再采用protobuf因为我们不应受制于任何复杂外部实现. 我们应该自有结构。

vless v0的addon主要被xray用来自定义xtls流控而因为本作作者已经发现xtls的漏洞并摒弃xtls开发了lazy技术所以也不会去继承xray的现有addon。

udp的 多路复用 与 分离信道

vless v1准备同时支持两种模式【经典的 类socks5/trojan 的多路复用】的方式,以及【分离信道】的方式。

究竟使用哪一种由 客户端决定,服务端将同时支持二者。

客户端使用 addon 部分来标识。

具体请看下文

udp包头确定

vless 的v0 始终处于beta中而且 【udp长度】的包头仅仅在 commit中所提及根本没写在该beta 文档里;

本作定义的 v1 对vless 的udp包头进行完整定义。

到底采用的是经典传输还是分离信道传输由握手部分的addon决定上文已经讲过。

在经典传输时每一个udp数据报 都采用如下格式 第 1、2字节 为 port。第3字节为 atype然后是变长的addr内容定义与tcp的握手的包头一致。接着是udp数据包长度的2字节然后是承载数据。

这样的格式是十分 类似 socks5/trojan 的在经典传输时也能支持fullcone。

与v0的区别是v0只在首包传输port和addr而我们每一个数据包 包头都具有 port 和 addr。

在 分离信道传输时,

一,客户端发送的格式: 首个客户端握手包的握手部分采用与tcp相同的格式

    接着是udp数据包前两字节为数据长度的2字节然后是承载数据。

    与经典传输的区别是每个数据包的包头并没有port和addr因此确实是分离信道, 客户端在该信道上传输 的udp目标地址 是确定、唯一的。

二,服务端发送的格式:
    因为我们服务端发往 客户端的方向 有时需要传输 UMFURS 信息,所以我们需要一字节来指示本次数据包的意义。
    
    第一字节为数据包意义指示,
    
        0标识 普通 来自原始raddr的数据包此时 第二字节和第三字节为数据长度,然后跟着数据;

        1标识 UMFURS 数据, 此时,第 2、3字节 为 port。第4字节为 atype然后是变长的addr内容定义与tcp的握手的包头一致。接着是udp数据包长度的2字节然后是承载数据。

内层mux

在cmdmux给出时使用内层mux使用 smux+simplesocks。关于simplesocks的情况 请阅读 trojan-go的文档。 我们的mux标准 除了包头是vless格式以外其余部分 完全与trojan-go一致

vless v1 所解决的问题

fullcone

v1对 udp 添加了 两种可支持fullcone的方式【经典多路复用】方式 以及 【分离信道】方式。

而v0连经典的多路复用转发udp数据包的fullcone都没有做到只能支持symmetric NAT因为v0协议缺少 udp的raddr部分。

【经典多路复用】方式 实际上就是trojan/socks5 所使用的方式。

udp分离信道方式发送 性能会比默认的 多路复用 发送性能要高。也就是说在同样实现fullcone的情况下在向不同远程地址同时发送数据时vless v1 比 trojan 快。

在有大量向不同 远程地址发送的 udp链接 存在时,才能体现出 分离信道 的优势 , 比如一些 实时游戏/多人视频会议。

mux

使用smux 以避免 mux.cool 的众多问题。

其他情况

传输在websocket之上的情况

之前还讨论过 在使用ws/grpc时免除udp长度信息的计划。

而同样作为高级层quic因为传输的是流, 不满足包的特征,是无法免去长度信息的。

之前以为grpc也是基于流的毕竟基于的h2有stream的概念但是后来阅读 clash的 gun.go 后才了解到原来grpc也是基于包的。

仔细思考, 免除udp长度信息主要是为了避免读取端 进行额外缓存, 减少读取端的拷贝

但是, 一旦实施的话,实际上会增加 发送端的 buf, 发送端需要一次额外拷贝到buf中, 再整体一起写入 websocket, 所以实际上 如果 把 【发送端和接收端】 作为一个 整体 来考虑的话, 该计划并没有减少任何 内存拷贝, 而且还增加了代码复杂度。

因此,讨论中的 免除udp长度信息的计划 不切实际,不予支持。

而且, v1的分离信道方式还是要先读取一字节, 所以还是要缓存, 所以完全没必要。