feat(pia): add PIA login-and-add WireGuard outbounds (#6272)

* 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.
This commit is contained in:
Masterain
2026-08-23 05:11:06 +08:00
committed by GitHub
parent a3e617215c
commit bd6a6aba43
73 changed files with 4095 additions and 31 deletions
+4 -3
View File
@@ -136,6 +136,7 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
│ │ └── model/ # **ALL GORM models** (model.go ~1.1k lines + siblings:
│ │ # node_client_traffic.go, node_client_ip.go,
│ │ # client_global_traffic.go). ⭐ Start here for data shape.
│ ├── pia/ # PIA WireGuard protocol client (auth, signed server list, /addKey)
│ ├── eventbus/ # In-process pub/sub (buffered channel): outbound.down|up,
│ │ # xray.crash, node.down|up, cpu.high, memory.high, login.attempt
│ ├── tunnelmonitor/ # Optional tunnel health probe (XUI_TUNNEL_HEALTH_* env vars):
@@ -163,7 +164,7 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
│ │ │ ├── host.go # /panel/api/hosts (per-inbound subscription host overrides)
│ │ │ ├── server.go # /panel/api/server (status, xray version, certs, logs, DB import/export)
│ │ │ ├── setting.go # /panel/api/setting (settings + API tokens)
│ │ │ ├── xray_setting.go # /panel/api/xray (raw Xray config editor, WARP/Nord, geodata)
│ │ │ ├── xray_setting.go # /panel/api/xray (raw Xray config editor, WARP/Nord/PIA, geodata)
│ │ │ ├── api.go # /panel/api gateway (token auth, envelope + CSRF wiring)
│ │ │ ├── index.go # login/logout/csrf/2FA
│ │ │ ├── spa.go # SPA fallback for /panel UI routes
@@ -202,7 +203,7 @@ node heartbeat every 5s, periodic traffic resets (hourly/daily/weekly/monthly).
│ │ │ ├── port_conflict.go # Detect inbound port collisions
│ │ │ ├── fallback.go # Xray fallback (SNI/ALPN routing on shared port)
│ │ │ ├── email/ # Email notification service (SMTP)
│ │ │ ├── integration/ # External providers: warp.go (Cloudflare WARP), nord.go (NordVPN)
│ │ │ ├── integration/ # External providers: warp.go, nord.go, pia.go
│ │ │ ├── outbound/ # Outbound config service
│ │ │ ├── panel/ # Cross-cutting panel services:
│ │ │ │ ├── panel.go # panel-level helpers
@@ -497,7 +498,7 @@ for AutoMigrate in `internal/database/db.go`.
| **Email notifications** | `service/email/` | `internal/eventbus/` (consumers) |
| **CPU / memory alerts** not firing | `job/check_cpu_usage.go`, `job/check_memory_usage.go` | `internal/eventbus/`, notifier settings in `service/setting.go` |
| Xray auto-restart on **dead tunnel** | `internal/tunnelmonitor/` | `XUI_TUNNEL_HEALTH_*` in `internal/config/` |
| **WARP / Nord** outbound integration | `service/integration/warp.go` / `nord.go` | `service/outbound_subscription.go` |
| **WARP / Nord / PIA** outbound integration | `service/integration/warp.go` / `nord.go` / `pia.go` | `internal/pia/`, `frontend/src/pages/xray/overrides/` |
| **MTProto** proxy issues | `internal/mtproto/manager.go`, `mtproto/process*.go` | `job/mtproto_job.go` |
| **DB migration** / new column | `internal/database/db.go` (AutoMigrate list), `migrate_data.go` | `model/model.go` |
| **Cron schedule** changes | `web.go``startTask()` | the specific `job/*.go` |
@@ -1,13 +1,13 @@
---
title: Outbounds & Routing
description: Shape egress in 3x-ui — WARP and NordVPN outbounds, outbound subscriptions (server pools), routing rules, and load balancers.
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, or arbitrary outbound
pools imported from a subscription, and select between them with routing rules
and balancers.
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
@@ -86,6 +86,23 @@ with a routing rule.
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
@@ -1,7 +1,8 @@
---
title: Xray Settings
description: Xray configuration template, outbound management, Warp/Nord
integration, and config testing. All endpoints under /panel/api/xray.
description: >-
Xray configuration template, outbound management, Warp/Nord/PIA integration, and
config testing. All endpoints under /panel/api/xray.
full: true
_openapi:
preload:
@@ -35,6 +36,9 @@ _openapi:
- depth: 2
title: Manage NordVPN integration. The action parameter selects the operation.
url: '#manage-nordvpn-integration-the-action-parameter-selects-the-operation'
- depth: 2
title: Manage PIA WireGuard integration. The action parameter selects the operation.
url: '#manage-pia-wireguard-integration-the-action-parameter-selects-the-operation'
- depth: 2
title: Reset traffic counters for a specific outbound by tag.
url: '#reset-traffic-counters-for-a-specific-outbound-by-tag'
@@ -117,6 +121,10 @@ _openapi:
id: manage-cloudflare-warp-integration-the-action-parameter-selects-the-operation
- content: Manage NordVPN integration. The action parameter selects the operation.
id: manage-nordvpn-integration-the-action-parameter-selects-the-operation
- content: >-
Manage PIA WireGuard integration. The action parameter selects the
operation.
id: manage-pia-wireguard-integration-the-action-parameter-selects-the-operation
- content: Reset traffic counters for a specific outbound by tag.
id: reset-traffic-counters-for-a-specific-outbound-by-tag
- content: Test an outbound configuration. Sends the outbound JSON (required),
@@ -175,7 +183,7 @@ export default function Layout(props) {
return (
<>
{props.children}
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/xray/","method":"post"},{"path":"/panel/api/xray/getDefaultJsonConfig","method":"get"},{"path":"/panel/api/xray/getOutboundsTraffic","method":"get"},{"path":"/panel/api/xray/getXrayResult","method":"get"},{"path":"/panel/api/xray/update","method":"post"},{"path":"/panel/api/xray/warp/{action}","method":"post"},{"path":"/panel/api/xray/nord/{action}","method":"post"},{"path":"/panel/api/xray/resetOutboundsTraffic","method":"post"},{"path":"/panel/api/xray/testOutbound","method":"post"},{"path":"/panel/api/xray/testOutbounds","method":"post"},{"path":"/panel/api/xray/balancerStatus","method":"post"},{"path":"/panel/api/xray/balancerOverride","method":"post"},{"path":"/panel/api/xray/routeTest","method":"post"},{"path":"/panel/api/xray/outbound-subs","method":"get"},{"path":"/panel/api/xray/outbound-subs","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"delete"},{"path":"/panel/api/xray/outbound-subs/{id}/del","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/refresh","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/move","method":"post"},{"path":"/panel/api/xray/outbound-subs/parse","method":"post"}]} showTitle />
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/xray/","method":"post"},{"path":"/panel/api/xray/getDefaultJsonConfig","method":"get"},{"path":"/panel/api/xray/getOutboundsTraffic","method":"get"},{"path":"/panel/api/xray/getXrayResult","method":"get"},{"path":"/panel/api/xray/update","method":"post"},{"path":"/panel/api/xray/warp/{action}","method":"post"},{"path":"/panel/api/xray/nord/{action}","method":"post"},{"path":"/panel/api/xray/pia/{action}","method":"post"},{"path":"/panel/api/xray/resetOutboundsTraffic","method":"post"},{"path":"/panel/api/xray/testOutbound","method":"post"},{"path":"/panel/api/xray/testOutbounds","method":"post"},{"path":"/panel/api/xray/balancerStatus","method":"post"},{"path":"/panel/api/xray/balancerOverride","method":"post"},{"path":"/panel/api/xray/routeTest","method":"post"},{"path":"/panel/api/xray/outbound-subs","method":"get"},{"path":"/panel/api/xray/outbound-subs","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}","method":"delete"},{"path":"/panel/api/xray/outbound-subs/{id}/del","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/refresh","method":"post"},{"path":"/panel/api/xray/outbound-subs/{id}/move","method":"post"},{"path":"/panel/api/xray/outbound-subs/parse","method":"post"}]} showTitle />
</>
);
}
@@ -1,11 +1,12 @@
---
title: خروجی‌ها و مسیریابی
description: مدیریت ترافیک خروجی در 3x-ui — خروجی‌های WARP و NordVPN، اشتراک‌های خروجی (مجموعه سرورها)، قواعد مسیریابی و متعادل‌کننده‌های بار.
description: مدیریت ترافیک خروجی در 3x-ui — خروجی‌های WARP، NordVPN، WireGuard PIA، اشتراک‌های خروجی (مجموعه سرورها)، قواعد مسیریابی و متعادل‌کننده‌های بار.
icon: Route
---
ورودی‌ها کلاینت‌ها را می‌پذیرند؛ **خروجی‌ها** تعیین می‌کنند ترافیک آن‌ها در ادامه به کجا برود.
3x-ui می‌تواند ترافیک را از طریق Cloudflare WARP، NordVPN یا مجموعه‌های خروجی دلخواه
3x-ui می‌تواند ترافیک را از طریق Cloudflare WARP، NordVPN، Private Internet Access
(خروجی WireGuard) یا مجموعه‌های خروجی دلخواه
وارد‌شده از یک اشتراک مسیریابی کند و با قواعد مسیریابی و متعادل‌کننده‌ها میان آن‌ها
انتخاب نماید.
@@ -86,6 +87,23 @@ WARP به سرور شما امکان می‌دهد ترافیک خود را از
یک کلید خصوصی را مستقیماً بپذیرد) و کشورها/سرورها را فهرست کند تا بتوانید یک خروجی NordVPN
بسازید.
## خروجی WireGuard PIA
3x-ui می‌تواند با نام کاربری و رمز عبور PIA وارد شود، کشورها/منطقه‌ها/سرورها را
از فهرست امضاشده نشان دهد و یک خروجی WireGuard بسازد. از
**Xray → خروجی‌ها → بیشتر → PIA** وارد شوید، سرور را انتخاب کنید و خروجی را
اضافه کنید. می‌توان چند سرور افزود (هر hostname یک خروجی). برچسب
`pia-<region>-<server>` است (مثلاً `pia-us-east-useast1`). افزودن یا **Reset**
در هر ردیف کلید را با `/addKey` ثبت می‌کند. یک hostname را نمی‌توان دو بار
افزود. خروج فقط توکن ذخیره‌شده را پاک می‌کند؛ حذف خروجی از فهرست خروجی‌ها.
Reset یا حذف، peer مربوط به WireGuard را در حساب PIA باطل نمی‌کند.
گذرواژه ذخیره نمی‌شود. توکن API مربوط به PIA با همان تنظیم
`NODE_TOKEN_ENCRYPTION` گره‌ها ذخیره می‌شود. اگر کلید قدیمی
`XUI_NODE_TOKEN_KEY` را بدون ورود دوباره به PIA کنار بگذارید، Add/Reset
تا ورود مجدد شکست می‌خورد. `allowedIPs` فقط
`0.0.0.0/0` است.
## اشتراک‌های خروجی (مجموعه سرورها)
یک **اشتراک خروجی** یک اشتراک share-link از راه دور را وارد می‌کند و سرورهای آن را به‌عنوان
@@ -1,12 +1,13 @@
---
title: Исходящие соединения и маршрутизация
description: Управляйте исходящим трафиком в 3x-ui — outbound-соединения WARP и NordVPN, подписки на исходящие соединения (пулы серверов), правила маршрутизации и балансировщики нагрузки.
description: Управляйте исходящим трафиком в 3x-ui — WARP, NordVPN, PIA WireGuard, подписки на исходящие соединения (пулы серверов), правила маршрутизации и балансировщики нагрузки.
icon: Route
---
Inbound-соединения принимают клиентов; **outbound-соединения** определяют, куда
дальше пойдёт их трафик. 3x-ui может направлять трафик через Cloudflare WARP,
NordVPN или произвольные пулы исходящих соединений, импортированные из подписки,
NordVPN, Private Internet Access (WireGuard) или произвольные пулы
исходящих соединений, импортированные из подписки,
а также выбирать между ними с помощью правил маршрутизации и балансировщиков.
## Редактирование исходящих соединений и маршрутизации
@@ -93,6 +94,24 @@ WARP. Также можно применить бесплатную лиценз
(или принимать приватный ключ напрямую) и выводить список стран/серверов, чтобы вы
могли построить outbound-соединение NordVPN.
## PIA WireGuard
3x-ui может войти с именем пользователя и паролем PIA, показать
страны/регионы/серверы из подписанного списка и собрать WireGuard-исходящее.
Откройте **Xray → Исходящие → Ещё → PIA**, войдите, выберите сервер и добавьте
исходящее. Можно добавить несколько серверов (по одному исходящему на hostname).
Тег: `pia-<region>-<server>` (например `pia-us-east-useast1`). Добавление или
**Reset** в строке регистрирует ключ через PIA `/addKey`. Один и тот же hostname
нельзя добавить дважды. Выход очищает только сохранённый токен; удаляйте
исходящие в списке исходящих. Reset и удаление не отзывают WireGuard-peer
в аккаунте PIA.
Пароль не сохраняется. Токен PIA API хранится с той же настройкой
`NODE_TOKEN_ENCRYPTION`, что и токены API узлов. Если убрать старый
`XUI_NODE_TOKEN_KEY` без повторного входа в PIA, Add/Reset не будут
работать, пока вы не войдёте снова. `allowedIPs` только
`0.0.0.0/0`.
## Подписки на исходящие соединения (пулы серверов)
**Подписка на исходящие соединения** импортирует удалённую подписку со
@@ -1,11 +1,12 @@
---
title: 出站与路由
description: 在 3x-ui 中调整出口流量——WARPNordVPN 出站、出站订阅(服务器池)、路由规则以及负载均衡器。
description: 在 3x-ui 中调整出口流量——WARPNordVPN、PIA WireGuard、出站订阅(服务器池)、路由规则以及负载均衡器。
icon: Route
---
入站负责接受客户端;**出站**则决定客户端的流量接下来发往何处。
3x-ui 可以让流量经由 Cloudflare WARP、NordVPN,或从订阅导入的任意出站池转发,
3x-ui 可以让流量经由 Cloudflare WARP、NordVPN、Private Internet Access
(WireGuard),或从订阅导入的任意出站池转发,
并通过路由规则和均衡器在它们之间进行选择。
## 编辑出站与路由
@@ -81,6 +82,19 @@ WARP 账户,并将其接入一个标签为 **`warp`** 的 WireGuard 出站:
直接接受一个私钥),并列出国家/服务器,从而让你构建一个
NordVPN 出站。
## PIA WireGuard
3x-ui 可以用 PIA 用户名和密码登录,从已验签的服务器列表里选择国家/区域/服务器,
并生成 WireGuard 出站。打开 **Xray → 出站 → 更多 → PIA**,登录后选服务器并添加出站。
可以添加多台服务器(每个 hostname 一条出站)。标签为 `pia-<region>-<server>`(例如
`pia-us-east-useast1`)。添加或对该行 **Reset** 会向该服务器的 PIA `/addKey` 注册密钥。
同一 hostname 不能添加两次。登出只清除保存的 token;删除出站请在出站列表里操作。
Reset 或删除出站不会撤销 PIA 账户侧的 WireGuard peer。
密码不落库。PIA API token 与节点 API token 共用 `NODE_TOKEN_ENCRYPTION`。
若在未重新登录 PIA 的情况下淘汰旧的 `XUI_NODE_TOKEN_KEY`Add/Reset 会失败,直到再次登录。
对端 `allowedIPs` 仅为 `0.0.0.0/0`IPv4)。
## 出站订阅(服务器池)
**出站订阅**会导入一个远程分享链接订阅,并将其中的服务器作为**出站**注入到正在运行的
+42 -1
View File
@@ -2265,7 +2265,7 @@
},
{
"name": "Xray Settings",
"description": "Xray configuration template, outbound management, Warp/Nord integration, and config testing. All endpoints under /panel/api/xray."
"description": "Xray configuration template, outbound management, Warp/Nord/PIA integration, and config testing. All endpoints under /panel/api/xray."
},
{
"name": "Subscription Server",
@@ -9315,6 +9315,47 @@
}
}
},
"/panel/api/xray/pia/{action}": {
"post": {
"tags": [
"Xray Settings"
],
"summary": "Manage PIA WireGuard integration. The action parameter selects the operation.",
"operationId": "post_panel_api_xray_pia_action",
"parameters": [
{
"name": "action",
"in": "path",
"required": true,
"description": "countries — list available countries from the signed PIA server list. servers — list regions and WireGuard servers in a country (sends countryCode). reg — sign in with a PIA username and password (sends username, password). data — return the signed-in account hint. del — delete stored PIA credentials. addKey — register a WireGuard key with the selected server (sends hostname) and return fields to build the outbound.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"success": {
"type": "boolean"
},
"msg": {
"type": "string"
},
"obj": {}
}
}
}
}
}
}
}
},
"/panel/api/xray/resetOutboundsTraffic": {
"post": {
"tags": [