# VMess protocol

VMess is the original encrypted communication protocol of V2Ray.

# version

The current version number is 1.

# rely

# Underlying protocol

VMess is a TCP-based protocol, and all data is transmitted using TCP.

# User ID

ID is equivalent to UUID (opens new window), which is a 16-byte random number, and its function is equivalent to a token. An ID has the form: de305d54-75b4-431b-adb2-eb6b9e546014, almost completely random, and can be generated by any UUID generator, such as this (opens new window).

The user ID can be specified in [Configuration File] (../config/overview.md).

# function

# Communication process

VMess is a stateless protocol, that is, the client and the server can directly transmit data without a handshake, and each data transmission has no effect on other data transmissions before and after. The VMess client initiates a request, and the server determines whether the request comes from a legitimate client. If the verification is passed, the request is forwarded, and the obtained response is sent back to the client. VMess uses an asymmetric format, that is, the request sent by the client and the response from the server use different formats.

# Client request

16 bytes X bytes The rest
Certification Information Instruction part Data part

# Certification Information

The authentication information is a 16-byte hash value, which is calculated as follows:

  • H = MD5
  • K = User ID (16 bytes)
  • M = UTC time, accurate to the second, the value is a random value of 30 seconds before and after the current time (8 bytes, Big Endian)
  • Hash = HMAC(H, K, M)

# Instruction part

The instruction part is encrypted by AES-128-CFB:

  • Key: MD5(User ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
  • IV: MD5(X + X + X + X), X = []byte (the time when the authentication information is generated) (8 bytes, Big Endian)
1 byte 16 bytes 16 bytes 1 byte 1 byte 4 bit 4 bit 1 byte 1 byte 2 bytes 1 byte N bytes P byte 4 bytes
Version number Ver Data encryption IV Data encryption Key Response authentication V Option Opt Margin P Encryption method Sec Keep Command Cmd Port Port Address type T Address A Random value Check F

Option Opt details: (when a bit is 1, it means that the option is enabled)

0 1 2 3 4 5 6 7
X X X X X M R S

among them:

  • Version number Ver: always 1;
  • Data encryption IV: random value;
  • Data encryption Key: random value;
  • Response authentication V: random value;
  • Option Opt:
    • S (0x01): standard format data stream (recommended to open);
    • R (0x02): The client expects to reuse TCP connections (V2Ray 2.23+ deprecated);
      • This item is valid only when S is turned on;
    • M (0x04): Turn on metadata obfuscation (recommended);
      • This item is valid only when S is turned on;
      • When the item is turned on, the client and the server need to construct two Shake instances respectively, namely RequestMask = Shake (request data IV) and ResponseMask = Shake (response data IV).
    • X: reserved
  • Margin P: add the random value of P bytes before the check value;
  • Encryption method: Specify the encryption method of the data part, the optional values are:
    • 0x00: AES-128-CFB;
    • 0x01: No encryption;
    • 0x02: AES-128-GCM;
    • 0x03: ChaCha20-Poly1305;
  • Command Cmd:
    • 0x01: TCP data;
    • 0x02: UDP data;
  • Port Port: integer port number in Big Endian format;
  • Address type T:
    • 0x01: IPv4
    • 0x02: domain name
    • 0x03: IPv6
  • Address A:
    • When T = 0x01, A is a 4-byte IPv4 address;
    • When T = 0x02, A is 1 byte length (L) + L byte domain name;
    • When T = 0x03, A is a 16-byte IPv6 address;
  • Check F: FNV1a hash of all the contents except F in the instruction part;

# Data part

The data part has two formats, the default is the basic format.

# Basic format (deprecated)

**This format is only for backward compatibility and may be deleted in future versions. **

All data is considered the actual content of the request. These contents will be sent to the address specified in the instruction section. When Cmd = 0x01, these data will be sent in the form of TCP; when Cmd = 0x02, these data will be sent in the form of UDP.

This format supports two encryption methods: "No encryption" and "AES-128-CFB". The encrypted Key and IV are specified by the command part.

# standard format

When Opt(S) is turned on, the data part uses this format. The actual request data is divided into several small blocks, and the format of each small block is as follows. After the server has verified all the small blocks, it is forwarded in the basic format.

2 bytes L byte
Length L data pack

among them:

  • Length L: An integer in Big Endian format, the maximum value is 2^14;
    • When Opt(M) is turned on, the value of L = the true value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
  • Data packet: the data packet encrypted by the specified encryption method;

Before the transmission ends, there must be actual data in the data packet, that is, data other than the length and authentication data. When the transmission is over, the client must send an empty data packet, that is, L = 0 (no encryption) or authentication data length (with encryption) to indicate the end of the transmission.

According to different encryption methods, the format of the data packet is as follows:

  • No encryption:
    • L byte: actual data;
  • AES-128-CFB: The entire data part is encrypted using AES-128-CFB
    • 4 bytes: FNV1a hash of actual data;
    • L-4 bytes: actual data;
  • AES-128-GCM: Key is the Key of the command part, IV = count (2 bytes) + IV (10 bytes). The count starts from 0 and increments by 1 for each data packet; IV is the 3rd to 12th bytes of the instruction part IV.
    • L-16 bytes: actual data;
    • 16 bytes: GCM certification information
  • ChaCha20-Poly1305: Key = MD5 (instruction part Key) + MD5 (MD5 (instruction part Key)), IV = count (2 bytes) + IV (10 bytes). The count starts from 0 and increments by 1 for each data packet; IV is the 3rd to 12th bytes of the instruction part IV.
    • L-16 bytes: actual data;
    • 16 bytes: Poly1305 authentication information

# Server response

The response header data is encrypted using AES-128-CFB, the IV is MD5 (Data Encryption IV), and the Key is MD5 (Data Encryption Key). The actual response data varies depending on the encryption settings.

1 byte 1 byte 1 byte 1 byte M bytes The rest
Response authentication V Option Opt Command Cmd Command length M Instruction content Actual response data

among them:

  • Response authentication V: must be consistent with the response authentication V in the client request;
  • Option Opt:
    • 0x01: The server is ready to reuse TCP connection (V2Ray 2.23+ is deprecated);
  • Command Cmd:
    • 0x01: dynamic port instruction
  • Actual response data:
    • If Opt(S) in the request is enabled, the standard format is used, otherwise the basic format is used.
    • The format is the same as the request data.
      • When Opt(M) is turned on, the value of length L = the true value xor Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

# Dynamic port instructions

1 byte 2 bytes 16 bytes 2 bytes 1 byte 1 byte
Keep Port Port User ID AlterID user level Effective time T

among them:

  • Port Port: integer port number in Big Endian format;
  • Effective time T: minutes;

When the client receives the dynamic port instruction, the server has opened a new port for communication, and the client can send data to the new port. After T minutes, this port will become invalid and the client must re-use the main port for communication.

# Comment

  • To ensure forward compatibility, the value of all reserved fields must be 0.