mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-25 23:35:00 +03:00
b6c859f5b9
xray-core 26.10.10 can hand DNS and routing to Lua: dns.script and routing.script name a .lua file (absolute, or found next to the Xray binary) that defines HandleDNSQuery / HandleRoute, and a DNS server's id is how a DNS script picks it. The keys round-tripped through the JSON template but had no field. - DNS: a Lua Script field, and an ID field in the server modal; - Basics: a Routing Script field beside the routing strategy; - Routing: a warning above the rules while a script is set, since the core then routes only through the script and skips every rule, the panel's api rule included. The descriptions say the script must still send the api inbound to the api outbound, and that Xray will not start if the file is missing. An empty field drops the key, because the core rejects an empty path.
196 lines
8.6 KiB
Plaintext
196 lines
8.6 KiB
Plaintext
---
|
|
title: Outbounds & Routing
|
|
description: Shape egress in 3x-ui — WARP, NordVPN, PIA WireGuard, outbound subscriptions, routing rules, and load balancers.
|
|
icon: Route
|
|
---
|
|
|
|
Inbounds accept clients; **outbounds** decide where their traffic goes next.
|
|
3x-ui can route traffic through Cloudflare WARP, NordVPN, Private Internet Access
|
|
(WireGuard), or arbitrary outbound pools imported from a subscription,
|
|
and select between them with routing rules and balancers.
|
|
|
|
## Editing outbounds & routing
|
|
|
|
Outbounds, routing rules, balancers, DNS, and logging all live in the **Xray
|
|
configuration** (the config template you edit under Xray Settings). There's no
|
|
separate per-rule UI — you edit the JSON, and the panel reloads Xray. The panel
|
|
also offers an **outbound connectivity test** and a **route test** (ask the
|
|
running core which outbound a given destination would use).
|
|
|
|
## Build an outbound
|
|
|
|
Every outbound is a JSON object with up to four parts: a **`tag`** (referenced by
|
|
routing rules and balancers), a **`protocol`**, protocol-specific **`settings`**,
|
|
and — for proxy protocols — **`streamSettings`** that must match the remote
|
|
inbound's transport and security. Two outbounds are almost always present:
|
|
|
|
- **`freedom`** sends traffic straight to its destination — the default egress.
|
|
Optionally set a `domainStrategy` (e.g. `UseIP`) to control how hostnames resolve.
|
|
- **`blackhole`** drops traffic. Route unwanted destinations (ads, torrents) here.
|
|
|
|
```json title="freedom + blackhole"
|
|
{
|
|
"outbounds": [
|
|
{ "tag": "direct", "protocol": "freedom", "settings": {} },
|
|
{ "tag": "block", "protocol": "blackhole", "settings": {} }
|
|
]
|
|
}
|
|
```
|
|
|
|
A **proxy** outbound (VLESS, VMess, Trojan, Shadowsocks) forwards to another
|
|
server — handy for chaining or sending select traffic abroad. Mind the wire
|
|
shapes 3x-ui uses: **VLESS is the flat form** (`address`/`port`/`id`/`flow`/
|
|
`encryption`), **VMess uses `settings.vnext[]`**, and **Trojan/Shadowsocks use
|
|
`settings.servers[]`**. The `streamSettings` must mirror the destination's
|
|
[transport and security](/docs/config/transports).
|
|
|
|
Assemble any outbound below and paste the JSON into **Xray Settings → Outbounds**:
|
|
|
|
<OutboundGenerator />
|
|
|
|
## Cloudflare WARP
|
|
|
|
WARP lets your server egress through Cloudflare's network. 3x-ui can register a
|
|
WARP account for you and wire it into a WireGuard outbound tagged **`warp`**:
|
|
|
|
<Steps>
|
|
|
|
<Step>
|
|
### Add a `warp`-tagged outbound
|
|
|
|
Create a WireGuard outbound with the tag `warp` in your Xray config.
|
|
</Step>
|
|
|
|
<Step>
|
|
### Register WARP
|
|
|
|
From the panel's WARP controls, register an account. 3x-ui fills the outbound's
|
|
keys, addresses, reserved bytes, and peer endpoint automatically.
|
|
</Step>
|
|
|
|
<Step>
|
|
### (Optional) auto-rotate the IP
|
|
|
|
Set a WARP update interval (in **days**) to periodically rotate the WARP IP. A
|
|
free license can also be applied.
|
|
</Step>
|
|
|
|
</Steps>
|
|
|
|
Route the traffic you want (for example specific domains) to the `warp` outbound
|
|
with a routing rule.
|
|
|
|
## NordVPN
|
|
|
|
3x-ui can fetch NordVPN (NordLynx/WireGuard) credentials from an access token (or
|
|
accept a private key directly) and list countries/servers, so you can build a
|
|
NordVPN outbound. Open **Xray → Outbounds → More → NordVPN**, sign in or save a
|
|
private key, select a server, and add the outbound. You can add several servers;
|
|
each hostname has a unique `nord-<hostname>` tag and cannot be added twice.
|
|
|
|
**Reset** on an added row keeps its server, tag, peer, and routing references but
|
|
refreshes its embedded private key from the currently stored NordVPN credentials.
|
|
Logout clears only those stored credentials. Existing outbounds continue to use
|
|
their embedded keys; remove unused NordVPN outbounds from the Outbounds list.
|
|
|
|
## PIA WireGuard
|
|
|
|
3x-ui can sign in with a PIA username and password, list countries/regions/servers
|
|
from the signed PIA server list, and build a WireGuard outbound. Open
|
|
**Xray → Outbounds → More → PIA**, sign in, pick a server, and add the outbound.
|
|
You can add several servers (one outbound per hostname). The tag is
|
|
`pia-<region>-<server>` (for example `pia-us-east-useast1`). Adding or using
|
|
**Reset** on a row registers a WireGuard key with PIA `/addKey` for that server.
|
|
The same hostname cannot be added twice. Logout clears the stored token only;
|
|
delete unused PIA outbounds from the Outbounds list. Reset and delete do not
|
|
revoke the WireGuard peer on the PIA account.
|
|
|
|
The password is not stored. The PIA API token is stored with the same
|
|
`NODE_TOKEN_ENCRYPTION` setting as node API tokens. If you retire an old
|
|
`XUI_NODE_TOKEN_KEY` without signing into PIA again, Add/Reset fail until you
|
|
re-login. Peer `allowedIPs` is IPv4-only (`0.0.0.0/0`).
|
|
|
|
## Outbound subscriptions (server pools)
|
|
|
|
An **outbound subscription** imports a remote share-link subscription and injects
|
|
its servers as **outbounds** into the running Xray config — without touching your
|
|
saved template. This is the recommended way to subscribe to a *pool* of servers.
|
|
|
|
| Field | Default | Meaning |
|
|
| ---------------- | ------- | -------------------------------------------------------------- |
|
|
| `url` | — | The remote subscription URL (SSRF-guarded). |
|
|
| `tagPrefix` | auto | Prefix for generated outbound tags (e.g. `hk-`); blank = `subN-`. |
|
|
| `updateInterval` | `600` | Refresh interval in **seconds**. |
|
|
| `prepend` | `false` | Place these outbounds before your manual ones. |
|
|
| `priority` | `0` | Merge order (lower first). |
|
|
|
|
Imported outbounds get **stable tags**: the same server keeps the same tag across
|
|
refreshes, so exact-tag routing/balancer selectors stay pinned — while
|
|
prefix/wildcard selectors (e.g. `hk-*`) automatically pick up new servers as the
|
|
pool changes. Supported link schemes: `vmess`, `vless`, `trojan`, `ss`,
|
|
`hysteria2` (`hy2`), and `wireguard` (`wg`). The panel refreshes enabled
|
|
subscriptions on a timer and reloads Xray when something changes.
|
|
|
|
## Routing rules
|
|
|
|
**Routing rules** decide which outbound (or balancer) each connection uses. Each
|
|
rule is a `field`-type matcher: set any of `domain`, `ip`, `port`, `network`,
|
|
`protocol`, `inboundTag`, `sourceIP`, … and point it at an **`outboundTag`** or a
|
|
**`balancerTag`**. Rules are evaluated **top-to-bottom — the first match wins**, so
|
|
put specific rules above general ones.
|
|
|
|
```json title="route ads to blackhole, private IPs direct"
|
|
{
|
|
"routing": {
|
|
"domainStrategy": "IPIfNonMatch",
|
|
"rules": [
|
|
{ "type": "field", "domain": ["geosite:category-ads-all"], "outboundTag": "block" },
|
|
{ "type": "field", "ip": ["geoip:private"], "outboundTag": "direct" }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### Lua scripts
|
|
|
|
Xray 26.10.10 can hand routing and DNS to Lua. **Basics → Routing Script** takes the
|
|
path of a `.lua` file that defines `HandleRoute` (absolute, or relative to the Xray
|
|
`bin` folder); **DNS → Lua Script** takes one that defines `HandleDNSQuery`, and a
|
|
DNS server's **ID** is the name such a script picks it by.
|
|
|
|
<Callout type="warn">
|
|
A routing script replaces **every** routing rule, the panel's own `api` rule
|
|
included. Send the `api` inbound to the `api` outbound in your script, or traffic
|
|
statistics and live client changes stop. Xray does not start if the file is missing
|
|
or fails to load.
|
|
</Callout>
|
|
|
|
## Balancers
|
|
|
|
A **balancer** groups outbounds by a **selector** (tag prefixes, including the
|
|
wildcard pools from outbound subscriptions) and spreads or fails traffic over them
|
|
with a **strategy**:
|
|
|
|
| Strategy | Picks… | Needs a monitor |
|
|
| ------------- | ----------------------------------------------- | ------------------------ |
|
|
| `random` | a random member per connection | no |
|
|
| `roundRobin` | members in rotation | no |
|
|
| `leastPing` | the lowest-latency member | **`observatory`** |
|
|
| `leastLoad` | the most stable member by sampled load | **`burstObservatory`** |
|
|
|
|
Reference a balancer from a rule via `balancerTag`. `leastPing` and `leastLoad`
|
|
need a health monitor, which Xray places at the **top level** of the config
|
|
(`observatory` / `burstObservatory`, **not** inside `routing`). The panel can
|
|
report balancer status and **override** a balancer to a specific outbound for
|
|
testing.
|
|
|
|
Build the routing block — rules, balancers, and the matching observatory — here:
|
|
|
|
<RoutingBuilder />
|
|
|
|
<Callout type="warn">
|
|
Outbounds that reach external services are fetched with SSRF protection — by
|
|
default private/internal addresses are blocked unless you explicitly allow them
|
|
per source.
|
|
</Callout>
|