mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-28 05:57:19 +00:00
bd6a6aba43
* feat(pia): add login-and-add WireGuard outbounds (#2) * fix(pia): keep PIA outbounds identifiable after the editor strips hostname The outbound editor drops piaHostname, so last-segment matching failed for hyphenated servers. Identify rows by the computed tag, re-encrypt stored tokens onto the active key, skip unusable catalog rows, and always release the catalog refresh latch.
175 lines
7.5 KiB
Plaintext
175 lines
7.5 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.
|
|
|
|
## 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" }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## 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>
|