mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-05 13:42:07 +03:00
feat(tuic): implement native in-process Go TUIC v5 server (#6577)
* feat(tuic): implement native in-process Go TUIC v5 server - Implement native TUIC v5 protocol server on pure Go using quic-go - Bridge decrypted TCP/UDP traffic into Xray-core via loopback SOCKS5 inbound - Support full Xray routing rules (geosite/geoip) and cascading outbounds - Implement atomic per-client traffic accounting with TotalGB and ExpiryTime - Add automatic legacy cleanup for older Rust tuic-server binaries, configs, and orphaned processes - Eliminate external Rust tuic-server downloads from install/CI scripts * fix(tuic): address traffic accounting, client reload, and socket lifecycle issues * fix(service): update checkTuicSocksReverseConflict to use bindAddr for listenOverlaps * fix(tuic): resolve traffic double-accounting, UDP fragmentation, and socket lifecycle issues * feat(tuic): complete native Go integration and address audit findings - Integrate an isolated QUIC fork pinned to a specific commit - Preserve original QUIC dependencies for Xray, Hysteria and Gin - Apply BBR, CUBIC and Reno to server connections and exported client profiles - Bridge Xray BBR with correct monotonic time and congestion type conversions - Handle congestion sender recreation after PMTU changes - Update congestion control for new connections without restarting the listener - Preserve existing connections and their selected congestion controller - Apply per-inbound log levels through the shared panel logger - Add lifecycle, authentication and TCP/UDP relay events without exposing secrets - Rate-limit repeated authentication and relay warnings - Support native and QUIC UDP relay modes on the same listener - Recover UDP associations after relay worker failures - Fix TCP relay cancellation, idle shutdown and half-close handling - Close active sessions when client credentials are revoked or disabled - Track traffic by immutable client statistics IDs across email and UUID changes - Prevent ambiguous accounting and duplicate UUIDs within TUIC inbounds - Persist pending traffic in a durable shutdown journal - Replay journal batches transactionally without duplicate accounting - Report server shutdown failures through the shared logger - Preserve legacy flat and nested TUIC settings compatibility - Normalize congestion controller values consistently across backend and frontend - Preserve controller, UDP mode and SNI in client links and subscriptions - Separate client profile options from server settings in the TUIC form - Keep certificate path autofill explicit when changing client SNI - Align UDP packet size validation with protocol limits - Simplify and localize TUIC field hints and certificate autofill messages - Add controller, TCP/UDP, logging and live settings update tests - Add accounting identity, journal replay and shutdown regression tests - Add relay recovery, session revocation and legacy frontend form tests * fix(service): alias the TUIC duplicate-UUID subquery for PostgreSQL < 16 syncInboundClients runs a COUNT(*) FROM (subquery) for every client sync, whatever the protocol. PostgreSQL before 16 rejects a FROM subquery with no alias, so on the distro PostgreSQL install.sh provisions (14 on Ubuntu 22.04, 15 on Debian 12) every client add or edit failed with SQLSTATE 42601. Reproduced against postgres:15 with the new env-gated test. * fix(database): create tuic_traffic_receipts through the model migration AddTuicTrafficBatch issued CREATE TABLE IF NOT EXISTS at runtime, a schema change outside db.go. The table was invisible to allModels and migrationModels, so x-ui migrate-db dropped the receipts and a retained journal could be counted twice after a SQLite to PostgreSQL move. It is now a GORM model in both lists, and the insert uses OnConflict DoNothing. * chore(tuic): skip the ICMP-dependent relay test on Windows, drop dead collectors Go disables SIO_UDP_CONNRESET on Windows, so a dead UDP bridge never fails a read there and TestAudit3UDPAssociationMustRecoverAfterBridgeReadFailure was red on every Windows run. Server.CollectTotalTraffic and Manager.CollectTraffic had no caller. * refactor(tuic): serve TUIC on apernet/quic-go instead of a personal fork The native server depended on github.com/poise52/quic-go, a personal fork of apernet/quic-go patched only to pick the congestion controller before the handshake. That put a second QUIC/TLS stack in the binary that no upstream security fix reaches. apernet/quic-go is already in the graph through xray-core and exposes SetCongestionControl, so BBR is now installed on each accepted connection with Xray's own congestion.UseBBR; the cross-module BBR adapter is gone. apernet ships New Reno as its only built-in sender, so a cubic setting is served as new_reno server-side (clients still get cubic in their profile). The test inspectors now read the sender under congestionMutex, which the post-handshake install writes under. Linux loopback, single stream through Xray: 2428 -> 3383 Mbit/s (bbr). --------- Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
@@ -18,7 +18,7 @@ inbounds** at once, with per-client traffic accounting.
|
||||
| **Auth** | Hysteria2 | The client credential. |
|
||||
| **Flow** | VLESS | XTLS flow, e.g. `xtls-rprx-vision`. |
|
||||
| **Limit IP** | all (except TUIC) | Max simultaneous source IPs (enforced via Fail2ban). |
|
||||
| **Total (GB)** | all (except TUIC) | Traffic quota; the client is disabled when exhausted (for TUIC, limits are set at the inbound level). |
|
||||
| **Total (GB)** | all | Traffic quota; the client is disabled when exhausted. |
|
||||
| **Expiry** | all | Date after which the client stops working. |
|
||||
| **Auto renewal** | all | Disabled, fixed interval in days, calendar weekly, or calendar monthly. |
|
||||
| **Telegram ID**| all | Links the client to a Telegram user for self-service/notifications.|
|
||||
|
||||
@@ -64,7 +64,7 @@ The inbound editor accepts these protocols:
|
||||
| **Mixed (SOCKS/HTTP)** | A combined SOCKS + HTTP listener. |
|
||||
| **Dokodemo-door / Tunnel** | Port forwarding / traffic redirect. |
|
||||
| **MTProto** | Telegram MTProto proxy, served by a bundled `mtg` process (not Xray). |
|
||||
| **TUIC** | QUIC-based proxy protocol (v5), served by a bundled `tuic-server` process. See [TUIC](/docs/config/tuic). |
|
||||
| **TUIC** | QUIC-based proxy protocol (v5), served by an in-process native Go server. See [TUIC](/docs/config/tuic). |
|
||||
|
||||
<Callout type="info">
|
||||
Hysteria2 isn't a separate protocol internally — it's the `hysteria` protocol
|
||||
|
||||
@@ -10,10 +10,7 @@ and custom congestion control algorithms to maintain stable connections over los
|
||||
unstable networks.
|
||||
|
||||
<Callout type="info">
|
||||
Like MTProto, TUIC runs as a **managed sidecar process** (`tuic-server` 1.0.0,
|
||||
written in Rust) rather than inside Xray-core. The panel manages the binary
|
||||
lifecycle, generates configurations, monitors process health, and tracks
|
||||
inbound traffic and client online presence.
|
||||
TUIC runs as an **in-process native Go server** inside 3x-ui. Decrypted traffic is bridged into Xray-core via a loopback SOCKS5 tunnel, enabling full Xray routing rules, cascading outbounds (e.g. TUIC → VLESS / WARP), per-client traffic quotas (`totalGB`), and zero-downtime hot user updates without restarting the port.
|
||||
</Callout>
|
||||
|
||||
## Key settings
|
||||
@@ -25,7 +22,7 @@ unstable networks.
|
||||
| **Port** | UDP port for incoming client QUIC connections. |
|
||||
| **Certificate & Key** | Full TLS certificate chain and private key. QUIC mandates TLS encryption; self-signed certificates or valid Let's Encrypt / ACME certs are supported. |
|
||||
| **SNI** | Server Name Indication matching your TLS certificate domain name. |
|
||||
| **Congestion Control** | QUIC congestion control algorithm: `bbr` (recommended for high throughput), `cubic`, or `new_reno`. |
|
||||
| **Congestion Control** | QUIC congestion control algorithm: `bbr` (recommended for high throughput), `cubic`, or `new_reno`. The server runs `bbr` or `new_reno`; `cubic` is sent to clients but served as `new_reno`. |
|
||||
| **ALPN** | Application-Layer Protocol Negotiation tokens (default: `h3`). |
|
||||
| **UDP Relay Mode** | Packet encapsulation mode: `native` (QUIC datagrams, recommended) or `quic`. |
|
||||
| **Zero-RTT Handshake** | Enables 0-RTT connection resumption to eliminate initial handshake round-trips for returning clients. |
|
||||
@@ -102,12 +99,12 @@ TUIC share links use standard URI formatting:
|
||||
tuic://<uuid>:<password>@<host>:<port>?congestion_control=bbr&alpn=h3&sni=vpn.example.com&udp_relay_mode=native&allow_insecure=0#Remark
|
||||
```
|
||||
|
||||
## Architecture & Notes
|
||||
## Architecture & Features
|
||||
|
||||
<Callout type="info">
|
||||
- **Standalone sidecar**: The panel ships pre-compiled `tuic-server` musl binaries on Linux (amd64, arm64, armv7, 386) and executable for Windows.
|
||||
- **Traffic accounting & limits**: The panel owns the inbound's public UDP port with a small relay and runs `tuic-server` behind it on a loopback port, so the inbound's upload and download bytes are counted exactly on every OS and enforced at the **inbound level** (`inbounds.total`); `tuic-server` therefore logs `127.0.0.1` as every client's address. Because upstream `tuic-server` does not provide an internal per-user metrics API, individual client traffic limits (`totalGB`) are not supported for TUIC clients. Client access can be controlled via expiration timestamps (`expiryTime`) and manual enable/disable toggles.
|
||||
- **Online status & "start after first use"**: The panel detects a client's activity from the sidecar's Info log lines (they carry the client UUID), so those features need the inbound's log level at `info` or `debug`; `warn` and `error` silence them.
|
||||
- **Client updates & connections**: Because upstream `tuic-server` lacks dynamic user reload APIs, client modifications (adding, updating, or disabling clients) restart the sidecar process and momentarily reset active connections.
|
||||
- **Deployment**: A TUIC inbound can be created on, or cloned to, a sub-node. The node's own panel runs the sidecar, so the node must run panel v3.8.0 or newer; the master refuses an older node.
|
||||
- **Native in-process Go engine**: TUIC v5 runs 100% natively in Go within the 3x-ui process. No external binaries or sidecars to download or maintain.
|
||||
- **Full Xray routing & cascading**: Decrypted traffic passes directly through Xray's routing engine. Inbound tags (`in-<port>-udp`) work seamlessly with routing rules, domain/IP blocks, and cascading to any outbound proxy (VLESS, Shadowsocks, WARP, etc.).
|
||||
- **Per-client traffic limits & expiration**: Individual traffic quotas (`totalGB`) and expiration timestamps (`expiryTime`) are tracked and enforced for each client.
|
||||
- **Zero-downtime client updates**: Adding, modifying, or disabling clients updates the in-memory user registry instantly without restarting the UDP port or interrupting existing client sessions.
|
||||
- **Deployment**: A TUIC inbound can be created on, or cloned to, a sub-node. The node's own panel runs the TUIC server, so the node must run panel v3.8.0 or newer; the master refuses an older node.
|
||||
</Callout>
|
||||
|
||||
@@ -18,7 +18,7 @@ icon: Users
|
||||
| **Auth** | Hysteria2 | اعتبارنامهی کلاینت. |
|
||||
| **Flow** | VLESS | جریان XTLS، برای مثال `xtls-rprx-vision`. |
|
||||
| **Limit IP** | همه (بهجز TUIC) | بیشینهی تعداد IPهای مبدأ همزمان (با Fail2ban اعمال میشود). |
|
||||
| **Total (GB)** | همه (بهجز TUIC) | سهمیهی ترافیک؛ هنگام اتمام، کلاینت غیرفعال میشود (برای TUIC محدودیت در سطح ورودی تعیین میشود). |
|
||||
| **Total (GB)** | همه | سهمیهی ترافیک؛ هنگام اتمام، کلاینت غیرفعال میشود. |
|
||||
| **Expiry** | همه | تاریخی که پس از آن کلاینت از کار میافتد. |
|
||||
| **Reset** | همه | دورهی تمدید خودکار به **روز** (سهمیه را از نو میچرخاند). |
|
||||
| **Telegram ID**| همه | کلاینت را به یک کاربر Telegram برای سلفسرویس/اعلانها پیوند میدهد.|
|
||||
|
||||
@@ -64,7 +64,7 @@ TLS یا REALITY) را انتخاب کنید. به [انتقالها](/docs/c
|
||||
| **Mixed (SOCKS/HTTP)** | یک شنونده ترکیبی SOCKS + HTTP. |
|
||||
| **Dokodemo-door / Tunnel** | فورواردینگ پورت / هدایت ترافیک. |
|
||||
| **MTProto** | پراکسی MTProto تلگرام که توسط یک فرایند همراه `mtg` سرویس میشود (نه Xray). |
|
||||
| **TUIC** | پروتکل پراکسی مبتنی بر QUIC نسخه ۵ که توسط فرایند `tuic-server` ارائه میشود. مشاهده [TUIC](/docs/config/tuic). |
|
||||
| **TUIC** | پروتکل پراکسی مبتنی بر QUIC نسخه ۵ که به صورت سرور بومی Go درون فرایند ارائه میشود. مشاهده [TUIC](/docs/config/tuic). |
|
||||
|
||||
<Callout type="info">
|
||||
Hysteria2 در سطح داخلی یک پروتکل جداگانه نیست — همان پروتکل `hysteria` است که
|
||||
|
||||
@@ -19,7 +19,7 @@ icon: Users
|
||||
| **Auth** | Hysteria2 | Учётные данные клиента. |
|
||||
| **Flow** | VLESS | Поток XTLS, например `xtls-rprx-vision`. |
|
||||
| **Limit IP** | все (кроме TUIC) | Максимум одновременных IP-адресов источника (контролируется через Fail2ban). |
|
||||
| **Total (GB)** | все (кроме TUIC) | Квота трафика; при исчерпании клиент отключается (для TUIC лимит задаётся на уровне инбаунда). |
|
||||
| **Total (GB)** | все | Квота трафика; при исчерпании клиент отключается. |
|
||||
| **Expiry** | все | Дата, после которой клиент перестаёт работать. |
|
||||
| **Reset** | все | Период автопродления в **днях** (обнуляет квоту). |
|
||||
| **Telegram ID**| все | Привязывает клиента к пользователю Telegram для самообслуживания/уведомлений.|
|
||||
|
||||
@@ -65,7 +65,7 @@ icon: ArrowDownToLine
|
||||
| **Mixed (SOCKS/HTTP)** | Совмещённый слушатель SOCKS + HTTP. |
|
||||
| **Dokodemo-door / Tunnel** | Перенаправление портов / перенаправление трафика. |
|
||||
| **MTProto** | Прокси Telegram MTProto, обслуживаемый встроенным процессом `mtg` (не Xray). |
|
||||
| **TUIC** | Протокол проксирования на базе QUIC (v5), обслуживаемый встроенным процессом `tuic-server`. См. [TUIC](/docs/config/tuic). |
|
||||
| **TUIC** | Протокол проксирования на базе QUIC (v5), обслуживаемый встроенным сервером на Go. См. [TUIC](/docs/config/tuic). |
|
||||
|
||||
<Callout type="info">
|
||||
Hysteria2 внутренне не является отдельным протоколом — это протокол `hysteria`
|
||||
|
||||
@@ -9,10 +9,7 @@ icon: Zap
|
||||
и настраиваемый контроль перегрузок для поддержания стабильной связи на сетях с потерями пакетов.
|
||||
|
||||
<Callout type="info">
|
||||
Как и MTProto, TUIC работает как **изолированный процесс-сайдкар** (`tuic-server` 1.0.0,
|
||||
написан на Rust), а не внутри Xray-core. Панель управляет жизненным циклом бинарника,
|
||||
генерирует конфигурации, отслеживает его состояние, фиксирует общий трафик инбаунда
|
||||
и онлайн-активность клиентов.
|
||||
TUIC работает как **встроенный нативный Go-сервер** прямо внутри процесса 3x-ui. Расшифрованный трафик направляется в ядро Xray-core через локальный SOCKS5-мост, что обеспечивает полную поддержку правил маршрутизации Xray, каскадирования (например, TUIC → VLESS / WARP), персональных квот клиентов (`totalGB`) и горячего обновления пользователей без обрыва соединений.
|
||||
</Callout>
|
||||
|
||||
## Ключевые параметры
|
||||
@@ -24,7 +21,7 @@ icon: Zap
|
||||
| **Порт** | UDP-порт для входящих QUIC-соединений клиентов. |
|
||||
| **Сертификат и ключ** | Полная цепочка SSL-сертификата и приватный ключ. Протокол QUIC требует обязательного шифрования TLS; поддерживаются сертификаты Let's Encrypt / ACME или самоподписанные. |
|
||||
| **SNI** | Имя сервера (Server Name Indication), совпадающее с доменным именем в сертификате. |
|
||||
| **Контроль перегрузок** | Алгоритм контроля перегрузок QUIC: `bbr` (рекомендуется для максимальной скорости), `cubic` или `new_reno`. |
|
||||
| **Контроль перегрузок** | Алгоритм контроля перегрузок QUIC: `bbr` (рекомендуется для максимальной скорости), `cubic` или `new_reno`. Сервер работает с `bbr` или `new_reno`; `cubic` передаётся клиентам, но на сервере применяется как `new_reno`. |
|
||||
| **ALPN** | Токены протоколов уровня приложений (по умолчанию: `h3`). |
|
||||
| **Режим UDP Relay** | Режим инкапсуляции пакетов: `native` (QUIC datagrams, рекомендуется) или `quic`. |
|
||||
| **Zero-RTT Handshake** | Включает 0-RTT возобновление сессий для мгновенного повторного подключения клиентов без ожидания завершения рукопожатия. |
|
||||
@@ -101,12 +98,12 @@ proxies:
|
||||
tuic://<uuid>:<password>@<host>:<port>?congestion_control=bbr&alpn=h3&sni=vpn.example.com&udp_relay_mode=native&allow_insecure=0#Remark
|
||||
```
|
||||
|
||||
## Архитектура и примечания
|
||||
## Архитектура и возможности
|
||||
|
||||
<Callout type="info">
|
||||
- **Автономный сайдкар**: Панель поставляется со скомпилированными статическими `musl`-бинарниками `tuic-server` для Linux (amd64, arm64, armv7, 386) и исполняемым файлом для Windows.
|
||||
- **Учёт трафика и лимиты**: Панель сама занимает публичный UDP-порт инбаунда небольшим relay и запускает `tuic-server` за ним на loopback-порту, поэтому входящие и исходящие байты инбаунда считаются точно на любой ОС и ограничиваются на **уровне инбаунда** (`inbounds.total`); в логах `tuic-server` адресом каждого клиента будет `127.0.0.1`. Поскольку апстрим `tuic-server` не предоставляет внутреннего API метрик по отдельным пользователям, персональные квоты трафика (`totalGB`) для клиентов TUIC не поддерживаются. Доступ клиентов контролируется по сроку действия (`expiryTime`) и переключателю активности.
|
||||
- **Статус онлайн и «старт после первого использования»**: Панель определяет активность клиента по строкам Info в логе сайдкара (в них есть UUID клиента), поэтому этим функциям нужен уровень логов `info` или `debug`; `warn` и `error` их отключают.
|
||||
- **Изменения клиентов и соединения**: Поскольку апстрим `tuic-server` не поддерживает динамическую перезагрузку пользователей без перезапуска, любое изменение списка клиентов (добавление, редактирование или отключение) перезапускает процесс сайдкара и кратковременно сбрасывает активные соединения.
|
||||
- **Развёртывание**: Инбаунд TUIC можно создать на дочернем узле или клонировать туда. Sidecar запускает панель самого узла, поэтому на узле нужна панель v3.8.0 или новее; более старый узел главная панель отклоняет.
|
||||
- **Нативный Go-движок**: TUIC v5 работает на 100% нативно на Go внутри процесса 3x-ui. Никаких внешних сторонних бинарников скачивать не требуется.
|
||||
- **Маршрутизация и каскады в Xray**: Трафик проходит через движок маршрутизации Xray. Теги инбаундов (`in-<port>-udp`) полноценно участвуют в правилах маршрутизации (Routing Rules), блокировках geosite/geoip и перенаправлении в любые аутбаунды (VLESS, Shadowsocks, WARP и др.).
|
||||
- **Персональные квоты трафика**: Лимиты трафика (`totalGB`) и сроки действия (`expiryTime`) учитываются и применяются индивидуально для каждого клиента.
|
||||
- **Горячее обновление без обрыва связи**: Добавление, редактирование или отключение клиентов обновляет реестр пользователей в памяти без перезапуска порта и без сброса активных сессий других пользователей.
|
||||
- **Развёртывание**: Инбаунд TUIC можно создать на дочернем узле или клонировать туда. TUIC-сервер запускает панель самого узла, поэтому на узле нужна панель v3.8.0 или новее; более старый узел главная панель отклоняет.
|
||||
</Callout>
|
||||
|
||||
@@ -17,7 +17,7 @@ icon: Users
|
||||
| **Auth** | Hysteria2 | 客户端凭据。 |
|
||||
| **Flow** | VLESS | XTLS 流控,例如 `xtls-rprx-vision`。 |
|
||||
| **Limit IP** | 全部(TUIC 除外) | 最大同时连接的源 IP 数量(通过 Fail2ban 强制执行)。 |
|
||||
| **Total (GB)** | 全部(TUIC 除外) | 流量配额;用尽后客户端将被禁用(对于 TUIC,限制在入站级别设置)。 |
|
||||
| **Total (GB)** | 全部 | 流量配额;用尽后客户端将被禁用。 |
|
||||
| **Expiry** | 全部 | 该日期之后客户端停止工作。 |
|
||||
| **自动续期** | 全部 | 关闭、固定天数、日历每周或日历每月。 |
|
||||
| **Telegram ID**| 全部 | 将客户端关联到 Telegram 用户,用于自助服务/通知。 |
|
||||
|
||||
@@ -61,7 +61,7 @@ icon: ArrowDownToLine
|
||||
| **Mixed (SOCKS/HTTP)** | SOCKS + HTTP 的组合监听器。 |
|
||||
| **Dokodemo-door / Tunnel** | 端口转发 / 流量重定向。 |
|
||||
| **MTProto** | Telegram MTProto 代理,由内置的 `mtg` 进程提供(而非 Xray)。 |
|
||||
| **TUIC** | 基于 QUIC 的代理协议(v5),由内置的 `tuic-server` 进程提供。参见 [TUIC](/docs/config/tuic)。 |
|
||||
| **TUIC** | 基于 QUIC 的代理协议(v5),由进程内原生 Go 服务器提供。参见 [TUIC](/docs/config/tuic)。 |
|
||||
|
||||
<Callout type="info">
|
||||
在内部,Hysteria2 并不是一个独立的协议——它是把传输版本设为 2 的 `hysteria`
|
||||
|
||||
Reference in New Issue
Block a user