mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 12:44:22 +00:00
Xray panel supporting multi-protocol multi-user expire day & traffic & ip limit (Vmess & Vless & Trojan & ShadowSocks & Wireguard)
dokodemo-doorfail2banhttprealityshadowsocksshadowsocks2022socks5trojanutlsvlessvmesswireguardxtlsxtls-rprx-visionxtls-rprx-vision-udp443
Account-based inbounds (Socks/Mixed/HTTP) keep their credentials in
`settings.accounts[]` — an array of plain {user, pass} objects — while
every other inbound (vless/vmess/trojan/shadowsocks/hysteria/…) keeps
them in `settings.clients[]`, the rich Client struct with id, email,
sub-id, totalGB, expiry, traffic-reset cadence, etc.
The whole client lifecycle on InboundService (AddInboundClient,
UpdateInboundClient, DelInboundClient, CopyInboundClients) was written
against the latter shape, and several of those methods do an unchecked
`settings["clients"].([]any)` cast on the way in. If anything ever
managed to call them against a SOCKS5 inbound the panel would panic
straight out of the goroutine.
In practice the UI itself can't get there — `dbinbound.isMultiUser()`
returns false for SOCKS, which already gates the ClientRowTable,
"add client" menu, copy-clients menu, etc. — but the HTTP API is
addressable directly, the Telegram bot path is independent, and a
future feature could easily plug into one of those entry points and
hit the cast. Defense in depth is cheap here.
Backend
-------
* Add `model.IsAccountBased(p Protocol) bool` covering Socks, Mixed
and HTTP. WireGuard is *not* in the set — its peers live under
`settings.peers[]` and are managed through a separate code path
that already knows about them.
* AddInboundClient / UpdateInboundClient / DelInboundClient now load
the target inbound up front and bail out with a clear, actionable
error when the protocol is account-based, instead of falling into
the unchecked clients cast. The error message points the caller at
the right escape hatch ("update the inbound directly with
settings.accounts[] instead").
* CopyInboundClients refuses account-based inbounds on either side
of the copy — neither direction has well-defined semantics
(downcasting a rich client to {user, pass} silently drops
sub-id/totalGB/expiry; upcasting the other way invents fields the
runtime can't honor).
Tests
-----
* TestIsAccountBased pins the protocol set, including the explicit
WireGuard-excluded and lowercase-invariant cases.
* TestAddInboundClient_RejectsSocks, TestUpdateInboundClient_RejectsSocks,
TestDelInboundClient_RejectsSocks: the three guards must fire on a
SOCKS inbound seeded with a realistic settings.accounts[] payload.
* TestCopyInboundClients_RejectsSocksSource and ...Target: both
directions are refused.
* TestAddInboundClient_AllowsVless: sanity check that the guard does
not fire on a client-based protocol — if this ever flipped the
feature would be broken for everyone, not just SOCKS users.
Other scenarios reviewed (no code changes needed):
* Routing rules — keyed off inbound tag, protocol-agnostic.
* Balancers — outbound-tag based, untouched by inbound protocol.
* Outbound side — frontend already exposes SOCKS as an outbound
with user/pass through the existing OutboundFormModal.
* Depletion / traffic reset / disable-invalid-clients — driven by
SQL queries on the client_traffics table, which is naturally empty
for account-based inbounds (they never create rows there).
* SetInboundEnable — operates on the inbound table directly, no
per-client surgery, safe for SOCKS.
* Sub-link generators (sub/subService, subJsonService, subClashService)
— already return empty for SOCKS/Mixed/HTTP/Tunnel/WireGuard.
* Frontend client modals (ClientFormModal, ClientRowTable,
ClientBulkModal, CopyClientsModal) — gated upstream by
`dbInbound.isMultiUser()`, which is false for SOCKS.
|
||
|---|---|---|
| .github | ||
| .vscode | ||
| config | ||
| database | ||
| frontend | ||
| logger | ||
| media | ||
| sub | ||
| util | ||
| web | ||
| windows_files | ||
| xray | ||
| .env.example | ||
| .gitignore | ||
| .nvmrc | ||
| CONTRIBUTING.md | ||
| docker-compose.yml | ||
| DockerEntrypoint.sh | ||
| Dockerfile | ||
| DockerInit.sh | ||
| go.mod | ||
| go.sum | ||
| install.sh | ||
| LICENSE | ||
| main.go | ||
| README.ar_EG.md | ||
| README.es_ES.md | ||
| README.fa_IR.md | ||
| README.md | ||
| README.ru_RU.md | ||
| README.zh_CN.md | ||
| update.sh | ||
| x-ui.rc | ||
| x-ui.service.arch | ||
| x-ui.service.debian | ||
| x-ui.service.rhel | ||
| x-ui.sh | ||
English | فارسی | العربية | 中文 | Español | Русский
3X-UI — advanced, open-source web-based control panel designed for managing Xray-core server. It offers a user-friendly interface for configuring and monitoring various VPN and proxy protocols.
Important
This project is only for personal usage, please do not use it for illegal purposes, and please do not use it in a production environment.
As an enhanced fork of the original X-UI project, 3X-UI provides improved stability, broader protocol support, and additional features.
Quick Start
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
For full documentation, please visit the project Wiki.
A Special Thanks to
Acknowledgment
- Iran v2ray rules (License: GPL-3.0): Enhanced v2ray/xray and v2ray/xray-clients routing rules with built-in Iranian domains and a focus on security and adblocking.
- Russia v2ray rules (License: GPL-3.0): This repository contains automatically updated V2Ray routing rules based on data on blocked domains and addresses in Russia.
Community Tools
Tools and integrations built by the community around 3x-ui.
- terraform-provider-3x-ui (License: MIT): Manage inbounds, clients, panel settings, and Xray configuration as code with Terraform / OpenTofu.
Support project
If this project is helpful to you, you may wish to give it a🌟