EN: Retranslate all documents via Gemini Pro 3, Human proofreading

This commit is contained in:
Meow
2026-01-24 06:07:31 +08:00
parent a07654a1d1
commit b7ee2196c6
91 changed files with 6053 additions and 5509 deletions
+14 -14
View File
@@ -1,28 +1,28 @@
# Development Guide
## Compile Documentation
## Compilation Documentation
Xray supports multiple platforms, and you can perform cross-compilation on various platforms by yourself.
Xray supports a wide range of platforms, allowing you to perform cross-compilation on various systems yourself.
Please click [Compile Documentation](./intro/compile.md) to view specific compile-related content.
Please click [Compilation Documentation](./intro/compile.md) to view specific compilation-related content.
## Design Concept
## Design Philosophy
Xray kernel provides a platform for secondary development.
The Xray kernel provides a platform upon which secondary development can be conducted.
This section explains the design goals and architecture of Xray.
This chapter expounds on Xray's design goals and architecture.
Please click [Design Principles](./intro/design.md) to learn about the design goals and architecture of Xray.
Please click [Design Philosophy](./intro/design.md) to understand Xray's design goals and architecture.
## Development Standards
## Development Guidelines
This section outlines the guidelines to follow when obtaining code, developing, submitting PRs, as well as the relevant coding standards.
This chapter explains the guidelines to follow during the process of obtaining code, conducting development, and submitting PRs, as well as relevant coding conventions.
Please click [Development Specification](./intro/guide.md) to view the guidelines that should be followed during Xray development.
Please click [Development Guidelines](./intro/guide.md) to view the criteria to be followed in Xray development.
## Protocol Details
Xray uses many protocols, and you can obtain a detailed description of each protocol through various means.
Xray utilizes many types of protocols. You can obtain detailed descriptions of these protocols through various channels.
### [VLESS Protocol](./protocols/vless.md)
@@ -30,12 +30,12 @@ VLESS is a stateless lightweight transport protocol that can serve as a bridge b
### [VMess Protocol](./protocols/vmess.md)
VMess is an encrypted transport protocol that can act as a bridge between Xray clients and servers.
VMess is an encrypted transport protocol that can serve as a bridge between Xray clients and servers.
### [Mux.Cool Protocol](./protocols/muxcool.md)
Mux.Cool protocol is a multiplexing transport protocol used to transmit multiple independent data streams within an established data stream.
The Mux.Cool protocol is a multiplexing transport protocol used to transmit multiple independent data streams within a single established data stream.
### [mKCP Protocol](./protocols/mkcp.md)
mKCP is a stream transmission protocol modified from the [KCP protocol](https://github.com/skywind3000/kcp) that can transmit arbitrary data streams in order.
mKCP is a stream transport protocol, modified from the [KCP Protocol](https://github.com/skywind3000/kcp), capable of transmitting arbitrary data streams in order.
+43 -27
View File
@@ -1,80 +1,96 @@
# Compile the document
# Compilation Documentation
## Preparatory Work
## Prerequisites
Xray uses [Golang](https://golang.org/) as its programming language, so you need to install the latest version of Golang first in order to compile.
Xray uses [Golang](https://golang.org/) as its programming language. You need to install the latest version of Golang to compile it.
::: tip TIP
Install Golang: [golang.org/doc/install](https://golang.org/doc/install)
:::
If you happen to use Windows, please **make sure** to use Powershell.
> If you are unfortunately using Windows, please **be sure** to use PowerShell.
## Pull Xray source code
## Pull Xray Source Code
```bash
git clone https://github.com/XTLS/Xray-core.git
git clone [https://github.com/XTLS/Xray-core.git](https://github.com/XTLS/Xray-core.git)
cd Xray-core && go mod download
```
If you have free time, you can try GitHub's official tool: `gh repo clone XTLS/Xray-core`
> If you have nothing better to do, you can try the GitHub official tool: `gh repo clone XTLS/Xray-core`
Note: In a network environment where Google cannot be accessed normally, dependencies cannot be pulled normally, and `GOPROXY` needs to be set first:
Note: In network environments where Google cannot be accessed normally, dependencies cannot be pulled correctly. You need to set `GOPROXY` first:
```bash
go env -w GOPROXY=https://goproxy.io,direct
go env -w GOPROXY=[https://goproxy.io](https://goproxy.io),direct
```
## Build Binary
:::warning
This command needs to be executed within Xray root directory.
The commands in this section need to be run inside the Xray root directory.
:::
### Windows(Powershell):
### Windows (Powershell)
```powershell
$env:CGO_ENABLED=0
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
go build -o xray.exe -trimpath -buildvcs=false -ldflags "-s -w -buildid=" ./main
```
### macOS, Linux:
### macOS, Linux
```bash
CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags "-s -w -buildid=" ./main
```
Running the above command will generate an xray executable file in the directory.
Running the above commands will generate the `xray` executable file in the directory.
::: tip
If you need to compile a program that can be debugged, i.e., you can use dlv to attach to the running program for debugging, please remove the '-w -s' options from the ldflags.
If you need to compile a debuggable program (i.e., you can attach `dlv` to the running program for debugging), please remove the `-w -s` options from `ldflags`.
- w option disables the generation of debug information. After using this option, gdb cannot be used for debugging.
- s option disables the symbol table.
PS: Actually, debugging with vscode or other IDEs seems to be more convenient.
- `-w`: Disable DWARF generation (debug info). After using this option, you cannot use gdb for debugging.
- `-s`: Disable the symbol table.
## Cross compilation:
PS: Actually, debugging with VSCode or other IDEs seems more convenient.
:::
Here, we take the example of compiling to a Linux server in a Windows (Powershell) environment:
## Cross Compilation
Here is an example of compiling for a Linux server in a Windows (Powershell) environment:
```powershell
$env:CGO_ENABLED=0
$env:GOOS="linux"
$env:GOARCH="amd64"
```
go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main```
go build -o xray -trimpath -buildvcs=false -ldflags "-s -w -buildid=" ./main
```
After uploading to the server, remember to execute `chmod +x xray` in the server terminal.
::: tip
Execute `go tool dist list` to view all supported systems and architectures.
Run `go tool dist list` to view all supported systems and architectures.
:::
## Reproducible Build:
## Reproducible Build
Following the above steps, it is possible to compile and release an identical binary file as the one in Release.
Use the following command to build (`<short commit ID>` should be replaced with the first seven characters of the corresponding commit SHA-256):
```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X [github.com/xtls/xray-core/core.build=](https://github.com/xtls/xray-core/core.build=)<short commit ID> -s -w -buildid=" -v ./main
```
For MIPS/MIPSLE architectures, you should use:
```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X [github.com/xtls/xray-core/core.build=](https://github.com/xtls/xray-core/core.build=)<short commit ID> -s -w -buildid=" -v ./main
```
::: warning
Please confirm that you are using the same Golang version as the one used to compile the release.
Please ensure that the Golang version you are using is consistent with the one used to compile the Release.
:::
## Compiling for Windows 7
Replace the Golang tools with the version provided in [go-win7](https://github.com/XTLS/go-win7), and then proceed with the compilation steps above.
+17 -17
View File
@@ -1,43 +1,43 @@
# Design Objectives
# Design Goals
- Xray Kernel provides a platform that supports essential network proxy functions and can be developed upon to provide a better user experience.
- Cross-platform is the primary principle to reduce the cost of secondary development.
- The Xray core provides a platform that supports necessary network proxy functions, upon which secondary development can be conducted to provide a better user experience.
- Cross-platform support is the primary principle to reduce the cost of secondary development.
## Architecture
![Architecture](./framework.png)
The kernel is divided into three layers: the application layer, the proxy layer, and the transport layer.
The core is divided into three layers: Application Layer, Proxy Layer, and Transport Layer.
Each layer contains several modules, which are independent of each other. Modules of the same type can be seamlessly replaced.
Each layer contains several modules. Modules are independent of each other, and modules of the same type can be seamlessly replaced.
### Application Layer
The application layer contains some commonly used functions in proxy layers, which are abstracted for reuse in different proxy modules.
The Application Layer contains common functions used in the Proxy Layer. These functions are abstracted to be reused across different proxy modules.
The modules at the application layer should be implemented purely in software and should not be dependent on hardware or platform-related technologies.
Modules in the Application Layer should be pure software implementations, independent of hardware or platform-specific technologies.
List of Important Modules:
Important module list:
- Dispatcher: Used to transfer data received by the inbound agent to the outbound agent;
- Router: Routing module, see [Routing Configuration](../../config/routing.md) for details;
- DNS: Built-in DNS server module;
- Proxy Manager: Proxy manager;
- **Dispatcher**: Used to transmit data received by the inbound proxy to the outbound proxy.
- **Router**: Routing module, see [Routing Configuration](../../config/routing.md) for details.
- **DNS**: Built-in DNS server module.
- **Proxy Manager**: Manages proxies.
### Proxy Layer
The proxy layer is divided into two parts: Inbound Proxy and Outbound Proxy.
The Proxy Layer is divided into two parts: Inbound Proxy and Outbound Proxy.
The two parts are independent of each other, where the inbound proxy does not rely on a specific outbound proxy, and vice versa.
The two parts are independent of each other. An inbound proxy does not depend on a specific outbound proxy, and vice versa.
#### Inbound Proxy
- Implement the [proxy.Inbound](https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go) interface;
- Implements the [proxy.Inbound](https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go) interface.
#### Outbound Proxy
- Implement the [proxy.Outbound](https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go) interface;
- Implements the [proxy.Outbound](https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go) interface.
### Transport Layer
The transport layer provides a set of tools and modules related to network data transmission.
The Transport Layer provides tool modules related to network data transmission.
+92 -72
View File
@@ -4,94 +4,94 @@
### Version Control
Project X's code is hosted on GitHub:
Project X code is hosted on GitHub:
- Xray Core [xray-core](https://github.com/XTLS/Xray-core)
- Installation script [Xray-install](https://github.com/XTLS/Xray-install)
- Configuration template [Xray-examples](https://github.com/XTLS/Xray-examples)
- Xray documentation [Xray-docs-next](https://github.com/XTLS/Xray-docs-next)
- Xray Core: [Xray-core](https://github.com/XTLS/Xray-core)
- Install Script: [Xray-install](https://github.com/XTLS/Xray-install)
- Configuration Templates: [Xray-examples](https://github.com/XTLS/Xray-examples)
- Xray Documentation: [Xray-docs-next](https://github.com/XTLS/Xray-docs-next)
You can use [Git](https://git-scm.com/) to get the code.
You can use [Git](https://git-scm.com/) to fetch the code.
### Branch
### Branches
- The main branch is the backbone of this project.
- The main branch is also the release branch of this project.
- It is necessary to ensure that main can be compiled and used normally at any time.
- If you need to develop new features, please create a new branch for development. After development and sufficient testing, merge it back to the main branch.
- Please delete branches that have been merged into the main branch and are no longer necessary.
- The trunk branch of this project is `main`.
- The release branch of this project is also `main`.
- Ensure that `main` is compilable and usable at any given time.
- If you need to develop new features, please create a new branch for development. After development is complete and fully tested, merge it back into the trunk branch.
- Branches that have already been merged into the trunk and are no longer necessary should be deleted.
### Release
<Badge text="WIP" type="warning"/> (Note: this is not translatable as it is a technical tag)
<Badge text="WIP" type="warning"/>
- Create two release channels: one for the beta version and another for the stable version.
- The beta version, also known as the daily build, is mainly used for specific testing, experimentation, and instant feedback and improvement.
- The stable version, updated regularly (e.g. monthly), merges stable modifications and releases them.
- Establish two release channels: Bleeding Edge and Stable.
- Bleeding Edge: Can be daily builds, mainly used for specific testing scenarios, trying out new features, and obtaining immediate feedback for further improvement.
- Stable: Scheduled updates (e.g., monthly), merging stable changes and releasing.
### Citing other projects
### Referencing Other Projects
- Golang
- It is recommended to use the Golang standard library and libraries under [golang.org/x/](https://pkg.go.dev/search?q=golang.org%2Fx) for product code;
- If you need to reference other projects, please create an issue for discussion beforehand;
- Other
- Tools that do not violate the agreement of both parties and are helpful to the project can be used.
- For product code, it is recommended to use the Golang standard library and libraries under [golang.org/x/](https://pkg.go.dev/search?limit=25&m=package&q=golang.org%2Fx).
- If you need to reference other projects, please create an issue for discussion beforehand.
- Others
- Tools that do not violate the agreements of either party and are helpful to the project can be used.
## Development Process
### Before Writing Code
If you encounter any issues or have any ideas for the project, please create an [issue](https://github.com/XTLS/Xray-core/issues) for discussion to reduce redundant work and save time spent on coding.
### Modify the code
- Golang
- Please refer to [Effective Go](https://golang.org/doc/effective_go.html);
- Run `go generate core/format.go` before each push;
- If you need to modify protobuf, such as adding new configuration items, please run: `go generate core/proto.go`;
- It is recommended to pass the test before submitting a pull request: `go test ./...`;
- It is recommended to have more than 70% code coverage for newly added code before submitting pull requests.
- Other
- Please pay attention to the readability of the code.
### Pull Request
- Before submitting a PR, please run `git pull https://github.com/xray/xray-core.git` to ensure that the merge can proceed smoothly;
- One PR only does one thing. If there are fixes for multiple bugs, please submit a PR for each bug;
- Due to Golang's special requirements (Package path), the PR process for Go projects is different from other projects. The recommended process is as follows:
1. Fork this project first and create your own `github.com/<your_name>/Xray-core.git` repository;
2. Clone your own Xray repository to your local machine: `git clone https://github.com/<your_name>/Xray-core.git`;
3. Create a new branch based on the `main` branch, for example `git branch issue24 main`;
4. Make changes on the new branch and commit the changes;
5. Before pushing the modified branch to your own repository, switch to the `main` branch, and run `git pull https://github.com/xray/xray-core.git` to pull the latest remote code;
6. If new remote code is obtained in the previous step, switch to the branch you created earlier and run `git rebase main` to perform branch merging. If there is a file conflict, you need to resolve the conflict;
7. After the previous step is completed, you can push the branch you created to your own repository: `git push -u origin your-branch`
8. Finally, send a PR from your new pushed branch in your own repository to the `main` branch of `xtls/Xray-core`;
9. Please fully describe the purpose of this PR, including the problem solved, the new feature added, or the modifications made in the title and body of the PR;
10. Please be patient and wait for the developer's response.
If you find any issues or have any ideas for the project, please create an [issue](https://github.com/XTLS/Xray-core/issues) for discussion to reduce repetitive work and time spent on code.
### Modifying Code
#### Functional issue
- Golang
- Please refer to [Effective Go](https://golang.org/doc/effective_go.html).
- Before every push, please run: `go generate core/format.go`.
- If you need to modify protobuf, such as adding new configuration items, please run: `go generate core/proto.go`.
- Before submitting a pull request, it is recommended to pass tests: `go test ./...`.
- Before submitting a pull request, it is recommended that new code has over 70% code coverage.
- Others
- Please pay attention to code readability.
Please submit at least one test case to verify changes to existing functionality.
### Pull Request
- Before submitting a PR, please run `git pull https://github.com/XTLS/Xray-core.git` to ensure the merge can proceed smoothly.
- One PR should do one thing. If there are fixes for multiple bugs, please submit a separate PR for each bug.
- Due to the special requirements of Golang (Package path), the PR process for Go projects differs from other projects. The recommended process is as follows:
1. Fork this project first and create your own `github.com/<your_name>/Xray-core.git` repository.
2. Clone your own Xray repository locally: `git clone https://github.com/<your_name>/Xray-core.git`.
3. Create a new branch based on the `main` branch, e.g., `git branch issue24 main`.
4. Make changes and commit them on the newly created branch.
5. Before pushing the completed branch to your own repository, switch to the `main` branch and run `git pull https://github.com/XTLS/Xray-core.git` to pull the latest remote code.
6. If new remote code was pulled in the previous step, switch back to the branch you created and run `git rebase main` to perform the branch merge operation. If you encounter file conflicts, you need to resolve them.
7. After the previous step is completed, you can push your created branch to your own repository: `git push -u origin your-branch`.
8. Finally, send a PR from the newly pushed branch in your repository to the `main` branch of `XTLS/Xray-core`.
9. In the title and body of the PR, please fully describe the problem solved / new feature added / intention of the code changes, etc.
10. Wait patiently for the developers' response.
### Changes to Code
#### Functional Issues
Please submit at least one Test Case to verify changes to existing functions.
#### Performance Related
Please provide the necessary test data to demonstrate performance issues in existing code or performance improvements in new code.
Please submit necessary test data to prove performance defects in existing code or performance improvements in new code.
#### New Feature
#### New Features
- If the new feature does not affect the existing functionality, please provide a toggle (such as a flag) that can be turned on/off, and keep the new feature disabled by default.
- For major new features (such as adding a new protocol), please submit an issue for discussion before development.
- If the new feature does not affect existing features, please provide a switch (e.g., flag) that can turn it on/off, and keep the new feature off by default.
- Before developing large new features (such as adding a new protocol), please submit an issue first and proceed with development after discussion.
#### Other
#### Others
It depends on the specific situation.
To be determined based on the specific situation.
## Xray Coding Guidelines
## Xray Coding Standards
The following content is applicable to Golang code in Xray.
The following applies to Golang code in Xray.
### Code Structure
@@ -100,7 +100,7 @@ Xray-core
├── app // Application module
│ ├── router // Router
├── common // Common code
├── proxy // Communication protocol
├── proxy // Communication protocols
│ ├── blackhole
│ ├── dokodemo-door
│ ├── freedom
@@ -111,21 +111,41 @@ Xray-core
### Coding Standards
Basic practices are consistent with the recommendations of the official Golang, with a few exceptions. Written here to help everyone familiarize themselves with Golang.
Basically consistent with the practices recommended by official Golang documentation, with some exceptions. Written here to help everyone get familiar with Golang.
#### Naming
- Use a single English word for file and directory names, such as hello.go;
- If not possible, use a hyphen for directories / underscore for files to connect two (or more) words, such as hello-world/hello_again.go;
- Use \_test.go to name test code files;
- Use PascalCase for types, such as ConnectionHandler;
- Do not force lowercase for abbreviations, i.e. HTML does not need to be written as Html;
- Use PascalCase for public member variables;
- Use camelCase for private member variables, such as `privateAttribute`;
- For easy refactoring, it is recommended to use PascalCase for all methods;
- Place completely private types in `internal`.
- Try to use single English words for file and directory names, such as `hello.go`.
- If unavoidable, use hyphens for directories / underscores for filenames to connect two (or more) words, e.g., `hello-world/hello_again.go`.
- Test code should end with `_test.go`.
- Use PascalCase for types, such as `ConnectionHandler`.
- Abbreviations are not forced to be lowercase, i.e., `HTML` does not need to be written as `Html`.
- Public member variables also use PascalCase.
- Private member variables use [lowerCamelCase](https://en.wikipedia.org/wiki/Camel_case), such as `privateAttribute`.
- To facilitate refactoring, it is recommended to use PascalCase for all methods.
- Put completely private types into `internal`.
#### Content Organization
- A file contains a main type and its related private functions;
- Testing-related files, such as Mock tools, should be placed in the testing subdirectory.
- A file contains one main type and its related private functions, etc.
- Test-related files, such as Mock utility classes, should be placed in the `testing` subdirectory.
#### Int32Range
**For end user**
A value representing an optional range, which can be written in the following ways:
- A single number or range enclosed in quotes:
- `""` (Treated as 0. Note: Not setting a field at all and setting it to empty might be two different concepts for some fields.)
- `"114"`
- `"114-514"`
- An independent int (in this case, it can only be a single number):
- `114`
**For dev**
If you need to include a range in the configuration file, please use the `Int32Range` type.
Use `.From` and `.To` to get values. When From > To (e.g., 1919-810), the values will be automatically swapped to ensure From is less than To. If you want to get the raw values, you can use `.Left` and `.Right`.
+54 -54
View File
@@ -1,6 +1,6 @@
# mKCP Protocol
mKCP is a stream transfer protocol, modified from the [KCP protocol](https://github.com/skywind3000/kcp), which can transmit any data stream in order.
mKCP is a stream transport protocol, modified from the [KCP Protocol](https://github.com/skywind3000/kcp), capable of transmitting arbitrary data streams in order.
## Version
@@ -10,83 +10,83 @@ mKCP has no version number and does not guarantee compatibility between versions
### Underlying Protocol
mKCP is a protocol based on UDP, and all communication uses UDP transmission.
mKCP is a UDP-based protocol; all communication is transmitted using UDP.
### Functions
- fnv: [FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) hash function
- Takes a string of arbitrary length as input parameter;
- Outputs a 32-bit unsigned integer.
- Input parameter is a string of arbitrary length;
- Outputs a 32-bit unsigned integer;
## Communication Process
1. mKCP splits data streams into several data packets for transmission. Each data stream has a unique identifier to distinguish it from other data streams. Each data packet in the data stream carries the same identifier.
2. mKCP does not have a handshake process. When receiving a data packet, it determines whether it is a new call or an ongoing call based on the identifier of the data stream it carries.
3. Each data packet contains several segments (Segment), which are divided into three types: data (Data), acknowledgment (ACK), and heartbeat (Ping). Each segment needs to be processed separately.
1. mKCP splits the data stream into several packets for transmission. A data stream has a unique identifier to distinguish different data streams. Every packet in a data stream carries the same identifier.
2. mKCP has no handshake process. When a packet is received, the identifier carried by it determines whether it is a new call or an ongoing one.
3. Each packet contains several segments. Segments are divided into three categories: Data, ACK (Acknowledgment), and Ping (Heartbeat). Each segment needs to be processed separately.
## Data Format
### Data Packet
### Packet
| 4 Bytes | 2 Bytes | L Bytes |
| ------- | ---------- | -------- |
| Auth A | Data Len L | Fragment |
| 4 Bytes | 2 Bytes | L Bytes |
| :--- | :--- | :--- |
| Authentication A | Data Length L | Segment Part |
as which:
Where:
- Authentication information A = fnv(fragment), big endian;
- The fragment may contain multiple sections.
- Authentication A = fnv(Segment Part), big endian;
- The Segment Part may contain multiple segments;
### Data snippet
### Data Segment
| 2 bytes | 1 byte | 1 byte | 4 bytes | 4 bytes | 4 bytes | 2 bytes | Len bytes |
| --------- | -------- | -------- | --------- | -------- | -------------- | -------- | --------- |
| Conv flag | Cmd flag | Opt flag | Timestamp | Sequence | Unacknowledged | Len flag | Data |
| 2 Bytes | 1 Byte | 1 Byte | 4 Bytes | 4 Bytes | 4 Bytes | 2 Bytes | Len Bytes |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| Identifier Conv | Command Cmd | Option Opt | Timestamp Ts | Sequence Sn | Unacknowledged Una | Length Len | Data |
as which:
Where:
- Identifier Conv: Identifier for mKCP data stream
- Command Cmd: Constant 0x01
- Option Opt: Optional values include:
- 0x00: Empty option
- 0x01: Opposite party has sent all data
- Timestamp Ts: Time when the current segment was sent from the remote end, big endian
- Sequence Number Sn: The position of the data segment in the data stream, the sequence number of the starting segment is 0, and each new segment is sequentially added by 1
- Unacknowledged Sequence Number Una: The minimum Sn that the remote host is sending and has not yet received confirmation.
- Identifier Conv: The identifier of the mKCP data stream.
- Command Cmd: Constant `0x01`.
- Option Opt: Optional values are:
- `0x00`: Empty option.
- `0x01`: The peer has sent all data.
- Timestamp Ts: The time when the current segment was sent from the remote end, big endian.
- Sequence Sn: The position of this data segment in the data stream. The sequence number of the starting segment is 0, and each subsequent new segment increases by 1 in order.
- Unacknowledged Una: The smallest Sn that the remote host is sending and has not yet received an acknowledgment for.
### Confirmation snippet
### ACK Segment
| 2 bytes | 1 byte | 1 byte | 4 bytes | 4 bytes | 4 bytes | 2 bytes | Len \* 4 bytes |
| ------- | ------ | ------ | ------- | --------------- | --------- | ------- | ------------------- |
| Conv ID | Cmd | Opt | Wnd | Next Seq Number | Timestamp | Length | Received Seq Number |
| 2 Bytes | 1 Byte | 1 Byte | 4 Bytes | 4 Bytes | 4 Bytes | 2 Bytes | Len * 4 Bytes |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| Identifier Conv | Command Cmd | Option Opt | Window Wnd | Next Receive Sn | Timestamp Ts | Length Len | Received Sns |
as which:
Where:
- Identifier Conv: Identifier of the mKCP data stream
- Command Cmd: Constant 0x00
- Option Opt: Same as above
- Window Wnd: The maximum sequence number that the remote host can receive
- Next receive sequence number Sn: The smallest sequence number of the data segment that the remote host has not received
- Timestamp Ts: The timestamp of the latest received data segment by the remote host, which can be used to calculate the delay
- Received sequence numbers: Each 4 bytes, indicating that the data of this sequence number has been confirmed received.
- Identifier Conv: The identifier of the mKCP data stream.
- Command Cmd: Constant `0x00`.
- Option Opt: Same as above.
- Window Wnd: The maximum sequence number the remote host can receive.
- Next Receive Sn: The smallest sequence number among the data segments not yet received by the remote host.
- Timestamp Ts: The timestamp of the latest data segment received by the remote host, used for calculating latency.
- Received Sns: Each is 4 bytes, indicating that data with this sequence number has been confirmed as received.
as which:
Note:
- The remote host expects to receive data within the serial number [Sn, Wnd) range.
- The remote host expects to receive data within the sequence number range [Sn, Wnd).
### Heartbeat Fragments
### Ping (Heartbeat) Segment
| 2 Bytes | 1 Byte | 1 Byte | 4 Bytes | 4 Bytes | 4 Bytes |
| ------- | ------ | ------ | --------------------- | ------------------- | ------- |
| Conv ID | Cmd | Opt | Unacknowledged Seq No | Next Receive Seq No | Rto |
| 2 Bytes | 1 Byte | 1 Byte | 4 Bytes | 4 Bytes | 4 Bytes |
| :--- | :--- | :--- | :--- | :--- | :--- |
| Identifier Conv | Command Cmd | Option Opt | Unacknowledged Una | Next Receive Sn | Latency Rto |
as which:
Where:
- Identifier Conv: Identifier for the mKCP data stream
- Command Cmd: Optional values include:
- 0x02: Remote host forcibly terminates the session
- 0x03: Normal heartbeat
- Option Opt: Same as above
- Unacknowledged sequence number Una: Same as the Una of the data fragment
- Next receive sequence number Sn: Same as the Sn of the acknowledgement fragment
- Delay Rto: Delay calculated by the remote host itself
- Identifier Conv: The identifier of the mKCP data stream.
- Command Cmd: Optional values are:
- `0x02`: Remote host forcibly terminates the session.
- `0x03`: Normal heartbeat.
- Option Opt: Same as above.
- Unacknowledged Una: Same as Una in the Data Segment.
- Next Receive Sn: Same as Sn in the ACK Segment.
- Latency Rto: The latency calculated by the remote host itself.
+79 -67
View File
@@ -1,6 +1,6 @@
# Mux.Cool Protocol
Mux.Cool protocol is a multiplexing transport protocol that is used to transmit multiple independent data streams within an established data stream.
The Mux.Cool protocol is a multiplexing transport protocol used to transmit multiple independent data streams within a single established data stream.
## Version
@@ -10,108 +10,120 @@ The current version is 1 Beta.
### Underlying Protocol
Mux.Cool must run on top of a reliable established data stream.
Mux.Cool must run on top of an established reliable data stream.
## Communication Process
Within a Mux.Cool connection, multiple sub-connections can be transmitted, each with a unique ID and status. The transmission process consists of frames, with each frame used to transmit data for a specific sub-connection.
A Mux.Cool connection can transmit multiple sub-connections. Each sub-connection has a unique ID and status. The transmission process consists of Frames, and each frame is used to transmit data for a specific sub-connection.
### Client behavior
### Client Behavior
When there is a need for a connection and there are no existing available connections, the client initiates a new connection to the server, referred to as the "main connection".
When there is a need for a connection and no existing connection is available, the client initiates a new connection to the server, hereafter referred to as the "main connection".
1. One main connection can be used to send several sub-connections. The client can decide independently how many sub-connections the main connection can handle.
2. For a new sub-connection, the client must send the `New` status to notify the server to establish the sub-connection, and then use the `Keep` status to transmit data.
3. When the sub-connection ends, the client sends the `End` status to notify the server to close the sub-connection.
4. The client can decide when to close the main connection, but must ensure that the server also maintains the connection.
5. The client can use the KeepAlive status to prevent the server from closing the main connection.
1. A main connection can be used to send multiple sub-connections. The client can decide the number of sub-connections the main connection can carry.
2. For a new sub-connection, the client must send the status `New` to notify the server to establish the sub-connection, and then use the status `Keep` to transmit data.
3. When a sub-connection ends, the client sends the `End` status to notify the server to close the sub-connection.
4. The client can decide when to close the main connection but must ensure the server also maintains the connection.
5. The client can use the `KeepAlive` status to prevent the server from closing the main connection.
### Server-side behavior
### Server Behavior
When a new sub-connection is received on the server side, the server should handle it as a normal connection.
When the server receives a new sub-connection, it should handle it as a normal connection.
1. When the status "End" is received, the server can close the upstream connection to the target address.
2. The same ID used in the request must be used to transfer sub-connection data in the server response.
3. The server cannot use the "New" status.
4. The server can use the KeepAlive status to avoid the client closing the main connection.
1. When receiving the `End` status, the server can close the uplink connection to the target address.
2. In the server's response, the same ID as the request must be used to transmit the sub-connection's data.
3. The server cannot use the `New` status.
4. The server can use the `KeepAlive` status to prevent the client from closing the main connection.
## Data Format
## Transmission Format
Mux.Cool uses symmetric transmission format, where the client and server send and receive data in the same format.
Mux.Cool uses a symmetric transmission format, meaning the client and server send and receive data in the same format.
### Frame Format
| 2 Bytes | L Bytes | X Bytes |
| ----------------- | -------- | --------------- |
| Metadata Length L | Metadata | Additional Data |
| 2 bytes | L bytes | X bytes |
| :--- | :--- | :--- |
| Metadata Length L | Metadata | Extra Data |
### Metadata
There are several types of metadata. All types of metadata contain two items, ID and Opt, with the following meanings:
There are several types of metadata. All types of metadata include ID and Opt items, with meanings as follows:
- ID: Unique identifier of the sub-connection
- For general MUX sub-connections, the ID is accumulated starting from 1
- For XUDP, the ID is always 0
- Opt:
- D(0x01): Additional data is available
* ID: Unique identifier for the sub-connection
* For general Mux sub-connections, the ID accumulates starting from 1.
* For [Single XUDP](https://github.com/XTLS/Xray-core/blob/main/common/xudp/xudp.go) implemented by Xray, the ID is always 0.
* Opt:
* D(0x01): Has extra data
When option Opt(D) is enabled, the additional data format is as follows:
When option Opt(D) is enabled, the extra data format is as follows:
| 2 Bytes | X-2 Bytes |
| ---------- | --------- |
| Length X-2 | Data |
| 2 bytes | X-2 bytes |
| :--- | :--- |
| Length X-2 | Data |
### New Sublink (New)
### New Sub-connection (New)
| 2 Bytes | 1 Byte | 1 Byte | 1 Byte | 2 Bytes | 1 Byte | A Bytes |
| ------- | ------ | ------ | --------- | ------- | ------ | ------- |
| ID | 0x01 | Option | Network N | Port | Type T | Address |
| 2 bytes | 1 byte | 1 byte | 1 byte | 2 bytes | 1 byte | A bytes | 8 bytes |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| ID | 0x01 | Option Opt | Network Type N | Port | Address Type T | Address A | Global ID (XUDP) |
where:
Where:
- Network type N:
- 0x01: TCP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of TCP.
- 0x02: UDP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of UDP.
- 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 a 1-byte length (L) + L-byte domain name;
- When T = 0x03, A is a 16-byte IPv6 address;
* Network Type N:
* 0x01: TCP, indicating that the traffic of the current sub-connection should be sent to the target via TCP.
* 0x02: UDP, indicating that the traffic of the current sub-connection should be sent to the target via UDP.
* 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 a 1-byte length (L) + L bytes of domain name;
* When T = 0x03, A is a 16-byte IPv6 address;
* Global ID (XUDP):
* The client calculates a global unique ID for the UDP source 2-tuple. The server uses this to ensure that when XUDP reconnects after disconnection, it still uses the same port to communicate with the target.
If Opt(D) is enabled when creating a sub-connection, the data carried by this frame needs to be sent to the target host.
When creating a new sub-connection, if Opt(D) is enabled, the data carried in this frame needs to be sent to the target host.
### Keep sub-connections
### Keep Sub-connection (Keep)
| 2 Bytes | 1 Byte | 1 Byte |
| ------- | ------ | ------ |
| ID | 0x02 | Option |
TCP
If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host. XUDP adds the UDP address after Opt(D), and the format is the same as creating a new sub-connection.
| 2 bytes | 1 byte | 1 byte |
| :--- | :--- | :--- |
| ID | 0x02 | Option Opt |
### End
UDP
| 2 Bytes | 1 Byte | 1 Byte |
| ------- | ------ | ------ |
| ID | 0x03 | Option |
| 2 bytes | 1 byte | 1 byte | 1 byte | 2 bytes | 1 byte | A bytes |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| ID | 0x02 | Option Opt | Network Type N | Port | Address Type T | Address A |
If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host.
When keeping a sub-connection, if Opt(D) is enabled, the data carried in this frame needs to be sent to the target host.
XUDP adds the UDP address after Opt(D), formatted the same as in "New Sub-connection", but without the Global ID.
### KeepAlive
### End Sub-connection (End)
| 2 Bytes | 1 Byte | 1 Byte |
| ------- | ------ | ---------- |
| ID | 0x04 | Option Opt |
| 2 bytes | 1 byte | 1 byte |
| :--- | :--- | :--- |
| ID | 0x03 | Option Opt |
While staying connected:
When closing a sub-connection, if Opt(D) is enabled, the data carried in this frame needs to be sent to the target host.
- If Opt(D) is enabled, the data carried by this frame must be discarded.
- ID can be a random value.
### Keep Connection (KeepAlive)
| 2 bytes | 1 byte | 1 byte |
| :--- | :--- | :--- |
| ID | 0x04 | Option Opt |
When keeping the connection:
* If Opt(D) is enabled, the data carried in this frame must be discarded.
* The ID can be a random value.
## Application
The Mux.Cool protocol is agnostic to the underlying protocol and can theoretically use any reliable streaming connection to transmit Mux.Cool protocol data.
The Mux.Cool protocol is independent of the underlying protocol. Theoretically, any reliable stream connection can be used to transmit Mux.Cool protocol data.
In target-oriented protocols such as Shadowsocks and VMess, a specified address must be included when establishing a connection. To maintain compatibility, the Mux.Cool protocol specifies the address as "v1.mux.cool". When the target address of the main connection matches this address, the Mux.Cool forwarding method is used. Otherwise, forwarding is done in the traditional way. (Note: This is an internal tag in the program, and VMess and VLESS do not send the "v1.mux.cool" address in data packets.)
In target-oriented protocols like Shadowsocks and VMess, a specified address must be included when the connection is established.
To maintain compatibility, the Mux.Cool protocol specifies the address as "v1.mux.cool". That is, when the target address of the main connection matches this, Mux.Cool forwarding is performed; otherwise, forwarding is performed in the traditional way. (Note: This is an internal marker within the program; VMess and VLESS do not send the "v1.mux.cool" address in the data packet.)
+46 -54
View File
@@ -1,99 +1,91 @@
# VLESS Protocol
VLESS is a stateless lightweight transmission protocol that can be used as a bridge between Xray clients and servers.
VLESS is a stateless lightweight transport protocol that serves as a bridge between Xray clients and servers.
## Request & Response
| 1 byte | 16 bytes | 1 byte | M bytes | 1 byte | 2 bytes | 1 byte | S bytes | X bytes |
| ---------------- | --------------- | ------------------------------- | ------------------------------- | ----------- | ------- | ------------ | ------- | ------------ |
| Protocol Version | Equivalent UUID | Additional Information Length M | Additional Information ProtoBuf | Instruction | Port | Address Type | Address | Request Data |
| 1 Byte | 16 Bytes | 1 Byte | M Bytes | 1 Byte | 2 Bytes | 1 Byte | S Bytes | X Bytes |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| Protocol Version | Equivalent UUID | Addons Length M | Addons ProtoBuf | Command | Port | Address Type | Address | Request Data |
| 1 Byte | 1 Byte | N Bytes | Y Bytes |
| --------------------------------------------- | ---------------------------------- | ---------------------------------- | ------------- |
| Protocol Version, consistent with the request | Length of additional information N | Additional information in ProtoBuf | Response data |
| 1 Byte | 1 Byte | N Bytes | Y Bytes |
| :--- | :--- | :--- | :--- |
| Protocol Version, same as request | Addons Length N | Addons ProtoBuf | Response Data |
VLESS had the aforementioned structure as early as the second alpha test version (ALPHA 2), with BETA being the fifth test version.
VLESS has had the above structure since the second alpha version, ALPHA 2 (BETA is the fifth test version):
"`Response authentication`" has been replaced with "`Protocol version`" and moved to the front, allowing VLESS to upgrade and eliminate the overhead of generating pseudo-random numbers. The obfuscation-related structure has been replaced with "`Additional information`" (ProtoBuf) and moved forward, giving the protocol itself scalability, with minimal overhead ([gogo/protobuf](https://github.com/gogo/protobuf)). If there is no additional information, there is no relevant overhead.
> "Response Authentication" was replaced by "Protocol Version" and moved to the very front, allowing VLESS to be upgraded while eliminating the overhead of generating pseudo-random numbers. Obfuscation-related structures were replaced by Addons (ProtoBuf) and moved forward, giving the protocol itself extensibility with minimal overhead ([gogo/protobuf](https://github.com/gogo/protobuf)); there is no related overhead if there are no Addons.
I always thought that "response authentication" was not necessary, and ALPHA replaced crypto/rand with math/rand in order to improve the performance of random number generation, which is no longer needed.
I always felt that "Response Authentication" wasn't necessary. In ALPHA, to improve the performance of random number generation, `math/rand` replaced `crypto/rand`, but now neither is needed.
The "Protocol Version" not only serves as "Response Authentication", but also gives VLESS the ability to upgrade the protocol structure seamlessly, bringing infinite possibilities. The "Protocol Version" is 0 in the test version and 1 in the official version. If there are any incompatible protocol structural changes in the future, the version should be upgraded.
"Protocol Version" not only serves the function of "Response Authentication" but also gives VLESS the ability to upgrade protocol structures painlessly, bringing infinite possibilities.
The "Protocol Version" is 0 in test versions and 1 in official versions. If there are incompatible protocol structure changes in the future, the version should be upgraded.
The design of VLESS server is switch version, which supports all VLESS versions at the same time. If you need to upgrade the protocol version (which may not happen), it is recommended that the server support it one month in advance, and then change the client after one month. VMess requests also have protocol versions, but their authentication information is outside, and the instruction part is highly coupled and has fixed encryption, which makes the protocol version meaningless inside. The server does not judge it, and the response does not have a protocol version. Trojan's protocol structure does not have a protocol version.
The design of the VLESS server is "switch version," meaning it supports all VLESS versions simultaneously. If a protocol version upgrade is needed (we might not reach that step), the recommended practice is for the server to support it a month in advance, and update clients a month later. VMess requests also have a protocol version, but its authentication information is outside, while the command part is highly coupled and has fixed encryption, making the inner protocol version meaningless. The server doesn't check it, and the response has no protocol version. The Trojan protocol structure has no protocol version.
The following is a UUID. I used to think that 16 bytes were a bit long and considered shortening it. However, I later saw that Trojan used 56 printable characters (56 bytes), which completely dispelled this idea. The server needs to verify the UUID every time, so performance is also very important: VLESS's Validator has undergone multiple refactoring/upgrades. Compared with VMess, it is very concise and consumes very few resources. It can support a large number of users at the same time, and its performance is also very strong. The verification speed is extremely fast (sync.Map). API dynamically adds and deletes users, making it more efficient and smooth.
https://github.com/XTLS/Xray-core/issues/158
Next is the UUID. I initially thought 16 bytes was a bit long and considered shortening it, but after seeing Trojan use 56 printable characters (56 bytes), I completely dismissed that thought. The server verifies the UUID every time, so performance is crucial: The VLESS Validator has undergone multiple refactors/upgrades. Compared to VMess, it is extremely concise and resource-efficient, capable of supporting a very large number of users simultaneously, with robust performance and extremely fast verification speed (sync.Map). Adding or deleting users dynamically via API is also more efficient and smoother.
<https://github.com/XTLS/Xray-core/issues/158>
Introducing ProtoBuf is an innovation, which will be explained in detail later. The structure from "instruction" to "address" is currently identical to VMess and also supports Mux.
Introducing ProtoBuf is a pioneering move, which will be explained in detail later. The structure from "Command" to "Address" is currently identical to VMess and also supports Mux.
Overall, ALPHA 2 to BETA mainly includes: structural evolution, cleaning and integration, performance improvement, and more completeness. All of these are incremental improvements, please refer to [VLESS Changes](https://github.com/rprx/v2ray-vless/releases) for details.
Overall, from ALPHA 2 to BETA, the changes were mainly: structural evolution, cleanup and integration, performance improvement, and greater perfection. These happened bit by bit; see [VLESS Changes](https://github.com/rprx/v2ray-vless/releases) for details.
## ProtoBuf
It seems that only VLESS supports embedding ProtoBuf, which is a data exchange format that encodes information tightly into binary TLV (Tag Length Value) structures.
It seems only VLESS allows optional embedded ProtoBuf. It is a data exchange format where information is tightly encoded into binary in a TLV structure (Tag Length Value).
The reason is that I saw an article that said that SS has some drawbacks, such as the lack of a design error reporting mechanism, and the client cannot take further action based on different errors. (But I don't agree that all errors should be reported, otherwise it can't prevent active probing. In the next beta version, the server can return a custom string of information.) So I think a scalable structure is important, and in the future, it can also carry dynamic port instructions. Not only the response, but the request also needs a similar structure. I originally planned to design TLV by myself, but then I found that ProtoBuf is the structure, ready-made, and it is completely suitable for this purpose, and the support for various languages is also good.
The origin was an article I read stating that SS has some shortcomings, such as lacking an error reporting mechanism design, meaning clients cannot take further actions based on different errors.
(I don't agree that all errors should be reported; otherwise, active probing cannot be prevented. In the next beta, the server can return a string of custom information.)
So I realized an extensible structure is important. In the future, it could also carry things like dynamic port commands. Not just responses, requests also need a similar structure.
I originally planned to design TLV myself, but then realized ProtoBuf *is* this structure, a ready-made wheel perfectly suitable for this task, with good language support.
Currently, "Additional Information" only has Scheduler and SchedulerV, which are substitutes for MessName and MessSeed. **When you don't need them, the "Additional Information Length" is 0, so there is no ProtoBuf serialization/deserialization overhead**. Actually, I prefer to call this process "concatenation" because that's all pb does in principle, and the related overhead is minimal. The concatenated bytes are very compact, similar to ALPHA's solution, and those who are interested can output and compare them separately.
Currently, "Addons" only contain Scheduler and SchedulerV, which replace MessName and MessSeed. **When you don't need them, "Addons Length" is 0, so there is no ProtoBuf serialization/deserialization overhead.** Actually, I prefer to call this process "splicing" because that's what pb effectively does in principle, with minimal overhead. The spliced bytes are very compact, hardly different from the ALPHA scheme. Those interested can output and compare them separately.
To indicate different levels of support for additional information (Addons, which can be understood as plugins and can have many plugins in the future), the next beta version will add "Addon Version" before "Addon Length". 256-1 = 255 bytes is enough and reasonable (65535 is too much and there may be malicious padding), and only one-tenth of the existing space is used. In the future, there will not be so many addons at the same time, and most of the time there will be no addons at all. If it is not enough, you can upgrade to a newer version of VLESS.
To indicate different levels of support for Addons (can be understood as plugins; there can be many plugins in the future), the next beta will add an "Addons Version" before "Addons Length". 256 - 1 = 255 bytes is sufficient and reasonable (65535 is too much and might be maliciously filled). Current usage is only one-tenth of that. There won't be that many Addons simultaneously in the future, and in most cases, there are no Addons at all. If it really isn't enough, the VLESS version can be upgraded.
To reduce logical judgment and other expenses, it is temporarily decided that Addons will not use a multi-level structure. A month ago, there was an idea of "variable protocol format". PB can shuffle the order, but it is not necessary because the design of modern encryption will not allow bystanders to see that the headers of the two transmissions are the same.
To reduce overhead like logic checks, it is tentatively decided that Addons will not use a multi-level structure. A month ago, there was an idea of "variable protocol format". pb can shuffle order, but it's unnecessary because modern encryption designs prevent observers from seeing that two transmissions have the same header.
Below is an introduction to the concepts of Schedulers and Encryption, both of which are optional. One is designed to address issues related to traffic timing, while the other is designed to address cryptographic issues.
Below introduces the concepts of Schedulers and Encryption. **Both are optional.** One addresses traffic timing characteristics, and the other addresses cryptographic issues.
## Flow
## ~~Schedulers~~ Flow
### Flow Control (Formerly Traffic Scheduler)
~~Tentative Chinese name: Traffic Scheduler~~ (Updated 2020-09-03: Chinese name confirmed as "Flow Control"). Instructions are carried by ProtoBuf, controlling the data part.
The Flow Control command is carried by ProtoBuf and manages the data section.
I previously found that VMess's original shake "metadata obfuscation" brought no meaningful changes over TLS, only reducing performance, so VLESS deprecated it. Also, the term "obfuscation" is easily misunderstood as camouflage, so it was also deprecated. By the way, I've never been optimistic about camouflage: if it can't be exactly the same, isn't that a strong characteristic? If it can be exactly the same, why not just use the camouflage target directly? I used SSR at first, later found out it only superficially fooled ISPs, and never used it again.
I previously discovered that VMess's original "metadata obfuscation" feature didn't provide any meaningful changes in TLS but only decreased performance. Consequently, VLESS has abandoned this feature. Moreover, the term "obfuscation" is often misinterpreted as camouflage, so it has been discarded.
So, what problem does the "Traffic Scheduler" solve? It affects macroscopic traffic timing characteristics, not microscopic characteristics (which encryption solves). Traffic timing characteristics can be protocol-induced, like the Socks5 handshake in Socks5 over TLS; different characteristics on TLS look like different protocols to monitors. Infinite Schedulers would be equivalent to infinite protocols (redistributing the data size sent each time, etc.). Traffic timing characteristics can also be behavior-induced, such as how many files are loaded when visiting the Google homepage, the order, and the size of each file. Adding another layer of encryption doesn't effectively mask this information.
As for camouflage, if it can't be an exact match, wouldn't it be a noticeable characteristic? If it could be an exact match, why not use the intended target for camouflage directly? Initially, I used SSR but found it only provided superficial disguises, fooling operators. Thus, I stopped using it.
Schedulers don't need to wrap everything on the outside like Encryption below, because the tiny amount of header data is negligible compared to the subsequent data volume.
#### Purpose of Flow Control
Flow Control influences macro traffic temporal characteristics rather than micro characteristics addressed by encryption. Traffic temporal characteristics can be:
1. **Protocol-based**, e.g., Socks5 handshake when using Socks5 over TLS. Different traits on TLS are considered different protocols for monitors. Infinite schedulers equate to infinite protocols (reallocating data sent each time).
2. **Behavior-based**, e.g., loading files, their order, and size when accessing Google's homepage. Adding another encryption layer cannot effectively conceal this information.
Schedulers don't require wrapping like encryption since the header data's tiny amount is negligible compared to the remaining data.
BETA 2 is anticipated to introduce two basic schedulers: Zstd compression and dynamic data expansion. Advanced operations will control and distribute at a macro level, but for now, these remain under development.
BETA 2 is expected to launch two elementary Schedulers: Zstd compression and dynamic data expansion. Advanced operations involve controlling and allocating from a macro level, which is postponed for now.
## Encryption
Unlike VMess, which is highly coupled, VLESS allows the server and client to pre-agree on an encryption method, which is only encrypted with an outer layer. This is somewhat similar to using TLS, which does not affect any of the data carried, and can be understood as replacing TLS with pre-agreed encryption at the bottom. Compared with high coupling, this approach is more reasonable and flexible: if there is a security issue with one encryption method, it can be discarded and another one can be used directly, which is very convenient. The VLESS server also allows for different encryption methods to coexist.
Unlike VMess's high coupling, VLESS servers and clients will soon be able to agree on an encryption method in advance, wrapping only one layer of encryption on the outside. This is somewhat similar to using TLS; it doesn't affect any carried data and can be understood as swapping the underlying layer from TLS to a preset agreed encryption. Compared to high coupling, this method is more reasonable and flexible: if a security issue arises with one encryption method, just discard it and switch to another, very convenient. VLESS servers will also allow different encryption methods to coexist.
Compared with VMess, VLESS replaces security with encryption and disableInsecureEncryption with decryption, which solves all the problems. Currently, encryption and decryption only accept "none" and cannot be left blank (even if there are connection security checks in the future), as detailed in the VLESS configuration document. Encryption does not need to be moved out one level, firstly because it cannot reuse a lot of code, and secondly because it will affect the control granularity, which will be understood by looking at future applications.
Compared to VMess, VLESS effectively replaces `security` with `encryption` and `disableInsecureEncryption` with `decryption`, solving all problems. Currently, `encryption` and `decryption` only accept "none" and cannot be empty (even if connection security checks are added later). See [VLESS Configuration Documentation](https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md) for details. `encryption` doesn't need to be moved out one level, firstly because a lot of code can't be reused, and secondly because it affects control granularity. Future applications will make this clear.
Encryption supports two types of forms. One type is completely independent and requires an additional password, suitable for private use. The other type combines with the existing UUID for encryption, which is suitable for public use.
Encryption supports two forms. One is completely independent encryption requiring an extra password, suitable for private use. The other combines with the existing UUID for encryption, suitable for public use.
(If the first form is used and the password is disclosed in some form, e.g., shared by many people, MITM attacks are not far off.)
Redesigned dynamic ports might be released alongside encryption. Instructions will be carried by ProtoBuf, and the implementation will differ significantly from VMess dynamic ports.
(If the first type of encryption is used and the password is publicly available in some form, such as multiple people sharing it, then a man-in-the-middle attack is not far away.)
wrapping existing encryption is very simple, just adding a layer of writer & reader. BETA 3 is expected to support SS's aes-128-gcm and chacha20-ietf-poly1305:
Client `encryption` can be filled with "auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654". "auto" will choose the best fit for the current machine, 0 represents beta version, and the last part is the password. Server `decryption` is filled similarly; it will attempt decryption one by one upon receiving a request.
A redesigned dynamic port may be released simultaneously with encryption, and the command is carried by ProtoBuf. The specific implementation and the dynamic port of VMess will also have many differences.
It is very easy to cash out encrypted currency, which adds an extra layer of writer & reader. BETA 3 is expected to support SS's aes-128-gcm and chacha20-ietf-poly1305:
The encryption on the client-side can be filled with "auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654". Auto will choose the most suitable one for the current machine, 0 represents the beta version, and the last one is the password. The decryption on the server-side is also filled in a similar way, and each decryption attempt will be made when the request is received.
Not all combinations need to be tried one by one: VMess encryption is divided into three parts. The first part is the authentication information, which combines UUID, alterId, and time factors. The second part is the instruction part, which is encrypted using a fixed algorithm. The instruction contains the encryption algorithm used in the data part. The third part is the important data part. It can be seen that the VMess encryption and decryption method is actually many-to-one (adapted by the server), not just combining UUID. However, it is also a relatively difficult thing to encrypt only by combining UUID. It will not be available in a short time. Considering that we now have VMessAEAD available, there is no need to rush. If VLESS introduces an encryption method that combines UUID, it is equivalent to reconstructing the entire VMess.
Not all combinations need to be tried one by one: VMess encryption is divided into three parts. The first part is authentication info, combining UUID, alterId, and time factors. The second part is the command part, encrypted with a fixed algorithm; the command contains the encryption algorithm used for the data part. The third part is the important data part. It can be seen that VMess encryption/decryption is actually many-to-one (server adaptation), not just combining UUID. But encrypting just by combining UUID is relatively troublesome and won't be released soon. Given we have VMessAEAD now, there's no rush. If VLESS introduces encryption combined with UUID, it's equivalent to refactoring the entire VMess.
## UDP issues
[XUDP: VLESS & VMess & Mux UDP FullCone NAT](https://github.com/XTLS/Xray-core/discussions/252)
## Client Development Guide
## Client Development Guidelines
1. The VLESS protocol itself may have incompatible upgrades, but the parameters in the client configuration file are basically only increased and not decreased. The protocol implementation of the iOS client needs to keep up with the upgrade.
2. Visual standard: Please use VLESS as the UI identifier uniformly, instead of VLess / Vless / vless. The configuration file is not affected, and the code should follow naturally.
3. `Encryption` should be made into an input box instead of a selection box. The default value of the new configuration should be `none`, and if the user leaves it blank, it should be filled in with `none`.
1. The VLESS protocol itself will have incompatible upgrades, but client configuration file parameters will basically only increase, not decrease. iOS client protocol implementation needs to follow upgrades closely.
2. **Visual Standard: Please use VLESS uniformly for UI identifiers**, not VLess / Vless / vless. Configuration files are unaffected, code style follows natural conventions.
3. `encryption` should be an input box, not a select box. The default value for new configurations should be `none`. If the user leaves it empty, fill `none` automatically.
## VLESS Sharing Link Standard
Thank you to [@DuckSoft](https://github.com/DuckSoft) for the proposal!
Thanks to <img src="https://avatars2.githubusercontent.com/u/7822648?s=32" width="32px" height="32px" alt="a"/> [@DuckSoft](https://github.com/DuckSoft) for the proposal!
Please see [VMessAEAD/VLESS Sharing Link Standard Proposal](https://github.com/XTLS/Xray-core/issues/91) for more details.
For details, please see [VMessAEAD / VLESS Sharing Link Standard Proposal](https://github.com/XTLS/Xray-core/issues/91)
+102 -101
View File
@@ -1,6 +1,6 @@
# VMess Protocol
VMess is an encrypted transmission protocol that can serve as a bridge between the Xray client and server.
VMess is an encrypted transport protocol that can act as a bridge between Xray clients and servers.
## Version
@@ -10,165 +10,166 @@ The current version number is 1.
### Underlying Protocol
VMess is a TCP-based protocol where all data is transmitted over TCP.
VMess is a TCP-based protocol; all data is transmitted using TCP.
### User ID
An ID is equivalent to a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier), which is a 16-byte long random number. Its function is similar to a token. An ID looks like: `de305d54-75b4-431b-adb2-eb6b9e546014`, it is almost entirely random and can be generated using any UUID generator, such as [this one](https://www.uuidgenerator.net/).
The ID is equivalent to a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier). It is a 16-byte random number that acts as a token.
An ID looks like: `de305d54-75b4-431b-adb2-eb6b9e546014`. It is almost completely random and can be generated using any UUID generator, such as [this one](https://www.uuidgenerator.net/).
User ID can be specified in the [configuration file](../../config/).
The User ID can be specified in the [configuration file](../../config/).
### Functions
- MD5: [MD5 Function](https://en.wikipedia.org/wiki/MD5)
- Input parameter is any length byte array
- Output is a 16-byte array
- Input parameter: Byte array of arbitrary length
- Output: A 16-byte array
- HMAC: [HMAC Function](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)
- Input parameters are:
- Input parameters:
- H: Hash function
- K: Key, any length byte array
- M: Message, any length byte array
- K: Key, byte array of arbitrary length
- M: Message, byte array of arbitrary length
- Shake: [SHA3-Shake128 Function](https://en.wikipedia.org/wiki/SHA-3)
- Input parameter is any length string
- Output is any length string
- Input parameter: String of arbitrary length
- Output: String of arbitrary length
## Communication Process
VMess is a stateless protocol, which means that data can be transmitted directly between the client and the server without the need for a handshake. Each data transmission has no impact on other data transmissions before or after it.
VMess is a stateless protocol, meaning no handshake is required between the client and server to transmit data. Each data transmission has no effect on previous or subsequent transmissions.
When a VMess client initiates a request, the server checks whether the request comes from a legitimate client. If the validation passes, the server forwards the request and sends the obtained response back to the client.
The VMess client initiates a request. The server determines if the request comes from a legitimate client. If verification passes, the request is forwarded, and the received response is sent back to the client.
VMess uses an asymmetric format, meaning that the requests sent by the client and the responses from the server use different formats.
VMess uses an asymmetric format, meaning the request sent by the client and the response from the server use different formats.
## Client Request
| 16 Bytes | X Bytes | Remaining |
| -------------------------- | ---------------- | --------- |
| Authentication Information | Instruction Part | Data Part |
| 16 bytes | X bytes | Remaining part |
| ------------------ | -------------- | -------------- |
| Authentication Info| Command Section| Data Section |
### Authentication Information
### Authentication Info
The authentication information is a 16-byte hash (hash) value, which is calculated as follows:
The authentication info is a 16-byte hash value, calculated as follows:
- H = MD5
- K = User ID (16 bytes)
- M = UTC time accurate to seconds, with a random value of ±30 seconds from the current time (8 bytes, Big Endian)
- M = UTC time, precise to seconds, a random value within 30 seconds before or after the current time (8 bytes, Big Endian)
- Hash = HMAC(H, K, M)
### Command Section
The instruction part is encrypted using AES-128-CFB.
The command section is encrypted using AES-128-CFB:
- Key: MD5(user ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
- IV: MD5(X + X + X + X), X = []byte(time generated by authentication information) (8 bytes, Big Endian)
- Key: MD5(User ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
- IV: MD5(X + X + X + X), where X = []byte(Time used for generating authentication info) (8 bytes, Big Endian)
| 1 Byte | 16 Bytes | 16 Bytes | 1 Byte | 1 Byte | 4 bits | 4 bits | 1 Byte | 1 Byte | 2 Bytes | 1 Byte | N Bytes | P Bytes | 4 Bytes |
| :-----: | :----------------: | :-----------------: | :---------------------------: | :-----: | :------: | :---------------: | :------: | :-----: | :-----: | :----------: | :-----: | :----------: | :------: |
| Version | Data Encryption IV | Data Encryption Key | Response Authentication Value | Options | Reserved | Encryption Method | Reserved | Command | Port | Address Type | Address | Random Value | Checksum |
| 1 byte | 16 bytes | 16 bytes | 1 byte | 1 byte | 4 bits | 4 bits | 1 byte | 1 byte | 2 bytes | 1 byte | N bytes | P bytes | 4 bytes |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| Version Ver | Data Encryption IV | Data Encryption Key | Response Auth V | Option Opt | Margin P | Encryption Sec | Reserved | Command Cmd | Port | Address Type T | Address A | Random Value | Checksum F |
Options Opt Details: (When a bit is 1, it means the option is enabled)
Option Opt details: (When a bit is 1, the option is enabled)
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| X | X | X | X | X | M | R | S |
| X | X | X | X | X | M | R | S |
of which:
Where:
- 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);
- R (0x02): Client expects to reuse TCP connection (deprecated in Xray 2.23+);
- This item only takes effect when S is enabled;
- M (0x04): Enable metadata obfuscation (recommended);
- This item only takes effect when S is enabled;
- When this item is enabled, the client and server need to construct two Shake instances respectively, RequestMask = Shake (request data IV), ResponseMask = Shake (response data IV).
- X: Reserved
- Redundancy P: Random value added before checksum value;
- Encryption Method: Specify the encryption method for the data part, and the optional values are:
- 0x00: AES-128-CFB;
- 0x01: No encryption;
- 0x02: AES-128-GCM;
- 0x03: ChaCha20-Poly1305;
- Instruction Cmd:
- 0x01: TCP data;
- 0x02: UDP data;
- Port Port: Integer port number in Big Endian format;
- Address Type T:
- **Version Ver**: Always 1.
- **Data Encryption IV**: Random value.
- **Data Encryption Key**: Random value.
- **Response Auth V**: Random value.
- **Option Opt**:
- S (0x01): Standard format data stream (Recommended enabled).
- R (0x02): Client expects to reuse TCP connection (Deprecated in Xray 2.23+).
- Valid only when S is enabled.
- M (0x04): Enable metadata obfuscation (Recommended enabled).
- Valid only when S is enabled.
- When enabled, both client and server need to construct two Shake instances respectively: RequestMask = Shake(Request Data IV), ResponseMask = Shake(Response Data IV).
- X: Reserved.
- **Margin P**: Adds P bytes of random value before the checksum.
- **Encryption Sec**: Specifies the encryption method for the data section. Options:
- 0x00: AES-128-CFB
- 0x01: No encryption
- 0x02: AES-128-GCM
- 0x03: ChaCha20-Poly1305
- **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 a 1-byte length (L) + L-byte domain name;
- When T = 0x03, A is a 16-byte IPv6 address;
- Check F: FNV1a hash of all content in the instruction except F.
- **Address A**:
- When T = 0x01, A is a 4-byte IPv4 address.
- When T = 0x02, A is 1-byte length (L) + L bytes domain name.
- When T = 0x03, A is a 16-byte IPv6 address.
- **Checksum F**: FNV1a hash of all content in the command section except F.
### Data Section
When Opt(S) is enabled, this format is used for the data section. The actual request data is divided into several small chunks, and each chunk has the following format. After the server verifies all the small chunks, it will be forwarded in the basic format.
When Opt(S) is enabled, the data section uses this format. The actual request data is split into several small chunks, each formatted as follows. The server verifies all small chunks before forwarding them according to the basic format.
| 2 Bytes | L Bytes |
| :------: | :---------: |
| 2 bytes | L bytes |
| :---: | :---: |
| Length L | Data Packet |
in which:
Where:
- Length L: A big-endian integer with a maximum value of 2^14.
- When Opt(M) is enabled, the value of L is equal to the true value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
- Packet: A data packet encrypted by the specified encryption method.
- **Length L**: Integer in Big Endian format, maximum value is 2^14.
- When Opt(M) is enabled, Value of L = Real Value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte().
- **Data Packet**: Data packet encrypted by the specified encryption method.
Before the transmission is completed, the data packet must contain actual data, in addition to the length and authentication data. When the transmission is complete, the client must send an empty data packet, that is, L = 0 (unencrypted) or the length of the authentication data (encrypted), to indicate the end of the transmission.
Before transmission ends, the data packet must contain actual data (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 length of authentication data (with encryption), to indicate the end of transmission.
The packets are formatted as follows, depending on the encryption method:
Depending on the encryption method, the data packet format is as follows:
- Unencrypted:
  - L bytes: actual data;
- AES-128-CFB: The entire data section 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 instruction section, IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.
  - L - 16 bytes: actual data;
  - 16 bytes: GCM authentication information
- ChaCha20-Poly1305: Key = MD5 (instruction part Key) + MD5 (MD5 (instruction part Key)), IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.
  - L - 16 bytes: actual data;
  - 16 bytes: Poly1305 authentication information
- **No encryption**:
- L bytes: Actual data.
- **AES-128-CFB**: The entire data section 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 from the Command Section, IV = count (2 bytes) + IV (10 bytes). count starts from 0 and increments by 1 for each packet; IV is the 3rd to 12th bytes of the Command Section IV.
- L - 16 bytes: Actual data.
- 16 bytes: GCM authentication info.
- **ChaCha20-Poly1305**: Key = MD5(Command Section Key) + MD5(MD5(Command Section Key)), IV = count (2 bytes) + IV (10 bytes). count starts from 0 and increments by 1 for each packet; IV is the 3rd to 12th bytes of the Command Section IV.
- L - 16 bytes: Actual data.
- 16 bytes: Poly1305 authentication info.
## Server Response
The header data is encrypted using AES-128-CFB encryption. The IV is MD5 of the data encryption IV, and the Key is MD5 of the data encryption Key. The actual response data varies depending on the encryption settings.
The response header data is encrypted using AES-128-CFB, with IV being MD5(Data Encryption IV) and Key being MD5(Data Encryption Key). The actual response data varies depending on encryption settings.
| 1 Byte | 1 Byte | 1 Byte | 1 Byte | M Bytes | Remaining Part |
| ------------------------- | ---------- | ----------- | ---------------- | --------------- | -------------------- |
| Response Authentication V | Option Opt | Command Cmd | Command Length M | Command Content | Actual Response Data |
| 1 byte | 1 byte | 1 byte | 1 byte | M bytes | Remaining part |
| :--- | :--- | :--- | :--- | :--- | :--- |
| Response Auth V | Option Opt | Command Cmd | Command Length M | Command Content | Actual Response Data |
in which
Where:
- Response Authentication V: must match the response authentication V in the client request.
- Option Opt:
- 0x01: server prepares to reuse TCP connections (deprecated in Xray 2.23+).
- Command Cmd:
- 0x01: dynamic port command.
- Actual response data:
- If Opt(S) in the request is enabled, the standard format is used. Otherwise, the basic format is used.
- Both formats are identical to the request data.
- When Opt(M) is enabled, the value of length L is equal to the true value XOR Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte().
- **Response Auth V**: Must match the Response Auth V in the client request.
- **Option Opt**:
- 0x01: Server is ready to reuse TCP connection (Deprecated in Xray 2.23+).
- **Command Cmd**:
- 0x01: Dynamic port command.
- **Actual Response Data**:
- If Opt(S) in the request was enabled, standard format is used; otherwise, basic format is used.
- The format is the same as the request data.
- When Opt(M) is enabled, Value of Length L = Real Value xor Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte().
### Dynamic Port Instructions
### Dynamic Port Command
| 1 Byte | 2 Bytes | 16 Bytes | 2 Bytes | 1 Byte | 1 Byte |
| -------- | ------- | -------- | ------- | ---------- | ----------------- |
| Reserved | Port | User ID | AlterID | User level | Validity period T |
| 1 byte | 2 bytes | 16 bytes | 2 bytes | 1 byte | 1 byte |
| :--- | :--- | :--- | :--- | :--- | :--- |
| Reserved | Port | User ID | AlterID | User Level | Validity Time T |
in which:
Where:
- Port: Integer port number in Big Endian format
- T: Number of minutes as integer value.
- **Port**: Integer port number in Big Endian format.
- **Validity Time T**: Number of minutes.
When the client receives a dynamic port command, the server opens a new port for communication. The client can then send data to the new port. After T minutes, the port will expire, and the client must use the main port to communicate again.
When the client receives a dynamic port command, 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 expire, and the client must resume using the main port for communication.
## Comment
## Notes
- To ensure forward compatibility, the values of all reserved fields must be 0.