V2Fly.orgV2Fly.org
Quick Start
Config Reference
Config Reference (v5, WIP)
Tools
Developer Guide
New concise guide
  • 简体中文
  • English
GitHub
Quick Start
Config Reference
Config Reference (v5, WIP)
Tools
Developer Guide
New concise guide
  • 简体中文
  • English
GitHub
  • Developer Guide

    • The first step: learn to compile
    • Step 2: Understand the architecture
    • Step 3: Start development
    • Release Archive
    • Release Signing
  • Protocol Details

    • VMess Protocol
      • Version
      • Dependencies
        • Underlying Protocol
        • User ID
        • Functions
      • Communication Process
      • Client Request
        • AEAD Authentication Format
        • MD5 Authentication Format (Deprecated)
        • Instruction Section (Common)
        • Data Section (Common)
      • Server Response
        • AEAD Authentication Response
        • MD5 Authentication Response (Deprecated)
        • Response Header Format
        • Dynamic Port Instruction
      • Notes
    • mKCP Protocol
    • Mux.Cool Protocol

VMess Protocol

VMess is the original encrypted communication protocol of V2Ray.

VMess protocol header has two authentication methods:

  • AEAD Authentication: Uses AEAD encryption to ensure the integrity of the protocol header;
  • MD5 Authentication: Traditional authentication method, uses MD5 + AES-128-CFB to encrypt the protocol header, cannot guarantee the integrity of the header itself.

Warning

MD5 authentication is deprecated. Please use AEAD authentication.

Currently, VMess can automatically negotiate between AEAD and MD5 authentication based on the protocol header.

Version

The current version number is 1.

Dependencies

Underlying Protocol

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

User ID

ID is equivalent to UUID, which is a 16-byte random number that functions as 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 one.

The user ID can be specified in the configuration file.

Functions

  • MD5: MD5 function

    • Input: byte array of any length
    • Output: 16-byte array
  • HMAC: HMAC function

    • Input parameters:
      • H: Hash function
      • K: Key, byte array of any length
      • M: Message, byte array of any length
  • Shake: SHA3-Shake128 function

    • Input: byte array of any length
    • Output: byte array of any length
  • KDF: Key Derivation Function, takes a master key in byte array form and several path components in byte array form, generates a subkey (used for AEAD authentication)

    KDF(key, path...):
        hmac_creator = HMAC(SHA256, "VMess AEAD KDF")
        for each p in path:
            hmac_creator = HMAC(hmac_creator, p)
        return hmac_creator(key)
    
  • CmdKey: A 16-byte key derived from user UUID (used for AEAD authentication)

    CmdKey = MD5(UUID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
    

Communication Process

VMess is a stateless protocol, meaning the client and server can transmit data directly without handshaking, and each data transmission has no effect on other transmissions before or after.

The VMess client initiates a request, and the server determines whether the request comes from a legitimate client. If verification passes, the request is forwarded, and the obtained response is sent back to the client.

VMess uses an asymmetric format, meaning the request sent by the client and the response from the server use different formats.

Client Request

A client request consists of three parts: Authentication Information, Instruction Section, and Data Section. The format of authentication information and instruction section varies depending on the authentication method.

AEAD Authentication Format

16 bytes18 bytes8 bytesY bytesRemaining
EAuIDALengthNonceAHeaderData Section

Where:

  • EAuID: Encrypted Authentication ID, used to identify user identity;
  • ALength: Encrypted instruction section length (2 bytes plaintext + 16 bytes GCM Tag);
  • Nonce: Random number for AEAD encryption;
  • AHeader: Encrypted instruction section;
  • Data Section: Actual transmitted data.

To maintain compatibility with the original protocol and configuration, the client's UUID information must be calculated from and only from the first 16 bytes.

EAuID (Encrypted Authentication ID)

EAuID plaintext format:

8 bytes4 bytes4 bytes
TimestampRandCRC

Where:

  • Timestamp: 64-bit Unix timestamp in seconds (Big-Endian);
  • Rand: Random number;
  • CRC: CRC32([Timestamp, Rand]), using IEEE polynomial;

EAuID encryption:

  • Encryption key: KDF(CmdKey, "AES Auth ID Encryption")[:16]
  • Encryption method: AES-128 block cipher

ALength (Encrypted Length)

ALength is the 16-bit big-endian VMess packet header length encrypted with AES-128-GCM.

  • Encryption key: KDF(CmdKey, "VMess Header AEAD Key_Length", EAuID, Nonce)[:16]
  • Nonce: KDF(CmdKey, "VMess Header AEAD Nonce_Length", EAuID, Nonce)[:12]
  • Additional Data (AD): EAuID

AHeader (Encrypted Header)

AHeader is the VMess standard header encrypted with AES-128-GCM (i.e., the instruction section content below).

  • Encryption key: KDF(CmdKey, "VMess Header AEAD Key", EAuID, Nonce)[:16]
  • Nonce: KDF(CmdKey, "VMess Header AEAD Nonce", EAuID, Nonce)[:12]
  • Additional Data (AD): EAuID

AES-GCM requires that Key-Nonce combinations do not repeat. Since EAuID and Nonce are used as KDF inputs for Key and Nonce, there are 96 bits of random entropy to ensure no repetition. Since the user UUID is used as input, it cannot be decrypted by attackers.

MD5 Authentication Format (Deprecated)

16 bytesX bytesRemaining
Authentication InfoInstruction SectionData Section

Where:

  • Authentication Info: HMAC-MD5 hash value, used to verify client identity;
  • Instruction Section: AES-128-CFB encrypted instructions;
  • Data Section: Actual transmitted data.

Authentication Information

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

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

Instruction Section Encryption

The instruction section is encrypted with AES-128-CFB:

  • Key: MD5(User ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
  • IV: MD5(X + X + X + X), where X = []byte(time when authentication info was generated) (8 bytes, Big-Endian)

Instruction Section (Common)

The structure of the instruction section is the same for both AEAD and MD5 authentication methods, differing only in the encryption method:

  • AEAD Authentication: Used as plaintext for AHeader, encrypted with AES-128-GCM;
  • MD5 Authentication: Encrypted with AES-128-CFB.
1 byte16 bytes16 bytes1 byte1 byte4 bits4 bits1 byte1 byte2 bytes1 byteN bytesP bytes4 bytes
Version VerRequest Encryption IVRequest Encryption KeyResponse Auth VOption OptMargin PEncryption SecReservedCommand CmdPortAddress Type TAddress ARandomChecksum F

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

01234567
XXXAPMRS

Where:

  • Version Ver: Always 1;
  • Request Encryption IV: Random value;
  • Request Encryption Key: Random value;
  • Response Auth V: Random value;
  • Option Opt:
    • S (0x01): Standard format data stream (enabled by default);
    • R (0x02): Client expects to reuse TCP connection (deprecated since V2Ray 2.23+);
      • Only valid when S is enabled;
    • M (0x04): Enable metadata obfuscation (recommended);
      • Only valid when S is enabled;
      • When enabled, client and server need to construct two Shake instances: RequestMask = Shake(Request Encryption IV), ResponseMask = Shake(Response Encryption IV);
    • P (0x08): Global padding;
      • Only valid when M is enabled;
      • Data section encryption must be AES-128-GCM or ChaCha20-Poly1305;
      • When enabled, client and server generate random-length padding bytes based on the Shake instance and append them after the ciphertext;
    • A (0x10): Enable authenticated packet length experiment;
    • X: Reserved;
  • Margin P: Add P random bytes before the checksum;
  • Encryption method: Specifies the encryption method for the data section:
    • 0x01: Legacy (AES-128-CFB);
    • 0x03: AES-128-GCM;
    • 0x04: ChaCha20-Poly1305;
    • 0x05: None;
    • 0x06: Zero (no encryption, no chunking, raw stream);
  • Command Cmd:
    • 0x01: TCP data;
    • 0x02: UDP data;
  • 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;
  • Checksum F: FNV1a hash of all content in the instruction section except F (Big-Endian);

Data Section (Common)

The data section is used to transmit actual request/response data. There are two formats:

  • Basic Format: Direct data transmission, deprecated;
  • Standard Format: Chunked data transmission with better encryption and integrity verification (default).

Basic Format (Deprecated)

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

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

This format supports None and AES-128-CFB encryption methods. The Key and IV are specified in the instruction section.

Zero Encryption Method

When the encryption method is Zero (0x06), the basic format is forced (instead of standard format), and no encryption is performed. Specific behavior:

  • Encryption method is treated as None;
  • Opt(S) (standard format) is forcibly disabled;
  • Opt(M) (metadata obfuscation) is forcibly disabled;

This means the data section will be transmitted as completely unencrypted raw stream. Note that the protocol header is still encrypted/authenticated using AEAD or MD5.

Standard Format

When Opt(S) is enabled, the data section uses this format. The actual request data is divided into several small chunks, each with the following format. After the server verifies all chunks, it forwards them in basic format.

2 bytesL-P bytesP bytes
Length LData PacketRandom

Where:

  • Length L:
    • Integer in Big-Endian format, maximum value is 2^14;
    • When Opt(M) is disabled, actual value of L = data value;
    • When Opt(M) is enabled, actual value of L = data value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
  • Padding Length P:
    • When Opt(P) is disabled, P = 0, no padding bytes;
    • When Opt(P) is enabled, P = ((RequestMask.NextByte() << 8) + RequestMask.NextByte()) % 64;
  • Data Packet: Data packet encrypted with the specified encryption method;

Before transmission ends, the data packet must contain actual data, i.e., data other than length and authentication data. When transmission ends, the client must send an empty data packet, i.e., L = 0 (no encryption) or authentication data length (with encryption), to indicate the end of transmission.

Let data packet length R = L - P. According to different encryption methods, the data packet format is as follows:

  • No encryption:
    • R bytes: Actual data;
  • AES-128-CFB: Entire data section is encrypted using AES-128-CFB
    • 4 bytes: FNV1a hash of actual data (Big-Endian);
    • R - 4 bytes: Actual data;
  • AES-128-GCM: Key is the Key from instruction section, IV = count (2 bytes) + IV (10 bytes). Count starts from 0 and increments by 1 for each packet; IV is bytes 3 to 12 of the instruction section IV.
    • R - 16 bytes: Actual data;
    • 16 bytes: GCM authentication info;
  • ChaCha20-Poly1305: Key = MD5(Instruction Section Key) + MD5(MD5(Instruction Section Key)), IV = count (2 bytes) + IV (10 bytes). Count starts from 0 and increments by 1 for each packet; IV is bytes 3 to 12 of the instruction section IV.
    • R - 16 bytes: Actual data;
    • 16 bytes: Poly1305 authentication info;

Server Response

The server response format corresponds to the client request. The server uses the corresponding response format based on the client request's authentication method (AEAD or MD5).

AEAD Authentication Response

In AEAD authentication mode, the response encryption Key and IV are derived as follows:

  • Response Encryption Key: SHA256(Request Encryption Key)[:16]
  • Response Encryption IV: SHA256(Request Encryption IV)[:16]

The response header data is encrypted using AES-128-GCM, divided into length and content parts.

Response length encryption (2 bytes length + 16 bytes GCM Tag):

  • Encryption key: KDF(Response Encryption Key, "AEAD Resp Header Len Key")[:16]
  • Nonce: KDF(Response Encryption IV, "AEAD Resp Header Len IV")[:12]
  • Additional Data (AD): None (nil)

Response content encryption:

  • Encryption key: KDF(Response Encryption Key, "AEAD Resp Header Key")[:16]
  • Nonce: KDF(Response Encryption IV, "AEAD Resp Header IV")[:12]
  • Additional Data (AD): None (nil)

MD5 Authentication Response (Deprecated)

In MD5 authentication mode, the response encryption Key and IV are derived as follows:

  • Response Encryption Key: MD5(Request Encryption Key)
  • Response Encryption IV: MD5(Request Encryption IV)

The response header data is encrypted using AES-128-CFB.

Response Header Format

The actual response data varies depending on encryption settings.

1 byte1 byte1 byte1 byteM bytesRemaining
Response Auth VOption OptCommand CmdCommand Length MCommand ContentActual Response Data

Where:

  • Response Auth V: Must match the Response Auth V in the client request;
  • Option Opt:
    • 0x01: Server is ready to reuse TCP connection (deprecated since V2Ray 2.23+);
  • Command Cmd:
    • 0x01: Dynamic port instruction;
  • Actual Response Data:
    • If Opt(S) is enabled in the request, standard format is used; otherwise, basic format is used;
    • If Opt(M) is enabled in the request, metadata obfuscation is enabled, with Shake instance ResponseMask;
    • If Opt(P) is enabled in the request, global padding is enabled, with Shake instance ResponseMask;
    • Format is the same as request data;

Dynamic Port Instruction

1 byte2 bytes16 bytes2 bytes1 byte1 byte
ReservedPortUser IDAlterIDUser LevelValid Time T

Where:

  • Port: Integer port number in Big-Endian format;
  • Valid Time T: Minutes;

When the client receives a 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 use the main port again for communication.

Notes

  • To ensure forward compatibility, the value of all reserved fields must be 0. ENDOFFILE
Edit this page on GitHub
Last Updated:
Contributors: transifex-integration[bot], Kaede Akino
Next
mKCP Protocol