3X-UI:强大的Xray-core网页管理面板
项目描述
3X-UI是一个基于网页的高级开源控制面板,专为管理Xray-core服务器而设计。作为原始X-UI项目的增强版本,它提供了用户友好的界面,用于配置和监控各种VPN和代理协议,包括VMess、VLESS、Trojan、Shadowsocks等。
重要提示:本项目仅用于个人使用和通信,请勿将其用于非法目的,请勿在生产环境中使用。
功能特性
- 多协议支持:全面支持VMess、VLESS、Trojan、Shadowsocks等多种代理协议
- 网页管理界面:直观的Web-based控制面板,无需命令行操作
- 流量监控:实时监控用户流量使用情况,支持流量限制和到期时间设置
- 客户端管理:细粒度的客户端管理,支持多用户配置
- 安全特性:集成Fail2Ban支持,防止暴力破解攻击
- 订阅服务:自动生成订阅链接,支持多种客户端订阅
- 多语言支持:支持中文、英文、波斯语、阿拉伯语等多种语言界面
- 自动化安装:提供一键安装脚本,简化部署过程
安装指南
系统要求
- Linux操作系统(Ubuntu、Debian、CentOS等)
- GLIBC 2.32或更高版本
- root权限
一键安装
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
手动安装
- 下载对应架构的Xray-core二进制文件
- 配置数据库和运行环境
- 启动Web服务
依赖项
- Xray-core v25.6.8或更高版本
- SQLite数据库
- 必要的系统工具(wget、curl、tar等)
使用说明
基本使用
- 访问面板:安装完成后,通过浏览器访问服务器IP和端口(默认端口:2053)
- 登录系统:使用默认用户名和密码(admin/admin)登录
- 配置入站协议:在"Inbounds"页面添加和配置代理协议
- 管理客户端:为每个入站协议添加和管理用户客户端
- 监控流量:在仪表板查看实时流量和使用情况
示例配置
创建VMess入站示例:
{
"protocol": "vmess",
"port": 443,
"settings": {
"clients": [
{
"id": "自动生成的UUID",
"email": "user@example.com",
"enable": true
}
]
},
"streamSettings": {
"network": "ws",
"security": "tls"
}
}
API使用
3X-UI提供RESTful API接口,支持程序化管理:
# 获取所有入站配置
curl -X POST http://localhost:2053/panel/api/inbounds/list \
-H "Authorization: Bearer <token>"
核心代码
主程序入口
package main
import (
"x-ui/config"
"x-ui/database"
"x-ui/logger"
"x-ui/web"
"x-ui/web/global"
)
func runWebServer() {
// 初始化日志系统
logger.InitLogger(logging.INFO)
// 初始化数据库
err := database.InitDB(config.GetDBPath())
if err != nil {
log.Fatalf("Error initializing database: %v", err)
}
// 启动Web服务器
server := web.NewServer()
global.SetWebServer(server)
err = server.Start()
if err != nil {
log.Fatalf("Error starting web server: %v", err)
}
}
数据库模型
package database
import (
"gorm.io/gorm"
"x-ui/database/model"
)
// 初始化数据表结构
func initModels() error {
models := []any{
&model.User{}, // 用户表
&model.Inbound{}, // 入站配置表
&model.Setting{}, // 系统设置表
&model.InboundClientIps{}, // 客户端IP记录表
}
for _, model := range models {
if err := db.AutoMigrate(model); err != nil {
return err
}
}
return nil
}
// 初始化默认用户
func initUser() error {
user := &model.User{
Username: "admin",
Password: "加密后的密码",
}
return db.Create(user).Error
}
Xray配置生成
package xray
// 生成Xray配置文件
func GenerateConfig(inbounds []*model.Inbound) (string, error) {
config := map[string]interface{}{
"log": map[string]interface{}{
"loglevel": "warning",
},
"inbounds": generateInboundsConfig(inbounds),
"outbounds": generateOutboundsConfig(),
"routing": generateRoutingConfig(),
}
configJson, err := json.MarshalIndent(config, "", " ")
if err != nil {
return "", err
}
return string(configJson), nil
}
// 生成入站配置
func generateInboundsConfig(inbounds []*model.Inbound) []interface{} {
var configInbounds []interface{}
for _, inbound := range inbounds {
if !inbound.Enable {
continue
}
inboundConfig := map[string]interface{}{
"port": inbound.Port,
"protocol": inbound.Protocol,
"settings": inbound.Settings,
"sniffing": map[string]interface{}{
"enabled": true,
"destOverride": []string{"http", "tls"},
},
}
configInbounds = append(configInbounds, inboundConfig)
}
return configInbounds
}
订阅服务
package sub
// 处理订阅请求
func (s *SubService) GetSubs(subId string, host string) ([]string, string, error) {
inbounds, err := s.getInboundsBySubId(subId)
if err != nil {
return nil, "", err
}
var result []string
for _, inbound := range inbounds {
clients, err := s.inboundService.GetClients(inbound)
if err != nil {
continue
}
for _, client := range clients {
if client.Enable && client.SubID == subId {
link := s.getLink(inbound, client.Email)
result = append(result, link)
}
}
}
// 返回Base64编码的订阅内容
if s.subEncrypt {
return []string{base64.StdEncoding.EncodeToString([]byte(strings.Join(result, "\n")))}, header, nil
}
return result, header, nil
}
流量统计
package job
// 流量统计任务
func (j *XrayTrafficJob) Run() {
if !j.xrayService.IsXrayRunning() {
return
}
// 获取流量数据
traffics, clientTraffics, err := j.xrayService.GetXrayTraffic()
if err != nil {
return
}
// 更新数据库中的流量统计
err, needRestart0 := j.inboundService.AddTraffic(traffics, clientTraffics)
if err != nil {
logger.Warning("add inbound traffic failed:", err)
}
// 如果需要重启服务
if needRestart0 {
j.xrayService.SetToNeedRestart()
}
}