Skip to content

Wire Compatibility

This page documents the exact wire formats needed for interoperability with existing Xray-core instances. Your implementation must produce and consume bytes in exactly these formats.

VLESS Wire Format

Request (Client → Server)

Offset  Size  Field
0       1     Version (0x00)
1       16    UUID (raw bytes, NOT hex string)
17      1     Addons length (N)
18      N     Addons (protobuf-encoded Addons message, or empty if N=0)
18+N    1     Command: 0x01=TCP, 0x02=UDP, 0x03=Mux, 0x04=Reverse
19+N    ...   Address (omitted for Mux/Reverse):
                Port: 2 bytes big-endian
                AddrType: 0x01=IPv4, 0x02=Domain, 0x03=IPv6
                Address:
                  IPv4: 4 bytes
                  Domain: 1 byte length + domain string
                  IPv6: 16 bytes

Addons protobuf:

protobuf
message Addons {
    string Flow = 1;   // "xtls-rprx-vision" or empty
    bytes  Seed = 2;
}

When Flow is empty: addons length = 0 (single 0x00 byte). When Flow is set: protobuf-encode and write length + data.

Response (Server → Client)

Offset  Size  Field
0       1     Version (echoes request version, 0x00)
1       1     Addons length (N)
2       N     Addons (protobuf-encoded, usually empty)

VLESS Body

CommandBody Format
TCP (no Vision)Raw stream bytes
UDP[2B length BE][payload] repeated
MuxMux frame format (below)
Mux port=666XUDP frame format (below)

VMess Wire Format (AEAD)

Auth Info (16 bytes)

authID = HMAC-MD5(key=MD5(UUID + timestamp/30s), data=timestamp + random)

Request Header

[16B AuthID]
[2B  EncryptedLength]  (AES-128-GCM, key from authID)
[NB  EncryptedCommand] (AES-128-GCM, key from authID)

Decrypted command:

1B  Version (1)
16B Request Body IV
16B Request Body Key
1B  Response Auth V
1B  Option (0x01=ChunkStream, 0x02=ConnectionReuse, 0x04=ChunkMasking, 0x08=GlobalPadding, 0x10=AuthenticatedLength)
1B  Padding Length + Security
1B  Reserved
1B  Command (0x01=TCP, 0x02=UDP, 0x03=Mux)
2B  Port (BE)
1B  Address Type
NB  Address
NB  Random Padding
4B  FNV1a32 Checksum

Response Header

1B  Response Auth V (must match request)
1B  Option
1B  Command
1B  Command Length

Body (AES-128-GCM)

[2B Length (encrypted with AES-GCM)]
[NB Payload (encrypted with AES-GCM)]
[2B Length]
[NB Payload]
...
[2B 0x0000]  (end marker)

Nonce: counter-based, incremented per chunk.

Trojan Wire Format

Request

[56B Hex(SHA224(password))]  (lowercase hex string, NOT binary)
[2B  CRLF (0x0D 0x0A)]
[1B  Command: 0x01=TCP, 0x03=UDP]
[1B  Address Type: 0x01=IPv4, 0x03=Domain, 0x04=IPv6]
[NB  Address]
[2B  Port (BE)]
[2B  CRLF (0x0D 0x0A)]
[... Payload]

UDP Framing (Command = 0x03)

[1B  Address Type]
[NB  Address]
[2B  Port (BE)]
[2B  Payload Length (BE)]
[2B  CRLF]
[NB  Payload]

Repeated for each UDP packet.

Mux Frame Format

Frame Header

[2B Meta Length (BE)]  — length of following metadata
[2B Session ID (BE)]
[1B Status: 0x01=New, 0x02=Keep, 0x03=End, 0x04=KeepAlive]
[1B Option: bit 0=Data, bit 1=Error]

New Session (Status=0x01)

[... Frame Header]
[1B Network: 0x01=TCP, 0x02=UDP]
[2B Port (BE)]
[1B Address Type: 0x01=IPv4, 0x02=Domain, 0x03=IPv6]
[NB Address]

Data Payload (when Option has Data bit)

After the frame header/metadata:

[2B Data Length (BE)]
[NB Data]

Session End (Status=0x03)

Just the frame header, no additional fields.

XUDP Frame Format

Same structure as Mux, but:

  • Session ID is always 0x0000
  • First frame includes 8-byte GlobalID after the address
  • Keep frames include per-packet destination address

XUDP New Session

[2B Meta Length]
[00 00]            Session ID = 0
[01]               Status = New
[01]               Option = Data
[02]               Network = UDP
[2B Port (BE)]
[1B Addr Type]
[NB Address]
[8B GlobalID]      BLAKE3 hash of client source
[2B Data Length (BE)]
[NB UDP Payload]

XUDP Keep (subsequent packets)

[2B Meta Length]
[00 00]            Session ID = 0
[02]               Status = Keep
[01]               Option = Data
[02]               Network = UDP   (if per-packet dest present)
[2B Port (BE)]     (destination of this packet)
[1B Addr Type]
[NB Address]
[2B Data Length (BE)]
[NB UDP Payload]

Vision Padding Format

[16B UserUUID]     (only in first frame, omitted after)
[1B  Command]      0x00=Continue, 0x01=End, 0x02=Direct
[2B  Content Length (BE)]
[2B  Padding Length (BE)]
[NB  Content]
[NB  Padding (random bytes)]

Multiple padding blocks can be concatenated in one write.

Address Encoding

All protocols use the same address encoding:

IPv4:    Type=0x01, followed by 4 bytes
Domain:  Type=0x02, followed by 1 byte length + domain string
IPv6:    Type=0x03, followed by 16 bytes

Port is always 2 bytes big-endian, written before the address (port-then-address order).

Key Compatibility Notes

  1. UUID encoding: Raw 16 bytes, NOT the hyphenated string form.

  2. Protobuf wire format: VLESS addons use standard protobuf encoding. The length prefix is a single byte (not varint), limiting addons to 255 bytes.

  3. XUDP session ID 0: This is how the server distinguishes XUDP from regular mux. Regular mux session IDs start from 1.

  4. XUDP magic port 666: When the VLESS outbound converts UDP to XUDP, it uses address v1.mux.cool with port 666. This is a convention, not a wire format detail (the address is sent as part of the VLESS header).

  5. Vision UserUUID once: The 16-byte UUID appears only in the first padding frame. If the first frame doesn't start with the expected UUID, the server falls back to non-Vision mode.

  6. Trojan password is hex: SHA224(password) is encoded as 56 lowercase hex characters (ASCII), not binary.

  7. VMess time window: The timestamp in the auth ID is time.Now().Unix() / 30. The server accepts ±120 seconds (8 time periods).

  8. Endianness: All multi-byte integers are big-endian unless otherwise noted.

  9. VLESS fallback detection: If the first 17 bytes (version + UUID) don't match any user, and fallback is enabled, the entire buffered data is forwarded to the fallback destination.

  10. Cone mode flag: The cone context value determines whether UDP uses XUDP (cone=true) or individual mux sessions (cone=false). This affects the wire format used.

Technical analysis for re-implementation purposes.