EN Refactor Transports

This commit is contained in:
Meow
2026-05-09 06:47:38 +08:00
parent eeca4a15fb
commit 9c0b0e37dc
19 changed files with 1362 additions and 1253 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ export const nav: DefaultTheme.Config["nav"] = [
{ text: "Basic Configuration", link: "/en/config/" },
{ text: "Inbound Protocols", link: "/en/config/inbounds/" },
{ text: "Outbound Protocols", link: "/en/config/outbounds/" },
{ text: "Transports", link: "/en/config/transports/" }
{ text: "Transport Configuration", link: "/en/config/transports/" }
]
},
{
+30 -11
View File
@@ -38,7 +38,7 @@ export const sidebar: DefaultTheme.Config["sidebar"] = {
{ text: "Routing", link: "/en/config/routing.md" },
{ text: "Statistics", link: "/en/config/stats.md" },
{
text: "Transport (uTLS, REALITY)",
text: "Transport Configuration",
link: "/en/config/transport.md"
},
{ text: "Metrics", link: "/en/config/metrics.md" },
@@ -101,23 +101,42 @@ export const sidebar: DefaultTheme.Config["sidebar"] = {
]
},
{
text: "Transports",
text: "Transport Configuration",
link: "/en/config/transports/",
collapsed: true,
items: [
{ text: "RAW", link: "/en/config/transports/raw.md" },
{
text: "XHTTP: Beyond REALITY",
link: "/en/config/transports/xhttp.md"
text: "Transport Methods",
items: [
{ text: "RAW", link: "/en/config/transports/raw.md" },
{
text: "XHTTP: Beyond REALITY",
link: "/en/config/transports/xhttp.md"
},
{ text: "mKCP", link: "/en/config/transports/mkcp.md" },
{ text: "gRPC", link: "/en/config/transports/grpc.md" },
{ text: "WebSocket", link: "/en/config/transports/websocket.md" },
{
text: "HTTPUpgrade",
link: "/en/config/transports/httpupgrade.md"
},
{ text: "Hysteria", link: "/en/config/transports/hysteria.md" }
]
},
{ text: "mKCP", link: "/en/config/transports/mkcp.md" },
{ text: "gRPC", link: "/en/config/transports/grpc.md" },
{ text: "WebSocket", link: "/en/config/transports/websocket.md" },
{
text: "HTTPUpgrade",
link: "/en/config/transports/httpupgrade.md"
text: "Transport Security",
items: [
{ text: "REALITY", link: "/en/config/transports/reality.md" },
{ text: "TLS", link: "/en/config/transports/tls.md" }
]
},
{ text: "Hysteria", link: "/en/config/transports/hysteria.md" }
{
text: "Additional Configuration",
items: [
{ text: "FinalMask", link: "/en/config/transports/finalmask.md" },
{ text: "Sockopt", link: "/en/config/transports/sockopt.md" }
]
}
]
}
],
+1 -1
View File
@@ -350,7 +350,7 @@ The weather is getting cooler, but the pace of development has not cooled down.
## 2022.8.28 <Badge>[v1.5.10](https://github.com/XTLS/Xray-core/releases/tag/v1.5.10)</Badge>
The underlying transport now supports more reasonable TCP Keepalive configurations.
`sockopt` now supports more reasonable TCP Keepalive configurations.
## 2022.6.20 <Badge>[v1.5.8](https://github.com/XTLS/Xray-core/releases/tag/v1.5.8)</Badge>
+2 -2
View File
@@ -38,7 +38,7 @@ An array containing a series of powerful fallback distribution configurations.
The `fallbacks` item is optional and can only be used with the TCP+TLS transport combination.
- When this item has child elements, [Inbound TLS](../transport.md#tlsobject) must set `"alpn":["http/1.1"]`.
- When this item has child elements, [Inbound TLS](../transports/tls.md#tlsobject) must set `"alpn":["http/1.1"]`.
Usually, you need to first set a default fallback with both `alpn` and `path` omitted or empty, and then configure other traffic splitting as needed.
@@ -56,7 +56,7 @@ Attempts to match the TLS ALPN negotiation result. Empty means any. Default is `
Xray will only attempt to read the TLS ALPN negotiation result when necessary. If successful, it outputs `realAlpn =` to the info log.
Usage: Solves the issue where Nginx's h2c service cannot be compatible with http/1.1 simultaneously. Nginx would require two `listen` lines, for 1.1 and h2c respectively.
Note: When `fallbacks` `alpn` contains `"h2"`, [Inbound TLS](../transport.md#tlsobject) needs to set `"alpn":["h2","http/1.1"]` to support h2 access.
Note: When `fallbacks` `alpn` contains `"h2"`, [Inbound TLS](../transports/tls.md#tlsobject) needs to set `"alpn":["h2","http/1.1"]` to support h2 access.
::: tip
The `alpn` set in Fallback matches the _actually negotiated_ ALPN, whereas the `alpn` set in Inbound TLS is the list of _optional_ ALPNs during the handshake. The meanings are different.
+3 -3
View File
@@ -38,7 +38,7 @@ The solution is not to listen on `0.0.0.0` but to listen on the specific IP addr
Supports Unix domain sockets in absolute path format, such as `"/dev/shm/domain.socket"`. You can add `@` at the beginning to represent [abstract](https://www.man7.org/linux/man-pages/man7/unix.7.html), and `@@` for abstract with padding.
When filling in a Unix domain socket, `port` and `allocate` will be ignored. The protocol can currently be VLESS, VMess, or Trojan, and applies only to TCP-based underlying transports, such as `tcp`, `websocket`, `grpc`. UDP-based transports like `mkcp` are not supported.
When filling in a Unix domain socket, `port` and `allocate` will be ignored. The protocol can currently be VLESS, VMess, or Trojan, and applies only to TCP-based transport methods, such as `tcp`, `websocket`, `grpc`. UDP-based transports like `mkcp` are not supported.
When filling in a Unix domain socket, you can use the format `"/dev/shm/domain.socket,0666"`, i.e., adding a comma and access permission indicators after the socket, to specify the access permissions of the socket. This can be used to solve socket permission issues that occur by default.
@@ -62,9 +62,9 @@ Connection protocol name. See the list of available [Inbound Protocols](./inboun
Specific configuration content, which varies by protocol. See `InboundConfigurationObject` in each protocol section for details.
> `streamSettings`: [StreamSettingsObject](./transport.md#streamsettingsobject)
> `streamSettings`: [StreamSettingsObject](./transport.md)
Underlying transport method (transport) is the way the current Xray node connects with other nodes.
Transport configuration for this inbound.
> `tag`: string
> The identifier of this inbound connection, used to locate this connection in other configurations.
+1 -1
View File
@@ -50,7 +50,7 @@ A map mapping local ports to required remote addresses/ports (if the inbound lis
When set to `true`, dokodemo-door will recognize data forwarded by iptables and forward it to the corresponding target address.
Please refer to the `tproxy` setting in [Transport Configuration](../transport.md#sockoptobject).
Please refer to the `tproxy` setting in [Sockopt](../transports/sockopt.md#sockoptobject).
> `userLevel`: number
+1 -1
View File
@@ -118,7 +118,7 @@ Currently, the following flow control modes are available in the inbound protoco
XTLS is only available under the following combinations:
- TCP+TLS/Reality: In this case, encrypted data is directly copied at the underlying layer (if transmitting TLS 1.3).
- TCP+TLS/REALITY: In this case, encrypted data is directly copied at the underlying layer (if transmitting TLS 1.3).
- VLESS Encryption: No underlying transport restrictions. If the underlying layer does not support direct copying (see above), it only penetrates Encryption.
> `reverse`: struct
+8 -8
View File
@@ -63,9 +63,9 @@ The identifier for this outbound connection, used to locate this connection in o
When not empty, its value must be **unique** among all `tag`s.
:::
> `streamSettings`: [StreamSettingsObject](./transport.md#streamsettingsobject)
> `streamSettings`: [StreamSettingsObject](./transport.md)
The underlying transport method is the way the current Xray node connects with other nodes.
Transport configuration for this outbound.
> `proxySettings`: [ProxySettingsObject](#proxysettingsobject)
@@ -79,10 +79,10 @@ Specific configuration related to Mux.
If this outbound attempts to send a domain request, this controls whether it is resolved/how it is resolved to an IP before sending.
The default value is `AsIs`, meaning it is sent to the remote server as is. All parameter meanings are roughly equivalent to `domainStrategy` in [sockopt](./transport.md#sockoptobject).
The default value is `AsIs`, meaning it is sent to the remote server as is. All parameter meanings are roughly equivalent to `domainStrategy` in [Sockopt](./transports/sockopt.md#sockoptobject).
::: tip
This controls **proxied requests**. If the address of the outbound proxy server is a domain name, and you need to select a resolution strategy for the domain name itself, you should configure `domainStrategy` in [sockopt](./transport.md#sockoptobject).
This controls **proxied requests**. If the address of the outbound proxy server is a domain name, and you need to select a resolution strategy for the domain name itself, you should configure `domainStrategy` in [Sockopt](./transports/sockopt.md#sockoptobject).
:::
### ProxySettingsObject
@@ -99,15 +99,15 @@ This controls **proxied requests**. If the address of the outbound proxy server
When the identifier of another outbound is specified, data sent by this outbound will be forwarded to the specified outbound for transmission.
::: danger
This option conflicts with [SockOpt.dialerProxy](./transport.md#sockoptobject). Choose one as needed.
This option conflicts with [Sockopt.dialerProxy](./transports/sockopt.md#sockoptobject). Choose one as needed.
By default, this forwarding method **does not go through** the underlying transport method (REALITY/XHTTP/gRPC...), meaning the `streamSettings` of this outbound will not take effect.<br>
If you need forwarding that supports underlying transport methods, please use `SockOpt.dialerProxy` instead or set `transportLayer` to `true`.
By default, this forwarding method **ignores** this outbound's own transport configuration (such as XHTTP, REALITY, or Sockopt), meaning the `streamSettings` of this outbound will not take effect.<br>
If you need forwarding that works together with `streamSettings`, please use `Sockopt.dialerProxy` instead or set `transportLayer` to `true` here.
:::
> `transportLayer`: true | false
`true` converts this setting to `SockOpt.dialerProxy` to support forwarding via underlying transport methods. The default is `false`, meaning no conversion.
`true` converts this setting to `Sockopt.dialerProxy` so the forwarding can use this outbound's `streamSettings`. The default is `false`.
### MuxObject
+1 -1
View File
@@ -57,7 +57,7 @@ This outbound has a default safety policy in server-side and reverse-proxy scena
Default value `"AsIs"`.
The meanings of all parameters are roughly equivalent to `domainStrategy` in [sockopt](../transport.md#sockoptobject).
The meanings of all parameters are roughly equivalent to `domainStrategy` in [Sockopt](../transports/sockopt.md#sockoptobject).
Only using `"AsIs"` here allows passing the domain name to the subsequent `sockopt` module. If set to non-`"AsIs"` here, causing the domain to be resolved to a specific IP, it will invalidate the subsequent `sockopt.domainStrategy` and its related `happyEyeballs`. (There is no negative impact if these two settings are not adjusted).
+1 -1
View File
@@ -2,7 +2,7 @@
Client implementation of the Hysteria protocol.
This page is very simple because the Hysteria protocol is actually composed of a simple proxy control protocol and a tuned QUIC underlying transport. In Xray, the proxy protocol and the underlying transport are separated. For more details (such as `brutal`), please refer to [hysteriaSettings](../transports/hysteria.md) [finalmask.quicParams](../transport.md#quicParams) in the underlying transport section.
This page is very simple because the Hysteria protocol is actually composed of a simple proxy control protocol and a tuned QUIC transport implementation. In Xray, the proxy protocol and transport configuration are separated. For more details (such as `brutal`), please refer to transport configuration items [hysteriaSettings](../transports/hysteria.md) and [FinalMask.quicParams](../transports/finalmask.md#quicparams).
::: tip
The `hysteria protocol` itself has no authentication. When using with a non `hysteria` transport layer, it will be unable to proxy `udp`, and using it with other transport layers is not recommended.
+1 -1
View File
@@ -84,7 +84,7 @@ Currently, the following flow control modes are available in the outbound protoc
XTLS is available only in the following combinations:
- **TCP+TLS/Reality**: In this case, if transmitting TLS 1.3, the core will attempt to Splice encrypted data at the bottom layer. If successful, it saves all core IO overhead.
- **TCP+TLS/REALITY**: In this case, if transmitting TLS 1.3, the core will attempt to Splice encrypted data at the bottom layer. If successful, it saves all core IO overhead.
- **VLESS Encryption**: No underlying transport restrictions. If the underlying transport is not TCP, it only attempts to penetrate Encryption, saving Encryption overhead. If it is TCP, it will still attempt to perform Splice.
::: tip About Splice
File diff suppressed because it is too large Load Diff
+404
View File
@@ -0,0 +1,404 @@
# FinalMask
FinalMask performs the last stage of traffic obfuscation after the core has already processed transport-layer security, including TLS and REALITY.
It can be used for multiple kinds of TCP and UDP camouflage, as well as QUIC-related parameter tuning.
## FinalMaskObject
`FinalMaskObject` corresponds to the `finalmask` item in [`StreamSettingsObject`](../transport.md#streamsettingsobject).
```json
{
// outbound example; also applies to inbound
"outbounds": [
{
// ...
"streamSettings": {
"finalmask": {
// [!code focus:30]
"tcp": [
{
"type": "",
"settings": {}
}
],
"udp": [
{
"type": "",
"settings": {}
}
],
"quicParams": {
"congestion": "force-brutal",
"debug": false,
"brutalUp": "60 mbps",
"brutalDown": 0,
"udpHop": {
"ports": "20000-50000",
"interval": "5-10"
},
"initStreamReceiveWindow": 8388608,
"maxStreamReceiveWindow": 8388608,
"initConnectionReceiveWindow": 20971520,
"maxConnectionReceiveWindow": 20971520,
"maxIdleTimeout": 30,
"keepAlivePeriod": 0,
"disablePathMTUDiscovery": false,
"maxIncomingStreams": 1024
}
}
}
}
]
}
```
> `tcp[n].type`: header-custom | fragment | sudoku
The first item in the array is the outermost camouflage layer.
Used together with `raw`, `httpupgrade`, `websocket`, `grpc`, and `xhttp`.
`header-custom`:
`fragment`:
`sudoku`:
> `tcp[n].settings`: header-custom | fragment | sudoku
### header-custom
```json
{
"clients": [
[
{
"delay": 0,
"rand": 0,
"randRange": "0-255",
"type": "",
"packet": []
}
]
],
"servers": [
[
{
"delay": 0,
"rand": 0,
"randRange": "0-255",
"type": "",
"packet": []
}
]
],
"errors": [
[
{
"delay": 0,
"rand": 0,
"randRange": "0-255",
"type": "",
"packet": []
}
]
]
}
```
`clients[n][m].delay`: delay in milliseconds. When it is `0`, the data is sent together with the previous packet.
`clients[n][m].rand`: adds a specified number of random bytes. Conflicts with `packet`.
`clients[n][m].randRange`: range of random-byte values. The default is `0-255`.
`clients[n][m].type`: the type of `packet`. Supported values are `array`, `str`, `hex`, and `base64`. The default is `array`.
`clients[n][m].packet`: adds fixed data. Conflicts with `rand`.
### fragment
```json
{
"packets": "tlshello",
"length": "100-200",
"delay": "10-20",
"maxSplit": "3-6"
}
```
### sudoku
```json
{
"password": "",
"ascii": "",
"customTable": "", // field name is custom_table in the upstream documentation
"customTables": [""], // field name is custom_tables in the upstream documentation
"paddingMin": 0, // field name is padding_min in the upstream documentation
"paddingMax": 0 // field name is padding_max in the upstream documentation
}
```
For the meaning of these fields, see the [upstream documentation](https://github.com/SUDOKU-ASCII/sudoku/blob/main/configs/README.md).
> `udp[n].type`: header-custom | header-dns | header-dtls | header-srtp | header-utp | header-wechat | header-wireguard | mkcp-original | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp
The first item in the array is the outermost camouflage layer.
Used together with `raw` UDP, `kcp`, `hysteria`, and `xhttp` H3.
`header-custom`: always prepended to the packet as a combined header.
`header-dns`: the old mKCP DNS camouflage. Some campus networks permit DNS requests before login, so this adds a DNS header to KCP.
`header-dtls`: the old mKCP DTLS camouflage. It imitates DTLS 1.2 packets. No extra settings.
`header-srtp`: the old mKCP SRTP camouflage. It imitates SRTP packets and tends to look like video-call traffic such as FaceTime. No extra settings.
`header-utp`: the old mKCP uTP camouflage. It imitates uTP packets and tends to look like BitTorrent traffic. No extra settings.
`header-wechat`: the old mKCP WeChat Video camouflage. It imitates WeChat video-call packets. No extra settings.
`header-wireguard`: the old mKCP WireGuard camouflage. It imitates WireGuard packets, though it is not the real WireGuard protocol. No extra settings.
`mkcp-original`: the simple obfuscation that used to be the default in mKCP. You may need it to connect to older mKCP servers. No extra settings.
`mkcp-aes128gcm`: the old mKCP `seed` feature. It uses AES-128-GCM for obfuscation.
`noise`: noise sent before the actual payload.
`salamander`: Salamander obfuscation from Hysteria2.
`sudoku`:
`xdns`: transmits data through DNS queries in a way similar to DNSTT. It performs standard DNS TXT queries to carry payload.
Because of technical limitations, the effective MTU is very small and QUIC is not usable. It is recommended to pair it with mKCP. Recommended MTU values are 130 on the client and 900 on the server.
Since the queries are standard DNS requests, they can be forwarded by any UDP DNS server, although the efficiency may be very poor.
To use this feature, the server must listen on port 53, the proxy protocol must target a DNS server such as `8.8.8.8:53`, and you must own the `domain` used by xdns and point its NS record to the server.
For example, if you own `example.com`, create an A record like `a.example.com` pointing to your server IP, then create an NS record like `t.example.com` pointing to `t.example.com`, and use `t.example.com` as the domain. The A record must not be a subdomain of the NS record.
`xicmp`: requires at least `CAP_NET_RAW`, must be the outermost layer, which means the first array element, and cannot be used together with `udpHop` or `dialerProxy`.
> `udp[n].settings`: header-custom | header-dns | mkcp-aes128gcm | noise | salamander | sudoku | xdns | xicmp
### header-custom
```json
{
"client": [
{
"rand": 0,
"randRange": "0-255",
"type": "",
"packet": []
}
],
"server": [
{
"rand": 0,
"randRange": "0-255",
"type": "",
"packet": []
}
]
}
```
`client[n].rand`: adds a specified number of random bytes. Conflicts with `packet`.
`client[n].randRange`: range of random-byte values. The default is `0-255`.
`client[n].type`: the type of `packet`. Supported values are `array`, `str`, `hex`, and `base64`. The default is `array`.
`client[n].packet`: adds fixed data. Conflicts with `rand`.
### header-dns
```json
{
"domain": "www.example.com"
}
```
### mkcp-aes128gcm
```json
{
"password": "your-password"
}
```
### noise
```json
{
"reset": 0,
"noise": [
{
"rand": "1-8192",
"randRange": "0-255",
"type": "",
"packet": [],
"delay": "10-20"
}
]
}
```
`noise[n].rand`: adds random bytes, or a specified random length of bytes. Conflicts with `packet`.
`noise[n].randRange`: range of random-byte values. The default is `0-255`.
`noise[n].type`: the type of `packet`. Supported values are `array`, `str`, `hex`, and `base64`. The default is `array`.
`noise[n].packet`: adds fixed data. Conflicts with `rand`.
`noise[n].delay`: delay in milliseconds. After sending one noise item, Xray waits for the specified time before sending the next one.
### salamander
```json
{
"password": "your-password"
}
```
### sudoku
```json
{
"password": "",
"ascii": "",
"customTable": "",
"customTables": [""],
"paddingMin": 0,
"paddingMax": 0
}
```
The same meanings as in the TCP version apply here.
### xdns
```json
{
"domain": "www.example.com"
}
```
### xicmp
```json
{
"listenIp": "0.0.0.0",
"id": 0
}
```
`listenIp`: the IP address to listen on.
`id`: when multiple clients share the same IP, it is recommended that the server keep this value at `0`.
> `quicParams`: [quicParamsObject](#quicParams)
### quicParams
```json
{
"congestion": "force-brutal",
"debug": false,
"brutalUp": "60 mbps",
"brutalDown": 0,
"udpHop": {
"ports": "20000-50000",
"interval": "5-10"
},
"initStreamReceiveWindow": 8388608,
"maxStreamReceiveWindow": 8388608,
"initConnectionReceiveWindow": 20971520,
"maxConnectionReceiveWindow": 20971520,
"maxIdleTimeout": 30,
"keepAlivePeriod": 0,
"disablePathMTUDiscovery": false,
"maxIncomingStreams": 1024
}
```
Used for QUIC parameter tuning in XHTTP H3 and Hysteria.
> `congestion`: reno | bbr | brutal | force-brutal
Congestion-control algorithm. Hysteria defaults to `brutal`. XHTTP H3 defaults to `bbr`.
`reno` and `bbr` are well-known algorithms.
`brutal` negotiates a fixed packet-sending rate with the peer, or falls back to BBR. It is supported only by Hysteria, because XHTTP has no negotiation mechanism.
`force-brutal` is the same as `brutal`, but it forcibly uses the fixed upstream rate from `brutalUp` and ignores peer negotiation.
> `debug`: false | true
Enable logging for the `bbr` and `brutal` congestion-control implementations.
> `brutalUp`: string
> `brutalDown`: string
Upload and download rate limits. The default value is `0`.
The format is user-friendly and supports common bit-rate forms such as `1000000`, `100kb`, `20 mb`, `100 mbps`, `1g`, and `1 tbps`. It is case-insensitive, spaces are optional, and when no unit is given the default is `bps`. The value must not be lower than 65535 bps.
The negotiation behavior is the same as Hysteria Brutal:
The server-side value limits the highest Brutal-mode rate the client is allowed to choose. `0` means the client is not limited by the server.
When the client value is `0`, it uses BBR mode. When it is non-zero, it uses Brutal mode and is still constrained by the server-side limit.
Remember the directions are relative: the server's upload is the client's download, and the server's download is the client's upload.
> `udpHop`: {"ports": string, "interval": number}
UDP port-hopping configuration.
`ports` specifies the hopping range. It can be a single numeric string like `"1234"`, or a range like `"1145-1919"`, which means ports 1145 through 1919. Commas can be used to combine ranges, for example `11,13,15-17`.
`interval` is the port-hopping interval in seconds. The minimum is 5. The default is 30 seconds.
> `initStreamReceiveWindow`: number
> `maxStreamReceiveWindow`: number
> `initConnectionReceiveWindow`: number
> `maxConnectionReceiveWindow`: number
These four are low-level QUIC window parameters. **Do not change them unless you fully understand what you are doing.** If you do need to change them, it is recommended to keep the ratio between stream and connection receive windows at 2:5.
> `maxIdleTimeout`: number
Maximum idle timeout in seconds. This is how long the server waits without receiving any client data before closing the connection. The supported range is 4 to 120 seconds. The default is 30 seconds.
> `keepAlivePeriod`: number
QUIC KeepAlive interval in seconds. The supported range is 2 to 60 seconds. Disabled by default.
> `disablePathMTUDiscovery`: bool
Whether to disable path MTU discovery.
Other implementations forcibly disable this on systems other than Linux, Windows, and Darwin, while Xray does not enforce that. If your operating system is outside those three, you may need to disable it manually.
> `maxIncomingStreams`: number
Server-side only. If set, it must not be smaller than `8`.
+2 -2
View File
@@ -7,9 +7,9 @@ Its design is not recommended for standalone use; instead, it is intended to wor
**It is recommended to switch to [XHTTP](https://github.com/XTLS/Xray-core/discussions/4113) to avoid significant traffic fingerprints such as HTTPUpgrade's "ALPN is http/1.1".**
:::
## HttpUpgradeObject
## HTTPUpgradeObject
`HttpUpgradeObject` corresponds to the `httpupgradeSettings` item in [`StreamSettingsObject`](../transport.md#streamsettingsobject).
`HTTPUpgradeObject` corresponds to the `httpupgradeSettings` item in [`StreamSettingsObject`](../transport.md#streamsettingsobject).
```json
{
+14 -2
View File
@@ -1,6 +1,8 @@
# Xray Transport Layer
# Xray Transport Configuration
Xray supports the following transport layers:
Xray supports the following transport configuration categories:
## Transport Methods
- [RAW](raw.md)
- [XHTTP: Beyond REALITY](xhttp.md)
@@ -9,3 +11,13 @@ Xray supports the following transport layers:
- [WebSocket](websocket.md)
- [HTTPUpgrade](httpupgrade.md)
- [Hysteria](hysteria.md)
## Transport Security
- [REALITY](reality.md)
- [TLS](tls.md)
## Additional Configuration
- [FinalMask](finalmask.md)
- [Sockopt](sockopt.md)
+1 -1
View File
@@ -37,7 +37,7 @@ Please ensure that the firewall configuration on the host is correct.
```
::: tip
The `header` and `seed` fields have been removed. Please use [FinalMask](../transport.md#finalmaskobject) for configuration.
The `header` and `seed` fields have been removed. Please use [FinalMask](./finalmask.md#finalmaskobject) for configuration.
Additionally, the previously default mKCP obfuscation has also been removed. To connect to a legacy server, you need to configure `mkcp-original` in FinalMask.
:::
+203
View File
@@ -0,0 +1,203 @@
# REALITY
REALITY is a modified form of TLS that uses the appearance and handshake characteristics of a target site as camouflage.
:::: tip
REALITY is currently one of the most secure transport-security schemes, and from the outside its traffic shape is consistent with ordinary web browsing.<br>
Enabling REALITY together with a suitable XTLS Vision flow-control mode can improve performance by several times or even more than ten times.
::: details For developers
REALITY only modifies TLS. On the client side it mainly requires slight handling around a fully random session ID and custom certificate verification, and in theory it is broadly compatible with most TLS combinations.
For more information, see the [REALITY project](https://github.com/XTLS/REALITY).
:::
::::
## RealityObject
`RealityObject` corresponds to the `realitySettings` item in [`StreamSettingsObject`](../transport.md#streamsettingsobject).
```json
{
// outbound example; also applies to inbound
"outbounds": [
{
// ...
"streamSettings": {
"security": "reality",
"realitySettings": {
// [!code focus:28]
// Inbound (server-side) settings
"show": false,
"target": "example.com:443",
"xver": 0,
"serverNames": ["example.com", "www.example.com"],
"privateKey": "",
"minClientVer": "",
"maxClientVer": "",
"maxTimeDiff": 0,
"shortIds": ["", "0123456789abcdef"],
"mldsa65Seed": "",
"limitFallbackUpload": {
"afterBytes": 0,
"bytesPerSec": 0,
"burstBytesPerSec": 0
},
"limitFallbackDownload": {
"afterBytes": 0,
"bytesPerSec": 0,
"burstBytesPerSec": 0
},
// Outbound (client-side) settings
"serverName": "",
"fingerprint": "chrome",
"password": "",
"shortId": "",
"mldsa65Verify": "",
"spiderX": ""
}
}
}
]
}
```
> `show`: true | false
When set to `true`, debug information is printed.
::: tip
The following fields are for **inbound** (**server-side**) configuration.
:::
> `target`: string
Required. The format is the same as VLESS fallback [dest](../features/fallback.md#fallbackobject).
The old name was `dest`. In current versions the two fields are aliases.
If `target` supports the post-quantum key-exchange algorithm X25519MLKEM768, the REALITY client also automatically uses that post-quantum algorithm for key negotiation. You can check support with `xray tls ping cloudflare.com`, replacing the domain with your `target` and optionally including a port.
The core decides whether the current configuration is client-side or server-side based on whether this field exists. Do not fill it in on the client side, or it will cause incorrect detection.
::: warning
For camouflage reasons, Xray **directly forwards** traffic that fails authentication, meaning traffic that is not a valid REALITY request, to `target`.
If the IP address of the `target` site is special, for example a site behind Cloudflare CDN, your server effectively becomes a port forwarder for Cloudflare and may be abused after scanning.
To avoid that, consider placing Nginx or something similar in front to filter out unwanted SNI values.
You can also consider configuring `limitFallbackUpload` and `limitFallbackDownload` to limit the rate.
:::
> `xver`: number
Optional. The format is the same as VLESS fallback [xver](../features/fallback.md#fallbackobject).
> `serverNames`: [string]
Required. The list of `serverName` values allowed for clients. `*` wildcards are not supported.
Usually this should stay consistent with `target`. In practice, valid values are any SNI accepted by the server according to the behavior of `target`, and typically refer to the [SAN](https://en.wikipedia.org/wiki/Subject_Alternative_Name) values on the returned certificate.
The list may contain an empty string `""`, meaning connections without SNI are accepted. Using this feature does not require `target` to have an IP certificate; you only need to ensure that it does not reject a Client Hello without SNI. When using this feature, the client-side `serverName` cannot be empty and should instead be filled with any valid IP address as a placeholder.
You can use `xray tls ping` to observe how the server responds to requests without SNI.
> `privateKey`: string
Required. Generate it with `./xray x25519`.
> `minClientVer`: string
Optional. Minimum Xray client version, in `x.y.z` format.
> `maxClientVer`: string
Optional. Maximum Xray client version, in `x.y.z` format.
> `maxTimeDiff`: number
Optional. Maximum allowed time difference, in milliseconds.
> `shortIds`: [string]
Required. The list of available `shortId` values for clients, which can be used to distinguish different clients.
See the `shortId` field for the required format.
If the list contains an empty string, the client-side `shortId` may also be empty.
> `mldsa65Seed`: string
Server-only. The private key used to add an extra post-quantum signature to the certificate sent to the REALITY client, using ML-DSA-65. If a quantum computer capable of breaking x25519 ever exists, leaked `password` material could allow MITM attacks; this feature is intended to prevent that future risk.
Generate the keypair with `xray mldsa65`. After the server is configured with the private key, the signature is added only as a certificate extension, so it does not affect old clients or clients that do not enable this feature.
Note that after enabling this feature, the certificate returned by `target` **must** be longer than 3500 bytes, because the post-quantum signature makes the temporary REALITY certificate larger. To avoid becoming a fingerprint, the `target` certificate also needs to be large. You can inspect this with `xray tls ping example.com`. For fully post-quantum security, `target` also needs to support the X25519MLKEM768 post-quantum key exchange, which can be checked with the same command.
> `limitFallbackUpload` / `limitFallbackDownload`
::: warning
The best practice for REALITY is still to borrow certificates from the same ASN, so in most cases you do not need this feature. It is only worth considering when you are forced to borrow certificates from something like a free CDN such as Cloudflare and want to avoid your server becoming an acceleration node for others.
Fallback rate limiting is itself a fingerprint and is not recommended. If you are developing a panel or one-click script, make sure these parameters are randomized.
:::
::: tip
`limitFallbackUpload` and `limitFallbackDownload` are optional and can rate-limit fallback connections that fail verification. `bytesPerSec` defaults to `0`, which means disabled.
Mechanism: for each unverified fallback connection, the rate-limiting algorithm starts after `afterBytes` bytes have been transmitted.
The algorithm uses a token bucket. The bucket capacity is `burstBytesPerSec`. Each transmitted byte consumes one token. The bucket starts full with `burstBytesPerSec` tokens.
Every second the bucket is refilled with `bytesPerSec` tokens until full.
Example: `afterBytes=10485760`, `burstBytesPerSec=5242880`, `bytesPerSec=1048576` means traffic is limited to 1 MB/s after 15 MB has been transmitted. If transmission pauses, it can burst back up to 5 MB/s after 5 seconds and then settle again at 1 MB/s.
Guidance: if `afterBytes` and `burstBytesPerSec` are too large, rate limiting has little practical effect. If `bytesPerSec` and `burstBytesPerSec` are too small, the behavior becomes easy to detect.
These parameters should be chosen with the resource size of the borrowed site in mind. If you do not want bursts, set `burstBytesPerSec` to `0`.
:::
> `afterBytes`: number
Optional. Starts rate limiting fallback REALITY connections only after the specified number of bytes has been transmitted. The default is `0`.
> `bytesPerSec`: number
Optional. Base rate limit for fallback REALITY connections, in bytes per second. The default is `0`, meaning disabled.
> `burstBytesPerSec`: number
Optional. Burst rate limit for fallback REALITY connections, in bytes per second. It takes effect when it is greater than `bytesPerSec`.
::: tip
The following fields are for **outbound** (**client-side**) configuration.
:::
> `serverName`: string
One of the server-side `serverNames`.
The client can also set this to any IP address. In that case Xray sends a Client Hello without an SNI extension. To use this feature, the server-side `serverNames` must contain an empty string `""`.
> `fingerprint`: string
Required. Same as [TLSObject](./tls.md#tlsobject). Note that `unsafe`, which disables uTLS for TLS, is not supported here because REALITY relies on that library to manipulate lower-level TLS parameters.
> `shortId`: string
One of the server-side `shortIds`.
Its length is 8 bytes, which means up to 16 hexadecimal characters in the range `0` to `f`. It may be shorter than 16 characters, and the core pads trailing zeroes automatically, but the number of characters must be **even**, because one byte is represented by two hex digits.
For example, `aa1234` is automatically expanded to `aa12340000000000`, but `aaa1234` causes an error.
Zero is also even, so if the server-side `shortIds` contains an empty string `""`, the client-side value may also be empty.
> `password`: string
Required. The public key corresponding to the server private key. Generate it with `./xray x25519 -i "server private key"`. The old field name was `publicKey`, but it was renamed to avoid misunderstanding. It is indeed an x25519 public key, but in the REALITY design it is held by the client and should not be treated as something to publish openly.
> `mldsa65Verify`
Optional. The public key used for `mldsa65` signature verification. When non-empty, Xray uses it to verify the certificate returned by the server. See the description of `mldsa65Seed` for details.
> `spiderX`: string
Initial crawler path and parameters. It is recommended that each client use a different value.
+298
View File
@@ -0,0 +1,298 @@
# Sockopt
Sockopt is used to configure low-level network behavior.
It can be used to tune transparent proxying, DNS resolution strategy, and many other socket-level options.
## SockoptObject
`SockoptObject` corresponds to the `sockopt` item in [`StreamSettingsObject`](../transport.md#streamsettingsobject).
```json
{
// outbound example; also applies to inbound
"outbounds": [
{
// ...
"streamSettings": {
"sockopt": {
// [!code focus:18]
"mark": 0,
"tcpMaxSeg": 1440,
"tcpFastOpen": false,
"tproxy": "off",
"domainStrategy": "AsIs",
"happyEyeballs": {},
"dialerProxy": "",
"acceptProxyProtocol": false,
"tcpKeepAliveInterval": 0,
"tcpKeepAliveIdle": 300,
"tcpUserTimeout": 10000,
"tcpcongestion": "bbr",
"interface": "wg0",
"V6Only": false,
"tcpWindowClamp": 600,
"tcpMptcp": false,
"addressPortStrategy": "",
"customSockopt": []
}
}
}
]
}
```
> `mark`: number
An integer. When non-zero, outbound connections are marked with this value through `SO_MARK`.
- Linux only.
- Requires `CAP_NET_ADMIN`.
> `tcpMaxSeg`: number
Used to set the maximum segment size of TCP packets.
> `tcpFastOpen`: true | false | number
Whether to enable [TCP Fast Open](https://en.wikipedia.org/wiki/TCP_Fast_Open).
When set to `true` or a positive integer, TFO is enabled. When set to `false` or a negative value, TFO is forcibly disabled. When the field is absent or `0`, the system default is used. This option is available for both inbound and outbound.
- It is only available on the following operating systems or later:
- Linux 3.16: requires the kernel parameter `net.ipv4.tcp_fastopen`. This parameter is a bitmap where `0x1` allows the client side and `0x2` allows the server side. The default is `0x1`. If the server must enable TFO, set it to `0x3`.
- ~~Windows 10 (1607)~~, but the implementation is incorrect
- Mac OS 10.11 / iOS 9, needs testing
- FreeBSD 10.3 on server side / 12.0 on client side: requires `net.inet.tcp.fastopen.server_enabled=1` and `net.inet.tcp.fastopen.client_enabled=1`, needs testing
- For inbound, a positive integer here means the [maximum number of pending TFO connection requests](https://tools.ietf.org/html/rfc7413#section-5.1). **Not every operating system supports setting this here**:
- Linux / FreeBSD: the positive integer is used as the limit. The maximum accepted value is 2147483647. If set to `true`, the value becomes `256`. On Linux, `net.core.somaxconn` also caps it, so if you exceed `somaxconn`, raise that as well.
- Mac OS: `true` or a positive integer only means enabling TFO. The backlog must be configured separately via `net.inet.tcp.fastopen_backlog`.
- Windows: `true` or a positive integer only means enabling TFO.
- For outbound, `true` or a positive integer simply means enabling TFO on any supported OS.
> `tproxy`: "redirect" | "tproxy" | "off"
Whether to enable transparent proxying. Linux only.
- `"redirect"`: transparent proxy in Redirect mode, supporting all IPv4 and IPv6 TCP connections
- `"tproxy"`: transparent proxy in TProxy mode, supporting all IPv4 and IPv6 TCP and UDP connections
- `"off"`: disable transparent proxying
Transparent proxying requires root or `CAP_NET_ADMIN`.
::: danger
When [Dokodemo-door](../inbounds/tunnel.md) has `followRedirect` set to `true`, and `tproxy` is empty in Sockopt, the `tproxy` value is set to `"redirect"`.
:::
> `domainStrategy`: "AsIs"<br>
> "UseIP" | "UseIPv6v4" | "UseIPv6" | "UseIPv4v6" | "UseIPv4"<br>
> "ForceIP" | "ForceIPv6v4" | "ForceIPv6" | "ForceIPv4v6" | "ForceIPv4"
The default value is `"AsIs"`.
When the target address is a domain name, this field controls how outbound connections resolve and use that target:
- With `"AsIs"`, Xray does not specially handle the domain name. In the end it uses Go's built-in dialer directly. The priority is fixed to the RFC 6724 default and does not follow configurations such as `gai.conf`, so in practice IPv6 is usually preferred.
- With any other value, Xray uses the Xray-core [built-in DNS server](../dns.md) for resolution. If there is no `DNSObject`, system DNS is used. If multiple IP addresses match, the core randomly picks one target IP.
- `"IPv4"` means try IPv4 only. `"IPv4v6"` means try IPv4 or IPv6, but for dual-stack domains prefer IPv4. The same logic applies to the IPv6-first variants.
- When built-in DNS also sets `"queryStrategy"`, the actual behavior is the intersection of the two settings. Only IP types included in both are resolved. For example, `"queryStrategy": "UseIPv4"` together with `"domainStrategy": "UseIP"` behaves the same as `"domainStrategy": "UseIPv4"`.
- When using a `"Use"` option, Xray falls back to `"AsIs"` if the resolution result does not match the requested family, such as a domain that only has IPv4 while using `UseIPv6`.
- When using a `"Force"` option, the connection fails outright if the resolution result does not match the requested family.
::: tip TIP
When using `"UseIP"` or `"ForceIP"`, and [OutboundObject](../outbound.md#outboundobject) specifies `sendThrough`, the core automatically infers whether IPv4 or IPv6 is needed from the local address. If you manually force a single IP family, such as `UseIPv4`, but it conflicts with `sendThrough`, the connection fails.
:::
::: danger
Improper use of this feature can create an infinite loop.
Short version: connecting to the server needs a DNS result, but completing the DNS query also needs to connect to the server.
> Tony: which came first, the chicken or the egg?
Detailed explanation:
1. Trigger condition: the proxy server is `proxy.com`, and the built-in DNS server is enabled in non-Local mode.
2. Before Xray establishes a TCP connection to `proxy.com`, it queries `proxy.com` through the built-in DNS server.
3. The built-in DNS server connects to `dns.com` and sends a query to obtain the IP of `proxy.com`.
4. Bad routing rules cause the request sent in step 3 to be proxied through `proxy.com`.
5. Xray now tries to establish another TCP connection to `proxy.com`.
6. Before doing that, it again queries `proxy.com` through the built-in DNS server.
7. The built-in DNS server reuses the connection from step 3 and sends the new query.
8. The problem appears: the connection from step 3 is waiting for the query result from step 7, while step 7 cannot finish until the connection from step 3 is fully established.
9. Good game.
Possible solutions:
- Fix the traffic split of the built-in DNS server.
- Use hosts.
- ~~If you still do not know how to solve it, do not use this feature.~~
So this feature is **not recommended** for inexperienced users unless they understand the routing implications.
:::
> `dialerProxy`: ""
An outbound identifier. When non-empty, the specified outbound is used to establish the connection. It can be used for chained forwarding that still respects transport configuration.
::: danger
This option is incompatible with `ProxySettingsObject.Tag`.
:::
> `acceptProxyProtocol`: true | false
Inbound-only. Controls whether PROXY protocol is accepted.
[PROXY protocol](https://www.haproxy.org/download/2.2/doc/proxy-protocol.txt) is used to pass the real source IP and port. If you do not know what it is, ignore this option.
Common reverse proxies such as HAProxy and Nginx can be configured to send it, and VLESS fallback `xver` can also send it.
When set to `true`, the peer must send PROXY protocol v1 or v2 immediately after the underlying TCP connection is established, otherwise the connection is closed.
> `tcpKeepAliveIdle`: number
TCP idle threshold in seconds. Once a TCP connection has been idle for this long, Keep-Alive probes begin.
For outbound, Xray uses Chrome's default values, where both idle and interval are 45 seconds. Setting either this field or `tcpKeepAliveInterval` to a negative value disables that default keepalive; a positive value overrides it.
For inbound, Keep-Alive is disabled by default. It becomes enabled when either this field or `tcpKeepAliveInterval` is non-zero. If only one is set, the other follows the operating-system default.
> `tcpKeepAliveInterval`: number
Time interval in seconds between Keep-Alive probes after TCP enters Keep-Alive state. The rest of the behavior is described above.
> `tcpUserTimeout`: number
In milliseconds. See: https://github.com/grpc/proposal/blob/master/A18-tcp-user-timeout.md
> `tcpcongestion`: ""
TCP congestion-control algorithm. Linux only.
When unset, the operating-system default is used.
::: tip Common algorithms
- `bbr` (recommended)
- `cubic`
- `reno`
:::
::: tip
Run `sysctl net.ipv4.tcp_congestion_control` to see the current system default.
:::
> `interface`: ""
Bind the outbound connection to a specific network-interface name. Supported on Linux, iOS, Mac OS, and Windows.
> `V6Only`: true | false
When set to `true`, listening on `::` accepts only IPv6 connections. Linux only.
> `tcpWindowClamp`: number
Bind the advertised TCP window size to this value. The kernel chooses the larger value between this and `SOCK_MIN_RCVBUF / 2`.
> `tcpMptcp`: true | false
The default value is `false`. When set to `true`, [Multipath TCP](https://en.wikipedia.org/wiki/Multipath_TCP) is enabled. This is client-only, because starting with Go 1.24 MPTCP is enabled by default when listening. It currently requires Linux kernel 5.6 or later.
> `tcpNoDelay`: true | false
This field has been removed because Go enables TCP no delay by default. If you want to disable it, do so through `customSockopt`.
> `addressPortStrategy`: "none" | "SrvPortOnly" | "SrvAddressOnly" | "SrvPortAndAddress" | "TxtPortOnly" | "TxtAddressOnly" | "TxtPortAndAddress"
Use SRV records or TXT records to specify the target address and or port used by outbound. The default value is `none`, which disables the feature.
These lookups go through system DNS rather than Xray's built-in DNS. The queried name is the outbound domain name. If the lookup fails, the request is sent using the original address and port.
`Srv*` means querying SRV records in their standard format. `Txt*` means querying TXT records in a format such as `127.0.0.1:80`.
`PortOnly` resets only the port. `AddressOnly` resets only the address. `PortAndAddress` resets both.
This option takes effect before `domainStrategy` inside `sockopt`. After the address is rewritten, it is still resolved according to `domainStrategy`, if any. However, it takes effect after `Freedom`'s own `domainStrategy`, so if that one already resolved the domain to an IP, this option no longer works.
As a practical consequence, if ordinary domain traffic is sent into a `Freedom` outbound with `AsIs`, enabling this field makes the core try to resolve and rewrite the address and port, for example by querying `google.com` for SRV records.
> `customSockopt`: []
An array for advanced users to specify any needed socket option. In theory, all connection-related settings above can be expressed here, and you can also set other socket options that exist but are not exposed directly by the core. It currently supports Linux, Windows, and Darwin. The example below is equivalent to `"tcpcongestion": "bbr"`.
Make sure you understand socket programming before using it.
```json
"customSockopt": [
{
"system": "linux",
"type": "str",
"level": "6",
"opt": "13",
"value": "bbr"
}
]
```
> `system`: ""
Optional. Restricts the option to a specific operating system. If the current system does not match, the option is skipped. Supported values are `linux`, `windows`, and `darwin`, all in lowercase. If left empty, the option is applied directly.
> `type`: ""
Required. The value type to set. Currently `int` and `str` are supported.
> `level`: ""
Optional. Protocol level. The default is `6`, which means TCP.
> `opt`: ""
The option number to operate on, in decimal. In the example above, `13` is the decimal form of `TCP_CONGESTION`, whose hexadecimal value is `0xd`.
> `value`: ""
The value to set. In the example above, the value is `bbr`.
When `type` is `int`, the value must be a decimal number.
> `happyEyeballs`: [HappyEyeballsObject](#happyeyeballsobject)
An RFC 8305 Happy Eyeballs implementation, TCP only. When the target is a domain name, it races the resolved addresses and chooses the first successful one. It only works when `Sockopt.domainStrategy` is not `AsIs`.
Note that `UseIPv4v6` and `ForceIPv4v6` effectively reduce the usable list to IPv4 and only query IPv6 if IPv4 resolution fails. That is not recommended. Prefer `UseIP` or `ForceIP` together with `HappyEyeballs.interleave`.
::: warning
Do not use this together with the `domainStrategy` on a `Freedom` outbound, because then `Sockopt` only sees the final IP after replacement.
:::
### HappyEyeballsObject
```json
"happyEyeballs": {
"tryDelayMs": 250,
"prioritizeIPv6": false,
"interleave": 1,
"maxConcurrentTry": 4
}
```
> `tryDelayMs`: number
Delay between each racing attempt, in milliseconds. The default is `0`, which disables the feature. A recommended value is `250`.
> `prioritizeIPv6`: bool
Controls which IP family comes first after sorting. The default is `false`, meaning IPv4 comes first.
> `interleave`: number
The RFC 8305 `First Address Family Count`. The default value is `1`. It controls how IPv4 and IPv6 addresses are interleaved.
For example, the waiting dial queue may be ordered as `46464646` when this is `1`, or `44664466` when it is `2`, where `6` means an IPv6 address and `4` means an IPv4 address.
> `maxConcurrentTry`: number
Maximum number of concurrent attempts. This prevents the core from launching too many connections when a domain resolves to many addresses and all of them fail. The default is `4`. Setting it to `0` disables Happy Eyeballs.
+338
View File
@@ -0,0 +1,338 @@
# TLS
TLS is a common transport-security mechanism.
It can be used to configure transport-layer encryption, certificate verification, client fingerprints, and related certificate settings.
## TLSObject
`TLSObject` corresponds to the `tlsSettings` item in [`StreamSettingsObject`](../transport.md#streamsettingsobject).
```json
{
// outbound example; also applies to inbound
"outbounds": [
{
// ...
"streamSettings": {
"security": "tls",
"tlsSettings": {
// [!code focus:18]
"serverName": "xray.com",
"verifyPeerCertByName": "",
"rejectUnknownSni": false,
"allowInsecure": false,
"alpn": ["h2", "http/1.1"],
"minVersion": "1.2",
"maxVersion": "1.3",
"cipherSuites": "Enter the cipher suite names you need here, separated by :",
"certificates": [],
"disableSystemRoot": false,
"enableSessionResumption": false,
"fingerprint": "",
"pinnedPeerCertSha256": "",
"curvePreferences": [""],
"masterKeyLog": "",
"echServerKeys": "",
"echConfigList": "",
"echSockopt": {}
}
}
}
]
}
```
> `serverName`: string
Server name. The server certificate's SAN must contain this value. It can be a domain name or an IP address. If it is a domain name, it will be sent in the SNI extension of the Client Hello. IP addresses will not send the SNI extension, because SNI does not allow IP addresses. If you fill in an IPv6 address, wrap it in `[]`.
When left empty, the value in `address` is used automatically if that value is a domain name.
Special value `"FromMitM"` causes Xray to use the SNI extracted from TLS decrypted by a `dokodemo-door` inbound.
> `verifyPeerCertByName`: string
Client-only. The SNI used for certificate verification. Multiple domain names can be separated with `,`; it is enough for any one SAN in the certificate to match one of them. This overrides the `serverName` used for verification and is intended for special cases such as domain fronting.
Special value `"FromMitM"` causes Xray to additionally include the SNI extracted from TLS decrypted by a `dokodemo-door` inbound.
> `rejectUnknownSni`: bool
When set to `true`, the server rejects the TLS handshake if the received SNI does not match the certificate domain. The default is `false`.
> `alpn`: [string]
An array of strings that specifies the ALPN values used during TLS handshake. The default value is `["h2", "http/1.1"]`.
Special value `["FromMitM"]`, when it is the only element, causes outbound TLS to reuse the ALPN from the TLS connection decrypted by a `dokodemo-door` inbound.
> `minVersion`: string
`minVersion` is the minimum acceptable TLS version.
> `maxVersion`: string
`maxVersion` is the maximum acceptable TLS version.
> `cipherSuites`: string
`cipherSuites` configures the list of supported cipher suites, separated by `:`.
You can find Go cipher-suite names and descriptions [here](https://golang.org/src/crypto/tls/cipher_suites.go#L500) or [here](https://golang.org/src/crypto/tls/cipher_suites.go#L44).
::: danger
These two options are not required in normal cases and usually do not affect security. If left unset, Go chooses automatically according to the platform. If you are not familiar with them, do not configure them.
:::
> `allowInsecure`: true | false
Whether to allow insecure connections. Client-only. The default value is `false`.
When set to `true`, Xray does not verify the validity of the TLS certificate provided by the remote host.
::: danger
~~For security reasons, this option should not be set to `true` in real deployments, otherwise you may be vulnerable to man-in-the-middle attacks.~~
This option is deprecated. Use `pinnedPeerCertSha256` to specify the certificate manually instead.
:::
> `disableSystemRoot`: true | false
Whether to disable the operating system's built-in CA certificates. The default value is `false`.
When set to `true`, Xray uses only the certificates specified in `certificates` during TLS handshake. When set to `false`, Xray uses only the operating system's built-in CA certificates during TLS handshake.
> `enableSessionResumption`: true | false
Whether to enable session resumption. It is disabled by default, and session resumption is only attempted when both the server and the client enable it.
If negotiation succeeds, certificates do not need to be transmitted during the handshake. This saves a tiny amount of handshake time, which is usually negligible.
Note that this is not TLS 0-RTT. `gotls` does not support that feature yet, so this does not reduce TLS handshake RTT.
> `fingerprint`: string
This parameter configures the fingerprint of the `TLS Client Hello`. The default value is `chrome`. To revert to native Go TLS, set it to `unsafe`. When enabled, Xray uses the uTLS library to **simulate** a TLS fingerprint, or generates one randomly. Three configuration styles are supported:
1. TLS fingerprints of the latest versions of common browsers, including:
- `"chrome"`
- `"firefox"`
- `"safari"`
- `"ios"`
- `"android"`
- `"edge"`
- `"360"`
- `"qq"`
2. Automatically generate a fingerprint when Xray starts:
- `"random"`: randomly choose one from newer browser versions
- `"randomized"`: generate a completely random unique fingerprint that fully supports TLS 1.3 with X25519
3. Use native uTLS hello names such as `"HelloRandomizedNoALPN"` or `"HelloChrome_106_Shuffle"`. See the full list in the [uTLS library](https://github.com/refraction-networking/utls/blob/master/u_common.go#L434).
::: tip
This feature only **simulates** the `TLS Client Hello` fingerprint. Behavior and other fingerprints remain the same as Go. If you want more complete browser-like TLS fingerprints and behavior, use [Browser Dialer](./websocket.md#browser-dialer).
:::
::: tip
When this feature is enabled, some TLS options that affect TLS fingerprints are overridden by the uTLS library and stop taking effect, such as ALPN.
The parameters still passed through are:
`"serverName" "disableSystemRoot" "pinnedPeerCertSha256" "masterKeyLog"`
:::
> `pinnedPeerCertSha256`: string
Used to specify the SHA-256 hash of the remote server certificate. It uses hexadecimal encoding and is case-insensitive, for example `e8e2d387fdbffeb38e9c9065cf30a97ee23c0e3d32ee6f78ffae40966befccc9`. Multiple hash values can be joined with `,`, and verification succeeds if any one of them matches.
This encoding matches the SHA-256 certificate fingerprint shown by the Chrome certificate viewer and the SHA-256 certificate fingerprint format used on crt.sh. You can compute it with `xray tls hash --cert <cert.pem>`, or with `openssl x509 -noout -fingerprint -sha256 -in cert.pem`, including its colon-separated format. `xray tls ping` also prints the SHA-256 hash of the remote certificate.
This check overrides normal certificate validation. There are two cases:
- If the core finds that the matching hash belongs to a leaf certificate, verification succeeds immediately.
- If the core finds that the matching hash belongs to a CA certificate, whether root or intermediate, it uses the value in `serverName` to verify that the leaf certificate is signed by that CA.
> `certificates`: \[ [CertificateObject](#certificateobject) \]
Certificate list. Each item represents one certificate. A full chain is recommended.
::: tip
If you want an A or A+ rating from tools such as ssllibs or myssl, see [this discussion](https://github.com/XTLS/Xray-core/discussions/56#discussioncomment-215600).
:::
> `curvePreferences`: [string]
An array of strings that specifies the curves supported when performing ECDHE during TLS handshake. Supported values are:
```text
CurveP256
CurveP384
CurveP521
X25519
X25519MLKEM768
SecP256r1MLKEM768*
SecP384r1MLKEM1024*
```
\*: not supported by uTLS
As of Go 1.26, the default includes all curves above. Changing the order does not force either side to prefer a specific curve; the actual curve is negotiated by the key-exchange mechanism itself.
> `masterKeyLog`: string
Path to a `(Pre)-Master-Secret` log file. It can be used by software such as Wireshark to decrypt TLS connections sent by Xray.
> `echServerKeys`: string
Server-only parameter used to enable Encrypted Client Hello on the server.
Use `xray tls ech --serverName example.com` to generate an ECH Server Key and its corresponding Config. `example.com` is the SNI exposed to the outside when SNI is encrypted, and can be any value. The Server Key includes the ECHConfig. If you lose the client-side Config, you can recover it with `xray tls ech -i "your server key"`. You can publish it in a DNS HTTPS record; see the format [here](https://dns.google/query?name=encryptedsni.com&rr_type=HTTPS) or in RFC 9460.
Note that after ECH is configured, the server still accepts normal non-ECH connections.
> `echConfigList`: string
Client-only parameter that configures ECHConfig. A non-empty value means the client enables Encrypted Client Hello. Two formats are supported.
The first is a fixed ECHConfig string, for example:
`"AF7+DQBaAAAgACA51i3Ssu4wUMV4FNCc8iRX5J+YC4Bhigz9sacl2lCfSQAkAAEAAQABAAIAAQADAAIAAQACAAIAAgADAAMAAQADAAIAAwADAAtleGFtcGxlLmNvbQAA"`
The second is querying a DNS server. For example, when using a CDN, you can dynamically obtain ECHConfig from HTTPS records. If a valid ECH Config is obtained, Xray obeys the TTL returned by the server. The query target is the configured SNI, or the configured server domain name if SNI is empty and the target is a domain name.
The basic format is `"udp://1.1.1.1"`, meaning query ECHConfig through UDP DNS 1.1.1.1. You can also use `"https://1.1.1.1/dns-query"` or `h2c://` to query via DoH or h2c. All of these support an explicit port, such as `udp://1.1.1.1:53`. If omitted, the default port is 53 or 443 according to the protocol.
You can also specify a dedicated domain for the ECHConfig lookup in the form `"example.com+https://1.1.1.1/dns-query"`. In that case Xray forcibly uses the ECHConfig from the DNS records of `example.com` for the connection. This is useful if you want to obtain ECHConfig from DNS without exposing that you are querying the target domain's HTTPS record, or when you do not want to publish HTTPS records under that domain.
> `echSockopt`: [SockoptObject](./sockopt.md#sockoptobject)
Adjusts the underlying socket options of the connection used when querying DNS for ECH records.
### CertificateObject
```json
{
"ocspStapling": 0,
"oneTimeLoading": false,
"usage": "encipherment",
"buildChain": false,
"certificateFile": "/path/to/certificate.crt",
"keyFile": "/path/to/key.key",
"certificate": [
"--BEGIN CERTIFICATE--",
"MIICwDCCAaigAwIBAgIRAO16JMdESAuHidFYJAR/7kAwDQYJKoZIhvcNAQELBQAw",
"ADAeFw0xODA0MTAxMzU1MTdaFw0xODA0MTAxNTU1MTdaMAAwggEiMA0GCSqGSIb3",
"DQEBAQUAA4IBDwAwggEKAoIBAQCs2PX0fFSCjOemmdm9UbOvcLctF94Ox4BpSfJ+",
"3lJHwZbvnOFuo56WhQJWrclKoImp/c9veL1J4Bbtam3sW3APkZVEK9UxRQ57HQuw",
"OzhV0FD20/0YELou85TwnkTw5l9GVCXT02NG+pGlYsFrxesUHpojdl8tIcn113M5",
"pypgDPVmPeeORRf7nseMC6GhvXYM4txJPyenohwegl8DZ6OE5FkSVR5wFQtAhbON",
"OAkIVVmw002K2J6pitPuJGOka9PxcCVWhko/W+JCGapcC7O74palwBUuXE1iH+Jp",
"noPjGp4qE2ognW3WH/sgQ+rvo20eXb9Um1steaYY8xlxgBsXAgMBAAGjNTAzMA4G",
"A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA",
"MA0GCSqGSIb3DQEBCwUAA4IBAQBUd9sGKYemzwPnxtw/vzkV8Q32NILEMlPVqeJU",
"7UxVgIODBV6A1b3tOUoktuhmgSSaQxjhYbFAVTD+LUglMUCxNbj56luBRlLLQWo+",
"9BUhC/ow393tLmqKcB59qNcwbZER6XT5POYwcaKM75QVqhCJVHJNb1zSEE7Co7iO",
"6wIan3lFyjBfYlBEz5vyRWQNIwKfdh5cK1yAu13xGENwmtlSTHiwbjBLXfk+0A/8",
"r/2s+sCYUkGZHhj8xY7bJ1zg0FRalP5LrqY+r6BckT1QPDIQKYy615j1LpOtwZe/",
"d4q7MD/dkzRDsch7t2cIjM/PYeMuzh87admSyL6hdtK0Nm/Q",
"--END CERTIFICATE--"
],
"key": [
"--BEGIN RSA PRIVATE KEY--",
"MIIEowIBAAKCAQEArNj19HxUgoznppnZvVGzr3C3LRfeDseAaUnyft5SR8GW75zh",
"bqOeloUCVq3JSqCJqf3Pb3i9SeAW7Wpt7FtwD5GVRCvVMUUOex0LsDs4VdBQ9tP9",
"GBC6LvOU8J5E8OZfRlQl09NjRvqRpWLBa8XrFB6aI3ZfLSHJ9ddzOacqYAz1Zj3n",
"jkUX+57HjAuhob12DOLcST8np6IcHoJfA2ejhORZElUecBULQIWzjTgJCFVZsNNN",
"itieqYrT7iRjpGvT8XAlVoZKP1viQhmqXAuzu+KWpcAVLlxNYh/iaZ6D4xqeKhNq",
"IJ1t1h/7IEPq76NtHl2/VJtbLXmmGPMZcYAbFwIDAQABAoIBAFCgG4phfGIxK9Uw",
"qrp+o9xQLYGhQnmOYb27OpwnRCYojSlT+mvLcqwvevnHsr9WxyA+PkZ3AYS2PLue",
"C4xW0pzQgdn8wENtPOX8lHkuBocw1rNsCwDwvIguIuliSjI8o3CAy+xVDFgNhWap",
"/CMzfQYziB7GlnrM6hH838iiy0dlv4I/HKk+3/YlSYQEvnFokTf7HxbDDmznkJTM",
"aPKZ5qbnV+4AcQfcLYJ8QE0ViJ8dVZ7RLwIf7+SG0b0bqloti4+oQXqGtiESUwEW",
"/Wzi7oyCbFJoPsFWp1P5+wD7jAGpAd9lPIwPahdr1wl6VwIx9W0XYjoZn71AEaw4",
"bK4xUXECgYEA3g2o9WqyrhYSax3pGEdvV2qN0VQhw7Xe+jyy98CELOO2DNbB9QNJ",
"8cSSU/PjkxQlgbOJc8DEprdMldN5xI/srlsbQWCj72wXxXnVnh991bI2clwt7oYi",
"pcGZwzCrJyFL+QaZmYzLxkxYl1tCiiuqLm+EkjxCWKTX/kKEFb6rtnMCgYEAx0WR",
"L8Uue3lXxhXRdBS5QRTBNklkSxtU+2yyXRpvFa7Qam+GghJs5RKfJ9lTvjfM/PxG",
"3vhuBliWQOKQbm1ZGLbgGBM505EOP7DikUmH/kzKxIeRo4l64mioKdDwK/4CZtS7",
"az0Lq3eS6bq11qL4mEdE6Gn/Y+sqB83GHZYju80CgYABFm4KbbBcW+1RKv9WSBtK",
"gVIagV/89moWLa/uuLmtApyEqZSfn5mAHqdc0+f8c2/Pl9KHh50u99zfKv8AsHfH",
"TtjuVAvZg10GcZdTQ/I41ruficYL0gpfZ3haVWWxNl+J47di4iapXPxeGWtVA+u8",
"eH1cvgDRMFWCgE7nUFzE8wKBgGndUomfZtdgGrp4ouLZk6W4ogD2MpsYNSixkXyW",
"64cIbV7uSvZVVZbJMtaXxb6bpIKOgBQ6xTEH5SMpenPAEgJoPVts816rhHdfwK5Q",
"8zetklegckYAZtFbqmM0xjOI6bu5rqwFLWr1xo33jF0wDYPQ8RHMJkruB1FIB8V2",
"GxvNAoGBAM4g2z8NTPMqX+8IBGkGgqmcYuRQxd3cs7LOSEjF9hPy1it2ZFe/yUKq",
"ePa2E8osffK5LBkFzhyQb0WrGC9ijM9E6rv10gyuNjlwXdFJcdqVamxwPUBtxRJR",
"cYTY2HRkJXDdtT0Bkc3josE6UUDvwMpO0CfAETQPto1tjNEDhQhT",
"--END RSA PRIVATE KEY--"
]
}
```
Server certificates are hot-reloaded every 3600 seconds, which is once per hour.
> `ocspStapling`: number
OCSP stapling refresh interval in seconds. The default value is `0`. Any non-zero value enables OCSP stapling and also replaces the default 3600-second certificate hot-reload interval; reloading and OCSP stapling happen together.
> `oneTimeLoading`: true | false
Load only once. The default is `false`. When set to `true`, both certificate hot reload and OCSP stapling are disabled.
> `usage`: "encipherment" | "verify" | "issue"
Certificate usage. The default value is `"encipherment"`.
- `"encipherment"`: the certificate is used for TLS authentication and encryption
- `"verify"`: the certificate is used to verify remote TLS certificates; in this case it must be a CA certificate
- `"issue"`: the certificate is used to issue other certificates; in this case it must also be a CA certificate
::: tip TIP 1
On Windows, you can install a self-signed CA certificate into the system store to verify remote TLS certificates.
:::
::: tip TIP 2
When a new client request arrives, suppose the specified `serverName` is `"xray.com"`. Xray first looks through the certificate list for a certificate usable for `"xray.com"`. If none is found, it uses any certificate whose `usage` is `"issue"` to issue one suitable for `"xray.com"` with a one-hour validity period, then adds that new certificate to the list for later use.
:::
::: tip TIP 3
When both `certificateFile` and `certificate` are specified, Xray prefers `certificateFile`. The same applies to `keyFile` and `key`.
:::
::: tip TIP 4
When `usage` is `"verify"`, both `keyFile` and `key` may be empty.
:::
::: tip TIP 5
You can generate a self-signed CA certificate with `xray tls cert`.
:::
::: tip TIP 6
If you already own a domain name, you can conveniently obtain free third-party certificates with tools such as [acme.sh](https://github.com/acmesh-official/acme.sh).
:::
> `buildChain`: true | false
Only takes effect when the certificate usage is `issue`. If set to `true`, the CA certificate is embedded into the issued certificate chain.
::: tip TIP 1
You should not embed a root certificate into the chain. This option is suitable only when the signing CA certificate is an intermediate certificate.
:::
> `certificateFile`: string
Path to the certificate file, for example a `.crt` file generated by OpenSSL.
> `certificate`: [string]
An array of strings representing the certificate content, in the same format as the sample above. Choose either `certificate` or `certificateFile`.
> `keyFile`: string
Path to the private-key file, for example a `.key` file generated by OpenSSL. Password-protected key files are not currently supported.
> `key`: [string]
An array of strings representing the private-key content, in the same format as the sample above. Choose either `key` or `keyFile`.