Skip to content

线路兼容性

本页面记录与现有 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

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 长度 大端序][载荷] 重复
MuxMux 帧格式(见下文)
Mux 端口=666XUDP 帧格式(见下文)

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 字节大端序,写在地址之前(端口优先顺序)。

关键兼容性说明

  1. UUID 编码:原始 16 字节,非带连字符的字符串形式。

  2. Protobuf 线路格式:VLESS addons 使用标准 Protobuf 编码。长度前缀为单个字节(非 varint),限制 addons 最大为 255 字节。

  3. XUDP 会话 ID 0:这是服务端区分 XUDP 和普通 mux 的方式。普通 mux 的会话 ID 从 1 开始。

  4. XUDP 魔术端口 666:当 VLESS outbound 将 UDP 转换为 XUDP 时,使用地址 v1.mux.cool 和端口 666。这是一个约定,不是线路格式细节(地址作为 VLESS 头部的一部分发送)。

  5. Vision UserUUID 仅出现一次:16 字节 UUID 仅出现在第一个填充帧中。如果第一帧不以预期的 UUID 开头,服务端将回退到非 Vision 模式。

  6. Trojan 密码是十六进制:SHA224(password) 编码为 56 个小写十六进制字符(ASCII),非二进制。

  7. VMess 时间窗口:auth ID 中的时间戳为 time.Now().Unix() / 30。服务端接受正负 120 秒的偏差(8 个时间周期)。

  8. 字节序:除非另有说明,所有多字节整数均为大端序。

  9. VLESS 回落检测:如果前 17 字节(版本 + UUID)不匹配任何用户且启用了回落,则整个缓冲的数据将被转发到回落目标。

  10. Cone 模式标志cone 上下文值决定 UDP 使用 XUDP(cone=true)还是独立的 mux 会话(cone=false)。这会影响使用的线路格式。

用于重新实现目的的技术分析。