mcp-xray-pilot 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +502 -0
  3. package/data/docs/_index.json +533 -0
  4. package/data/docs/basic__api.md +148 -0
  5. package/data/docs/basic__dns.md +366 -0
  6. package/data/docs/basic__fakedns.md +202 -0
  7. package/data/docs/basic__geodata.md +64 -0
  8. package/data/docs/basic__inbound.md +159 -0
  9. package/data/docs/basic__index.md +136 -0
  10. package/data/docs/basic__log.md +67 -0
  11. package/data/docs/basic__metrics.md +262 -0
  12. package/data/docs/basic__observatory.md +115 -0
  13. package/data/docs/basic__outbound.md +164 -0
  14. package/data/docs/basic__policy.md +140 -0
  15. package/data/docs/basic__reverse.md +268 -0
  16. package/data/docs/basic__routing.md +474 -0
  17. package/data/docs/basic__stats.md +61 -0
  18. package/data/docs/basic__transport.md +1283 -0
  19. package/data/docs/features__features_browser_dialer.md +61 -0
  20. package/data/docs/features__features_env.md +66 -0
  21. package/data/docs/features__features_fallback.md +110 -0
  22. package/data/docs/features__features_index.md +17 -0
  23. package/data/docs/features__features_multiple.md +144 -0
  24. package/data/docs/features__features_xtls.md +13 -0
  25. package/data/docs/inbounds__inbounds_dokodemo.md +11 -0
  26. package/data/docs/inbounds__inbounds_http.md +80 -0
  27. package/data/docs/inbounds__inbounds_hysteria.md +60 -0
  28. package/data/docs/inbounds__inbounds_index.md +22 -0
  29. package/data/docs/inbounds__inbounds_shadowsocks.md +118 -0
  30. package/data/docs/inbounds__inbounds_socks.md +87 -0
  31. package/data/docs/inbounds__inbounds_trojan.md +78 -0
  32. package/data/docs/inbounds__inbounds_tun.md +47 -0
  33. package/data/docs/inbounds__inbounds_tunnel.md +86 -0
  34. package/data/docs/inbounds__inbounds_vless.md +135 -0
  35. package/data/docs/inbounds__inbounds_vmess.md +95 -0
  36. package/data/docs/inbounds__inbounds_wireguard.md +78 -0
  37. package/data/docs/outbounds__outbounds_blackhole.md +42 -0
  38. package/data/docs/outbounds__outbounds_dns.md +97 -0
  39. package/data/docs/outbounds__outbounds_freedom.md +170 -0
  40. package/data/docs/outbounds__outbounds_http.md +70 -0
  41. package/data/docs/outbounds__outbounds_hysteria.md +39 -0
  42. package/data/docs/outbounds__outbounds_index.md +24 -0
  43. package/data/docs/outbounds__outbounds_loopback.md +65 -0
  44. package/data/docs/outbounds__outbounds_shadowsocks.md +105 -0
  45. package/data/docs/outbounds__outbounds_socks.md +58 -0
  46. package/data/docs/outbounds__outbounds_trojan.md +49 -0
  47. package/data/docs/outbounds__outbounds_vless.md +122 -0
  48. package/data/docs/outbounds__outbounds_vmess.md +76 -0
  49. package/data/docs/outbounds__outbounds_wireguard.md +141 -0
  50. package/data/docs/transports__transports_grpc.md +137 -0
  51. package/data/docs/transports__transports_h2.md +11 -0
  52. package/data/docs/transports__transports_http.md +11 -0
  53. package/data/docs/transports__transports_httpupgrade.md +61 -0
  54. package/data/docs/transports__transports_hysteria.md +110 -0
  55. package/data/docs/transports__transports_index.md +19 -0
  56. package/data/docs/transports__transports_mkcp.md +125 -0
  57. package/data/docs/transports__transports_quic.md +11 -0
  58. package/data/docs/transports__transports_raw.md +156 -0
  59. package/data/docs/transports__transports_splithttp.md +11 -0
  60. package/data/docs/transports__transports_tcp.md +11 -0
  61. package/data/docs/transports__transports_websocket.md +75 -0
  62. package/data/docs/transports__transports_xhttp.md +11 -0
  63. package/dist/data/compatibility.js +170 -0
  64. package/dist/data/compatibility.js.map +1 -0
  65. package/dist/data/geocatalogue.js +191 -0
  66. package/dist/data/geocatalogue.js.map +1 -0
  67. package/dist/docs.js +339 -0
  68. package/dist/docs.js.map +1 -0
  69. package/dist/handlers.js +217 -0
  70. package/dist/handlers.js.map +1 -0
  71. package/dist/index.js +66 -0
  72. package/dist/index.js.map +1 -0
  73. package/dist/lint.js +737 -0
  74. package/dist/lint.js.map +1 -0
  75. package/dist/schemas/protocols/blackhole.js +16 -0
  76. package/dist/schemas/protocols/blackhole.js.map +1 -0
  77. package/dist/schemas/protocols/common.js +32 -0
  78. package/dist/schemas/protocols/common.js.map +1 -0
  79. package/dist/schemas/protocols/dns.js +14 -0
  80. package/dist/schemas/protocols/dns.js.map +1 -0
  81. package/dist/schemas/protocols/dokodemo.js +17 -0
  82. package/dist/schemas/protocols/dokodemo.js.map +1 -0
  83. package/dist/schemas/protocols/freedom.js +45 -0
  84. package/dist/schemas/protocols/freedom.js.map +1 -0
  85. package/dist/schemas/protocols/http.js +38 -0
  86. package/dist/schemas/protocols/http.js.map +1 -0
  87. package/dist/schemas/protocols/hysteria.js +51 -0
  88. package/dist/schemas/protocols/hysteria.js.map +1 -0
  89. package/dist/schemas/protocols/index.js +50 -0
  90. package/dist/schemas/protocols/index.js.map +1 -0
  91. package/dist/schemas/protocols/loopback.js +11 -0
  92. package/dist/schemas/protocols/loopback.js.map +1 -0
  93. package/dist/schemas/protocols/shadowsocks.js +60 -0
  94. package/dist/schemas/protocols/shadowsocks.js.map +1 -0
  95. package/dist/schemas/protocols/socks.js +42 -0
  96. package/dist/schemas/protocols/socks.js.map +1 -0
  97. package/dist/schemas/protocols/trojan.js +34 -0
  98. package/dist/schemas/protocols/trojan.js.map +1 -0
  99. package/dist/schemas/protocols/tun.js +19 -0
  100. package/dist/schemas/protocols/tun.js.map +1 -0
  101. package/dist/schemas/protocols/vless.js +44 -0
  102. package/dist/schemas/protocols/vless.js.map +1 -0
  103. package/dist/schemas/protocols/vmess.js +48 -0
  104. package/dist/schemas/protocols/vmess.js.map +1 -0
  105. package/dist/schemas/protocols/wireguard.js +34 -0
  106. package/dist/schemas/protocols/wireguard.js.map +1 -0
  107. package/dist/schemas/security/index.js +16 -0
  108. package/dist/schemas/security/index.js.map +1 -0
  109. package/dist/schemas/security/reality.js +35 -0
  110. package/dist/schemas/security/reality.js.map +1 -0
  111. package/dist/schemas/security/tls.js +46 -0
  112. package/dist/schemas/security/tls.js.map +1 -0
  113. package/dist/schemas/security/xtls.js +17 -0
  114. package/dist/schemas/security/xtls.js.map +1 -0
  115. package/dist/schemas/transports/grpc.js +18 -0
  116. package/dist/schemas/transports/grpc.js.map +1 -0
  117. package/dist/schemas/transports/httpupgrade.js +14 -0
  118. package/dist/schemas/transports/httpupgrade.js.map +1 -0
  119. package/dist/schemas/transports/hysteria.js +25 -0
  120. package/dist/schemas/transports/hysteria.js.map +1 -0
  121. package/dist/schemas/transports/index.js +32 -0
  122. package/dist/schemas/transports/index.js.map +1 -0
  123. package/dist/schemas/transports/mkcp.js +34 -0
  124. package/dist/schemas/transports/mkcp.js.map +1 -0
  125. package/dist/schemas/transports/raw.js +19 -0
  126. package/dist/schemas/transports/raw.js.map +1 -0
  127. package/dist/schemas/transports/websocket.js +15 -0
  128. package/dist/schemas/transports/websocket.js.map +1 -0
  129. package/dist/schemas/transports/xhttp.js +34 -0
  130. package/dist/schemas/transports/xhttp.js.map +1 -0
  131. package/dist/search.js +78 -0
  132. package/dist/search.js.map +1 -0
  133. package/dist/state.js +87 -0
  134. package/dist/state.js.map +1 -0
  135. package/dist/tools.js +274 -0
  136. package/dist/tools.js.map +1 -0
  137. package/dist/tools_impl/diff.js +55 -0
  138. package/dist/tools_impl/diff.js.map +1 -0
  139. package/dist/tools_impl/github.js +416 -0
  140. package/dist/tools_impl/github.js.map +1 -0
  141. package/dist/tools_impl/merge.js +181 -0
  142. package/dist/tools_impl/merge.js.map +1 -0
  143. package/dist/tools_impl/refresh.js +46 -0
  144. package/dist/tools_impl/refresh.js.map +1 -0
  145. package/dist/tools_impl/suggest.js +169 -0
  146. package/dist/tools_impl/suggest.js.map +1 -0
  147. package/dist/types.js +10 -0
  148. package/dist/types.js.map +1 -0
  149. package/dist/utils.js +81 -0
  150. package/dist/utils.js.map +1 -0
  151. package/dist/validate.js +408 -0
  152. package/dist/validate.js.map +1 -0
  153. package/package.json +62 -0
@@ -0,0 +1,474 @@
1
+ ---
2
+ url: https://xtls.github.io/en/config/routing.html
3
+ source_url: https://raw.githubusercontent.com/XTLS/Xray-docs-next/main/docs/en/config/routing.md
4
+ title: Routing
5
+ category: basic
6
+ slug: routing
7
+ fetched_at: 2026-05-04T18:42:42.094Z
8
+ ---
9
+ # Routing
10
+
11
+ The routing module can send inbound data through different outbound connections based on different rules, achieving the purpose of on-demand proxying.
12
+
13
+ A common usage is splitting traffic between domestic and foreign destinations. Xray can determine the region of the traffic through internal mechanisms and then send them to different outbound proxies.
14
+
15
+ For a more detailed analysis of the routing function: [Analysis of Routing (Part 1)](../document/level-1/routing-lv1-part1.md).
16
+
17
+ ## RoutingObject
18
+
19
+ `RoutingObject` corresponds to the `routing` item in the configuration file.
20
+
21
+ ```json
22
+ {
23
+ "routing": {
24
+ "domainStrategy": "AsIs",
25
+ "rules": [],
26
+ "balancers": []
27
+ }
28
+ }
29
+ ```
30
+
31
+ > `domainStrategy`: "AsIs" | "IPIfNonMatch" | "IPOnDemand"
32
+
33
+ Domain resolution strategy. Different strategies are used based on different settings.
34
+
35
+ - `"AsIs"`: No extra operation. Uses the domain in the destination address or the sniffed domain. Default value.
36
+ - `"IPIfNonMatch"`: When no rule is matched after a full round of matching, resolve the domain to an IP and perform a second round of matching.
37
+ - `"IPOnDemand"`: Before starting matching, resolve the domain to an IP immediately for matching.
38
+
39
+ Actual resolution behavior will be delayed until the first IP rule is encountered to reduce latency. The result will contain both IPv4 and IPv6 (you can further restrict this via `queryStrategy` in the built-in DNS). When a domain resolves to multiple IPs, each rule will try all IPs in turn. If any IP meets the requirement, the rule is considered matched.
40
+
41
+ When `sniff` + `routeOnly` is enabled, allowing the routing system to see both IP and domain, if the aforementioned resolution occurs, the routing system can only see the IP resolved from the domain and cannot see the original destination IP, unless resolution fails.
42
+
43
+ When two domains exist (target domain + sniffed result), the priority of the sniffed result is always higher, whether for resolution or domain matching.
44
+
45
+ Regardless of whether resolution occurs, the routing system will not affect the actual destination address. The requested target remains the original target.
46
+
47
+ > `rules`: \[[RuleObject](#ruleobject)\]
48
+
49
+ Corresponds to an array, where each item is a rule.
50
+
51
+ For each connection, routing will judge these rules from top to bottom. When the first effective rule is encountered, the connection is forwarded to the `outboundTag` or `balancerTag` specified by it.
52
+
53
+ ::: tip
54
+ When no rule is matched, traffic is sent via the first outbound by default.
55
+ :::
56
+
57
+ > `balancers`: \[ [BalancerObject](#balancerobject) \]
58
+
59
+ An array, where each item is a load balancer configuration.
60
+
61
+ When a rule points to a load balancer, Xray will select an outbound through this load balancer and then forward traffic using it.
62
+
63
+ ### RuleObject
64
+
65
+ ```json
66
+ {
67
+ "domain": ["baidu.com", "qq.com", "geosite:cn"],
68
+ "ip": ["0.0.0.0/8", "10.0.0.0/8", "fc00::/7", "fe80::/10", "geoip:cn"],
69
+ "port": "53,443,1000-2000",
70
+ "sourcePort": "53,443,1000-2000",
71
+ "localPort": "53,443,1000-2000",
72
+ "network": "tcp",
73
+ "sourceIP": ["10.0.0.1"],
74
+ "localIP": ["192.168.0.25"],
75
+ "user": ["love@xray.com"],
76
+ "vlessRoute": "53,443,1000-2000",
77
+ "inboundTag": ["tag-vmess"],
78
+ "protocol": ["http", "tls", "quic", "bittorrent"],
79
+ "attrs": { ":method": "GET" },
80
+ "process": ["curl"],
81
+ "outboundTag": "direct",
82
+ "balancerTag": "balancer",
83
+ "ruleTag": "rule name",
84
+ "webhook": {
85
+ "url": "https://api.example.com/alert",
86
+ "deduplication": 300
87
+ }
88
+ }
89
+ ```
90
+
91
+ ::: danger
92
+ When multiple attributes are specified simultaneously, these attributes must be satisfied **simultaneously** for the current rule to take effect.
93
+ :::
94
+
95
+ > `domain`: \[string\]
96
+
97
+ - **Pure string**: Same as substring below, but the `"keyword:"` prefix can be omitted.
98
+ - **Regular expression**: Starts with `"regexp:"`, the rest is a regular expression. The rule takes effect when the regular expression matches the target domain. For example, "regexp:\\\\.goo.\*\\\\.com\$" matches "www.google.com" and "fonts.googleapis.com", but not "google.com". Case sensitive.
99
+ - **Subdomain (Recommended)**: Starts with `"domain:"`, the rest is a domain name. The rule takes effect when the domain is the target domain or its subdomain. For example, "domain:xray.com" matches "www.xray.com" and "xray.com", but not "wxray.com".
100
+ - **Substring**: Starts with `"keyword:"`, the rest is a string. The rule takes effect when this string matches any part of the target domain. For example, "keyword:sina.com" matches "sina.com", "sina.com.cn", and "www.sina.com", but not "sina.cn".
101
+ - **Full match**: Starts with `"full:"`, the rest is a domain name. The rule takes effect when this domain exactly matches the target domain. For example, "full:xray.com" matches "xray.com" but not "www.xray.com".
102
+ - **Dotless domain**: Starts with `"dotless:"`, the rest is a string that cannot contain `.`. The rule takes effect when the domain contains no `.` and this string matches any part of the target domain. For example, "dotless:pc-" matches "pc-alice", "mypc-alice". Suitable for intranet NetBIOS domains, etc. Case sensitive.
103
+ - **Predefined domain list**: Starts with `"geosite:"`, the rest is a name, such as `geosite:google` or `geosite:cn`. Refer to [Predefined Domain List](#predefined-domain-list) for names and domain lists.
104
+ - **Load domains from file**: In the form of `"ext:file:tag"`. Must start with `ext:` (lowercase), followed by filename and tag. The file is stored in the [Resource Directory](./features/env.md#resource-file-path). The file format is the same as `geosite.dat`, and the tag must exist in the file.
105
+
106
+ ::: tip
107
+ `"ext:geoip.dat:cn"` is equivalent to `"geoip:cn"`
108
+ :::
109
+
110
+ > `ip`: \[string\]
111
+
112
+ An array, where each item represents an IP range. The rule takes effect when an item matches the target IP. Available forms:
113
+
114
+ - **IP**: Like `"127.0.0.1"`.
115
+ - **[CIDR](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing)**: Like `"10.0.0.0/8"`. You can also use `"0.0.0.0/0"` or `"::/0"` to specify all IPv4 or IPv6.
116
+ - **Predefined IP list**: This list is pre-installed in every Xray installation package, named `geoip.dat`. Usage is like `"geoip:cn"`. Must start with `geoip:` (lowercase), followed by a two-character country code. Supports almost all countries with internet access.
117
+ - **Special value**: `"geoip:private"`, includes all private addresses, such as `127.0.0.1`.
118
+ - **Load IPs from file**: In the form of `"ext:file:tag"`. Must start with `ext:` (lowercase), followed by filename and tag. The file is stored in the [Resource Directory](./features/env.md#resource-file-path). The file format is the same as `geoip.dat`, and the tag must exist in the file.
119
+ - **Inverse selection `!`**: `"!10.0.0.0/8"` means anything not in `10.0.0.0/8`, and `"!geoip:cn"` means results not in `geoip:cn`. Multiple inverse options have an `AND` relationship, while positive options, or positive options together with all inverse options, have an `OR` relationship. For example, `ip: ["!geoip:cn", "!geoip:us", "geoip:telegram"]` matches IPs that are not from the US AND not from China, OR are Telegram IPs.
120
+
121
+ > `port`: number | string
122
+
123
+ Target port range. Three forms:
124
+
125
+ - `"a-b"`: a and b are positive integers less than 65536. This is a closed interval. The rule takes effect when the target port falls within this range.
126
+ - `a`: a is a positive integer less than 65536. The rule takes effect when the target port is a.
127
+ - A mixture of the above two forms, separated by commas ",". For example: `"53,443,1000-2000"`.
128
+
129
+ > `sourcePort`: number | string
130
+
131
+ Source port. Three forms:
132
+
133
+ - `"a-b"`: a and b are positive integers less than 65536. This is a closed interval. The rule takes effect when the source port falls within this range.
134
+ - `a`: a is a positive integer less than 65536. The rule takes effect when the source port is a.
135
+ - A mixture of the above two forms, separated by commas ",". For example: `"53,443,1000-2000"`.
136
+
137
+ > `localPort`: number | string
138
+
139
+ Local inbound port. Format matches `port`/`sourcePort`. Useful when the inbound listens on a port range.
140
+
141
+ > `network`: "tcp" | "udp" | "tcp,udp"
142
+
143
+ Optional values are "tcp", "udp", or "tcp,udp". The rule takes effect when the connection method matches.
144
+
145
+ Since the core obviously only supports TCP and UDP layer 4 protocols, a routing rule containing only `"network": "tcp,udp"` can be used as a "catch-all" to match any traffic. An example usage is placing it at the very end of all routing rules to specify the default outbound when no other rules match (otherwise the core defaults to the first outbound).
146
+
147
+ Of course, other ways that obviously match any traffic, such as specifying ports 1-65535 or IPs 0.0.0.0/0 + ::/0, have a similar effect.
148
+
149
+ > `sourceIP`: \[string\]
150
+
151
+ An array, where each item represents an IP range. Forms include IP, CIDR, GeoIP, and loading IPs from a file. The rule takes effect when an item matches the source IP.
152
+
153
+ Alias: `source`
154
+
155
+ > `localIP`: \[string\]
156
+
157
+ Format is the same as other IPs. Used to specify the IP used by the local inbound (when using 0.0.0.0 to listen on all IPs, different actual incoming IPs will produce different localIPs).
158
+
159
+ Ineffective for UDP (due to UDP being message-oriented, tracking is not possible); it always sees the listening IP.
160
+
161
+ > `user`: \[string\]
162
+
163
+ An array, where each item is an email address. The rule takes effect when an item matches the source user.
164
+
165
+ Similar to domains, it also supports regex matching starting with `regexp:`. (Similarly, need to replace `\` with `\\`, see explanation in domain section).
166
+
167
+ > `vlessRoute`: number | string
168
+
169
+ VLESS inbound allows the client to modify the 7th and 8th bytes of the configured UUID to any bytes. The server routing will use this as `vlessRoute` data, allowing users to customize parts of the server routing based on needs without changing any external fields.
170
+
171
+ ```
172
+ --------------↓↓↓↓------------------
173
+ xxxxxxxx-xxxx-0000-xxxx-xxxxxxxxxxxx
174
+ ```
175
+
176
+ The configuration uses data after Big-Endian encoding to uint16 (if you don't understand, treat these four digits as a hexadecimal number and convert to decimal). E.g., `0001→1`, `000e→14`, `38b2→14514`. The reason for this is that the syntax here is the same as `port`; you can freely specify many segments for routing just like specifying ports.
177
+
178
+ > `inboundTag`: \[string\]
179
+
180
+ An array, where each item is an identifier. The rule takes effect when an item matches the identifier of the inbound protocol.
181
+
182
+ > `protocol`: \[ "http" | "tls" | "quic" | "bittorrent" \]
183
+
184
+ An array, where each item represents a protocol. The rule takes effect when a protocol matches the protocol type of the current connection.
185
+
186
+ `http` only supports 1.0 and 1.1; h2 is not supported yet (plaintext h2 traffic is also very rare).
187
+
188
+ `tls` TLS 1.0 ~ 1.3.
189
+
190
+ `quic` Due to the complexity of this protocol, sniffing may sometimes fail.
191
+
192
+ `bittorrent` Only has the most basic sniffing; may not work for much encrypted and obfuscated traffic.
193
+
194
+ ::: tip
195
+ You must enable the `sniffing` option in the inbound proxy to sniff the protocol type used by the connection.
196
+ :::
197
+
198
+ > `attrs`: object
199
+
200
+ A JSON object where keys and values are strings. Used to detect HTTP traffic attribute values (due to obvious reasons, only supports 1.0 and 1.1). The rule is matched when HTTP headers contain all specified keys and values contain the specified substrings. Keys are case-insensitive. Values support regular expressions.
201
+
202
+ It also supports pseudo-headers like `:method` and `:path` from h2 for matching methods and paths (although these headers do not exist in HTTP/1.1).
203
+
204
+ For non-CONNECT methods of HTTP inbounds, `attrs` can be obtained directly. For other inbounds, sniffing must be enabled to obtain these values for matching.
205
+
206
+ Example:
207
+
208
+ - Detect HTTP GET: `{":method": "GET"}`
209
+ - Detect HTTP Path: `{":path": "/test"}`
210
+ - Detect Content Type: `{"accept": "text/html"}`
211
+
212
+ > `process`: \[string\]
213
+
214
+ If the connection originates from the local machine, match its process. If not from local, it is directly regarded as a match failure. Only supports Windows and Linux.
215
+
216
+ This option is an array, where each item has three matching modes.
217
+
218
+ 1. **No slash**: Matches process name.
219
+ 2. **Contains slash, does not end with slash**: Matches absolute path.
220
+ 3. **Contains slash, ends with slash**: Matches folder; all processes under this folder are considered a match.
221
+
222
+ Note:
223
+
224
+ - All options are case-sensitive.
225
+ - On Windows, use backslash `\` for paths. Here it is uniformly required to use forward slash `/`, e.g., `C:/Windows/System32/curl.exe`, because backslashes are treated as escape characters in JSON, which is inconvenient (unless you choose to double the backslashes, which also works).
226
+ - When matching by process name, the core automatically removes the `.exe` suffix. Similarly, `["curl"]` can match curl on both Linux and Windows. When using absolute paths, the `.exe` suffix cannot be ignored.
227
+
228
+ Special syntax sugar:
229
+
230
+ - `self/`: Matches the current core process, very useful for avoiding routing loops.
231
+ - `xray/`: Will be replaced by the absolute path where the current core resides, matching all Xray processes started from this binary.
232
+
233
+ > `outboundTag`: string
234
+
235
+ Corresponds to an outbound identifier.
236
+
237
+ > `balancerTag`: string
238
+
239
+ Corresponds to a Balancer identifier.
240
+
241
+ ::: tip
242
+ You must choose one between `balancerTag` and `outboundTag`. When both are specified, `outboundTag` takes effect.
243
+ :::
244
+
245
+ > `ruleTag`: string
246
+
247
+ Optional. No actual effect, only used to identify the name of this rule.
248
+
249
+ If set, information regarding this rule will be output at the Info level when the rule is matched, used for debugging which specific rule was hit.
250
+
251
+ > `webhook`: [WebhookObject](#webhookobject)
252
+
253
+ Optional. If set, a POST request will be sent to the specified URL when the rule is matched.
254
+
255
+ Example of data sent in the POST request:
256
+
257
+ ```json
258
+ {
259
+ "email": "2", // string | null
260
+ "level": null, // number | null
261
+ "protocol": "tls", // string | null
262
+ "network": "tcp", // string
263
+ "source": "tcp:127.0.0.1:54203", // string | null
264
+ "destination": "tcp:dns.google:443", // string
265
+ "routeTarget": null, // string | null
266
+ "originalTarget": "tcp:8.8.8.8:443", // string | null
267
+ "inboundTag": "VLESS_TCP", // string | null
268
+ "inboundName": "vless", // string | null
269
+ "inboundLocal": "tcp:192.168.108.1:443", // string | null
270
+ "outboundTag": "notify-bittorrent", // string | null
271
+ "ts": 1771886901 // number
272
+ }
273
+ ```
274
+
275
+ #### WebhookObject
276
+
277
+ ```json
278
+ {
279
+ "url": "http://127.0.0.1:8080/api/webhook",
280
+ "deduplication": 10,
281
+ "headers": {
282
+ "X-API-Key": "your-secret-key"
283
+ }
284
+ }
285
+ ```
286
+
287
+ > `url`: string
288
+
289
+ The URL to which the notification will be sent. Both standard web addresses and local Unix socket paths are supported.
290
+
291
+ - `https://api.example.com/alert` — a standard URL for sending notifications via HTTP(S). Used for integration with external web services or APIs.
292
+ - `/var/run/webhook.sock` — sends the notification via a Unix socket, with the POST request directed to the root path `/` of the socket.
293
+ - `/var/run/webhook.sock:/alert` — sends the notification via a Unix socket to a specific endpoint `/alert`. This allows direct integration with local services without using a network interface.
294
+ - `@abstract:/webhook` — abstract socket (lock-free, Linux/Android only).
295
+ - `@@padded:/webhook` — abstract socket with padding for HAProxy compatibility.
296
+
297
+ > `deduplication`: number
298
+
299
+ The time (in seconds) for event deduplication. If multiple events are triggered within this period, duplicate requests are ignored.
300
+
301
+ > `headers`: object
302
+
303
+ HTTP request headers.
304
+
305
+ ### BalancerObject
306
+
307
+ Load balancer configuration. When a load balancer takes effect, it selects the most suitable outbound from the specified outbounds according to the configuration and forwards the traffic.
308
+
309
+ ```json
310
+ {
311
+ "tag": "balancer",
312
+ "selector": [],
313
+ "fallbackTag": "outbound",
314
+ "strategy": {}
315
+ }
316
+ ```
317
+
318
+ > `tag`: string
319
+
320
+ The identifier of this load balancer, used to match `balancerTag` in `RuleObject`.
321
+
322
+ > `selector`: \[ string \]
323
+
324
+ An array of strings. Each string is used for prefix matching against outbound identifiers. Among the following outbound identifiers: `[ "a", "ab", "c", "ba" ]`, `"selector": ["a"]` will match `[ "a", "ab" ]`.
325
+
326
+ Generally matches multiple outbounds to distribute load among them.
327
+
328
+ > `fallbackTag`: string
329
+
330
+ If all outbounds cannot be connected based on observation results, the outbound specified by this configuration item is used.
331
+
332
+ Note: Requires adding [observatory](./observatory.md#observatoryobject) or [burstObservatory](./observatory.md#burstobservatoryobject) configuration items.
333
+
334
+ > `strategy`: [StrategyObject](#strategyobject)
335
+
336
+ #### StrategyObject
337
+
338
+ ```json
339
+ {
340
+ "type": "roundRobin",
341
+ "settings": {}
342
+ }
343
+ ```
344
+
345
+ > `type` : "random" | "roundRobin" | "leastPing" | "leastLoad"
346
+
347
+ - `random`: Default value. Randomly selects a matched outbound proxy.
348
+ - `roundRobin`: Selects matched outbound proxies in order.
349
+ - `leastPing`: Selects the matched outbound proxy with the lowest latency based on observation results. Requires [observatory](./observatory.md#observatoryobject) or [burstObservatory](./observatory.md#burstobservatoryobject).
350
+ - `leastLoad`: Selects the most stable outbound proxy based on observation results. Requires [observatory](./observatory.md#observatoryobject) or [burstObservatory](./observatory.md#burstobservatoryobject).
351
+
352
+ ::: tip
353
+ Regardless of the mode, if all nodes corresponding to its `selector` have `observatory` or `burstObservatory` configured, healthy nodes can be filtered out. If no healthy nodes are available, it attempts `fallbackTag`.
354
+ :::
355
+
356
+ > `settings`: [StrategySettingsObject](#strategysettingsobject)
357
+
358
+ ##### StrategySettingsObject
359
+
360
+ This is an optional configuration item. The configuration format varies for different load balancing strategies. Currently, only the `leastLoad` strategy supports this item.
361
+
362
+ ```json
363
+ {
364
+ "expected": 2,
365
+ "maxRTT": "1s",
366
+ "tolerance": 0.01,
367
+ "baselines": ["1s"],
368
+ "costs": [
369
+ {
370
+ "regexp": false,
371
+ "match": "tag",
372
+ "value": 0.5
373
+ }
374
+ ]
375
+ }
376
+ ```
377
+
378
+ > `expected`: number
379
+
380
+ The number of optimal nodes selected by the load balancer. Traffic will be randomly distributed among these nodes.
381
+
382
+ > `maxRTT`: string
383
+
384
+ The maximum acceptable RTT duration for speed tests.
385
+
386
+ > `tolerance`: float number
387
+
388
+ The maximum acceptable failure rate for speed tests. For example, 0.01 means accepting a 1% failure rate. (Seemingly unimplemented).
389
+
390
+ > `baselines`: \[ string \]
391
+
392
+ The maximum acceptable standard deviation duration for RTT speed tests.
393
+
394
+ > `costs`: \[ CostObject \]
395
+
396
+ Optional configuration item. An array to assign weights to all outbounds.
397
+
398
+ > `regexp`: true | false
399
+
400
+ Whether to use regular expressions to select outbound `Tag`.
401
+
402
+ > `match`: string
403
+
404
+ Matches outbound `Tag`.
405
+
406
+ > `value`: float number
407
+
408
+ Weight value. The larger the value, the less likely the corresponding node is to be selected.
409
+
410
+ ### Load Balancer Configuration Example
411
+
412
+ ```json
413
+ "routing": {
414
+ "rules": [
415
+ {
416
+ "inboundTag": [
417
+ "in"
418
+ ],
419
+ "balancerTag": "round"
420
+ }
421
+ ],
422
+ "balancers" : [
423
+ {
424
+ "selector": [
425
+ "out"
426
+ ],
427
+ "strategy": {
428
+ "type":"roundRobin"
429
+ },
430
+ "tag": "round"
431
+ }
432
+ ]
433
+ },
434
+
435
+ "inbounds": [
436
+ {
437
+ // Inbound config
438
+ "tag": "in"
439
+ }
440
+ ],
441
+
442
+ "outbounds": [
443
+ {
444
+ // Outbound config
445
+ "tag": "out1"
446
+ },
447
+ {
448
+ // Outbound config
449
+ "tag": "out2"
450
+ }
451
+ ]
452
+ ```
453
+
454
+ ### Predefined Domain List
455
+
456
+ This list is pre-installed in every Xray installation package, named `geosite.dat`. This file contains some common domain names. Usage: `geosite:xxx`, e.g., `geosite:google` represents routing filtering or DNS filtering for domains included within `google` in the file.
457
+
458
+ Common domains include:
459
+
460
+ - `category-ads`: Contains common advertising domains.
461
+ - `category-ads-all`: Contains common advertising domains, as well as domains of advertising providers.
462
+ - `cn`: Equivalent to the collection of `geolocation-cn` and `tld-cn`.
463
+ - `apple`: Contains the vast majority of Apple domains.
464
+ - `google`: Contains the vast majority of Google domains.
465
+ - `microsoft`: Contains the vast majority of Microsoft domains.
466
+ - `facebook`: Contains the vast majority of Facebook domains.
467
+ - `twitter`: Contains the vast majority of Twitter domains.
468
+ - `telegram`: Contains the vast majority of Telegram domains.
469
+ - `geolocation-cn`: Contains common mainland China site domains.
470
+ - `geolocation-!cn`: Contains common non-mainland China site domains.
471
+ - `tld-cn`: Contains top-level domains managed by CNNIC for mainland China, such as domains ending in `.cn`, `.中国`.
472
+ - `tld-!cn`: Contains top-level domains not used in mainland China, such as domains ending in `.tw` (Taiwan), `.jp` (Japan), `.sg` (Singapore), `.us` (USA), `.ca` (Canada), etc.
473
+
474
+ You can also view the complete domain list here: [Domain list community](https://github.com/v2fly/domain-list-community).
@@ -0,0 +1,61 @@
1
+ ---
2
+ url: https://xtls.github.io/en/config/stats.html
3
+ source_url: https://raw.githubusercontent.com/XTLS/Xray-docs-next/main/docs/en/config/stats.md
4
+ title: Statistics
5
+ category: basic
6
+ slug: stats
7
+ fetched_at: 2026-05-04T18:42:42.586Z
8
+ ---
9
+ # Statistics
10
+
11
+ Used to configure Xray traffic data statistics.
12
+
13
+ ## StatsObject
14
+
15
+ `StatsObject` corresponds to the `stats` item in the configuration file.
16
+
17
+ ```json
18
+ {
19
+ "stats": {}
20
+ }
21
+ ```
22
+
23
+ Currently, statistics do not require any parameters. As long as the `StatsObject` item exists, internal statistics are enabled.
24
+
25
+ After enabling statistics, you only need to enable the corresponding items in [Policy](./policy.md) to collect the corresponding data.
26
+
27
+ ## Retrieving Statistics
28
+
29
+ You can use relevant `xray api` commands to retrieve statistics.
30
+
31
+ The currently available statistics are as follows:
32
+
33
+ - User Data
34
+ - `user>>>[email]>>>traffic>>>uplink`
35
+
36
+ Uplink traffic for a specific user, in bytes.
37
+
38
+ - `user>>>[email]>>>traffic>>>downlink`
39
+
40
+ Downlink traffic for a specific user, in bytes.
41
+
42
+ ::: tip
43
+ If the corresponding user does not specify an Email, statistics will not be enabled.
44
+ :::
45
+
46
+ - Global Data
47
+ - `inbound>>>[tag]>>>traffic>>>uplink`
48
+
49
+ Uplink traffic for a specific inbound, in bytes.
50
+
51
+ - `inbound>>>[tag]>>>traffic>>>downlink`
52
+
53
+ Downlink traffic for a specific inbound, in bytes.
54
+
55
+ - `outbound>>>[tag]>>>traffic>>>uplink`
56
+
57
+ Uplink traffic for a specific outbound, in bytes.
58
+
59
+ - `outbound>>>[tag]>>>traffic>>>downlink`
60
+
61
+ Downlink traffic for a specific outbound, in bytes.