线路兼容性
本页面记录与现有 Xray-core 实例互操作所需的精确线路格式。你的实现必须严格按照这些格式生成和解析字节数据。
VLESS 线路格式
请求(客户端 -> 服务端)
偏移量 大小 字段
0 1 版本(0x00)
1 16 UUID(原始字节,非十六进制字符串)
17 1 Addons 长度(N)
18 N Addons(Protobuf 编码的 Addons 消息,N=0 时为空)
18+N 1 命令:0x01=TCP、0x02=UDP、0x03=Mux、0x04=Reverse
19+N ... 地址(Mux/Reverse 时省略):
端口:2 字节大端序
地址类型:0x01=IPv4、0x02=域名、0x03=IPv6
地址:
IPv4:4 字节
域名:1 字节长度 + 域名字符串
IPv6:16 字节Addons Protobuf:
message Addons {
string Flow = 1; // "xtls-rprx-vision" 或空
bytes Seed = 2;
}Flow 为空时:addons 长度 = 0(单个 0x00 字节)。 Flow 有值时:进行 Protobuf 编码并写入长度 + 数据。
响应(服务端 -> 客户端)
偏移量 大小 字段
0 1 版本(回显请求版本,0x00)
1 1 Addons 长度(N)
2 N Addons(Protobuf 编码,通常为空)VLESS Body
| 命令 | Body 格式 |
|---|---|
| TCP(无 Vision) | 原始流字节 |
| UDP | [2B 长度 大端序][载荷] 重复 |
| Mux | Mux 帧格式(见下文) |
| Mux 端口=666 | XUDP 帧格式(见下文) |
VMess 线路格式(AEAD)
Auth Info(16 字节)
authID = HMAC-MD5(key=MD5(UUID + timestamp/30s), data=timestamp + random)请求头
[16B AuthID]
[2B 加密长度] (AES-128-GCM,密钥派生自 authID)
[NB 加密命令] (AES-128-GCM,密钥派生自 authID)解密后的命令:
1B 版本(1)
16B 请求 Body IV
16B 请求 Body Key
1B 响应认证 V
1B 选项(0x01=ChunkStream、0x02=ConnectionReuse、0x04=ChunkMasking、0x08=GlobalPadding、0x10=AuthenticatedLength)
1B 填充长度 + 安全算法
1B 保留
1B 命令(0x01=TCP、0x02=UDP、0x03=Mux)
2B 端口(大端序)
1B 地址类型
NB 地址
NB 随机填充
4B FNV1a32 校验和响应头
1B 响应认证 V(必须与请求匹配)
1B 选项
1B 命令
1B 命令长度Body(AES-128-GCM)
[2B 长度(AES-GCM 加密)]
[NB 载荷(AES-GCM 加密)]
[2B 长度]
[NB 载荷]
...
[2B 0x0000] (结束标记)Nonce:基于计数器,每个分块递增。
Trojan 线路格式
请求
[56B Hex(SHA224(password))] (小写十六进制字符串,非二进制)
[2B CRLF(0x0D 0x0A)]
[1B 命令:0x01=TCP、0x03=UDP]
[1B 地址类型:0x01=IPv4、0x03=域名、0x04=IPv6]
[NB 地址]
[2B 端口(大端序)]
[2B CRLF(0x0D 0x0A)]
[... 载荷]UDP 分帧(命令 = 0x03)
[1B 地址类型]
[NB 地址]
[2B 端口(大端序)]
[2B 载荷长度(大端序)]
[2B CRLF]
[NB 载荷]每个 UDP 数据包重复上述结构。
Mux 帧格式
帧头
[2B 元数据长度(大端序)] — 后续元数据的长度
[2B 会话 ID(大端序)]
[1B 状态:0x01=New、0x02=Keep、0x03=End、0x04=KeepAlive]
[1B 选项:bit 0=数据、bit 1=错误]新建会话(Status=0x01)
[... 帧头]
[1B 网络协议:0x01=TCP、0x02=UDP]
[2B 端口(大端序)]
[1B 地址类型:0x01=IPv4、0x02=域名、0x03=IPv6]
[NB 地址]数据载荷(选项包含数据位时)
帧头/元数据之后:
[2B 数据长度(大端序)]
[NB 数据]会话结束(Status=0x03)
仅包含帧头,无附加字段。
XUDP 帧格式
与 Mux 结构相同,但:
- 会话 ID 始终为
0x0000 - 首帧在地址之后包含 8 字节 GlobalID
- Keep 帧包含逐包目标地址
XUDP 新建会话
[2B 元数据长度]
[00 00] 会话 ID = 0
[01] 状态 = New
[01] 选项 = 数据
[02] 网络协议 = UDP
[2B 端口(大端序)]
[1B 地址类型]
[NB 地址]
[8B GlobalID] 客户端源地址的 BLAKE3 哈希
[2B 数据长度(大端序)]
[NB UDP 载荷]XUDP Keep(后续数据包)
[2B 元数据长度]
[00 00] 会话 ID = 0
[02] 状态 = Keep
[01] 选项 = 数据
[02] 网络协议 = UDP (存在逐包目标地址时)
[2B 端口(大端序)] (此数据包的目标地址)
[1B 地址类型]
[NB 地址]
[2B 数据长度(大端序)]
[NB UDP 载荷]Vision 填充格式
[16B UserUUID] (仅在首帧中,之后省略)
[1B 命令] 0x00=继续、0x01=结束、0x02=直连
[2B 内容长度(大端序)]
[2B 填充长度(大端序)]
[NB 内容]
[NB 填充(随机字节)]多个填充块可以在一次写入中拼接。
地址编码
所有协议使用相同的地址编码:
IPv4: 类型=0x01,后跟 4 字节
域名: 类型=0x02,后跟 1 字节长度 + 域名字符串
IPv6: 类型=0x03,后跟 16 字节端口始终为 2 字节大端序,写在地址之前(端口优先顺序)。
关键兼容性说明
UUID 编码:原始 16 字节,非带连字符的字符串形式。
Protobuf 线路格式:VLESS addons 使用标准 Protobuf 编码。长度前缀为单个字节(非 varint),限制 addons 最大为 255 字节。
XUDP 会话 ID 0:这是服务端区分 XUDP 和普通 mux 的方式。普通 mux 的会话 ID 从 1 开始。
XUDP 魔术端口 666:当 VLESS outbound 将 UDP 转换为 XUDP 时,使用地址
v1.mux.cool和端口666。这是一个约定,不是线路格式细节(地址作为 VLESS 头部的一部分发送)。Vision UserUUID 仅出现一次:16 字节 UUID 仅出现在第一个填充帧中。如果第一帧不以预期的 UUID 开头,服务端将回退到非 Vision 模式。
Trojan 密码是十六进制:SHA224(password) 编码为 56 个小写十六进制字符(ASCII),非二进制。
VMess 时间窗口:auth ID 中的时间戳为
time.Now().Unix() / 30。服务端接受正负 120 秒的偏差(8 个时间周期)。字节序:除非另有说明,所有多字节整数均为大端序。
VLESS 回落检测:如果前 17 字节(版本 + UUID)不匹配任何用户且启用了回落,则整个缓冲的数据将被转发到回落目标。
Cone 模式标志:
cone上下文值决定 UDP 使用 XUDP(cone=true)还是独立的 mux 会话(cone=false)。这会影响使用的线路格式。