Skip to content

Latest commit

 

History

History
111 lines (60 loc) · 5.77 KB

vless_v1.md

File metadata and controls

111 lines (60 loc) · 5.77 KB

vless v1 标准

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

v2ray/v2ray-core#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的分离信道方式还是要先读取一字节, 所以还是要缓存, 所以完全没必要。