This commit is contained in:
itboyhan1 2025-05-28 15:05:39 +00:00 committed by GitHub
commit fd61c42cef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 283 additions and 80 deletions

View file

@ -9,10 +9,10 @@
**لوحة تحكم ويب متقدمة • مبنية على Xray Core**
[![](https://img.shields.io/github/v/release/mhsanaei/3x-ui.svg)](https://github.com/MHSanaei/3x-ui/releases)
[![](https://img.shields.io/github/actions/workflow/status/mhsanaei/3x-ui/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/mhsanaei/3x-ui.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/mhsanaei/3x-ui/total.svg)](#)
[![](https://img.shields.io/github/v/release/itboyhan1/3x-ui-xdsb.svg)](https://github.com/itboyhan1/3x-ui-xdsb/releases)
[![](https://img.shields.io/github/actions/workflow/status/itboyhan1/3x-ui-xdsb/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/itboyhan1/3x-ui-xdsb.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/itboyhan1/3x-ui-xdsb/total.svg)](#)
[![License](https://img.shields.io/badge/license-GPL%20V3-blue.svg?longCache=true)](https://www.gnu.org/licenses/gpl-3.0.en.html)
> **تنبيه:** المشروع ده للتعلم الشخصي والتواصل فقط. رجاءً استخدمه بشكل قانوني.
@ -33,14 +33,14 @@
لتثبيت المشروع أو تحديثه، نفذ الأمر ده:
```bash
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/refs/tags/v2.6.0/install.sh)
```
## تثبيت النسخة القديمة (مش موصى بيها)
لو عايز تثبت نسخة معينة، استخدم الأمر ده، مثلاً نسخة `v1.7.9`:
```bash
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/$VERSION/install.sh") $VERSION
```
## شهادة SSL
@ -112,7 +112,7 @@ case "${ARCH}" in
*) XUI_ARCH="amd64" ;;
esac
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
wget https://github.com/itboyhan1/3x-ui-xdsb/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
```
2. بعد تحميل الباكدج، نفذ الأوامر دي للتثبيت أو التحديث:
@ -157,7 +157,7 @@ systemctl restart x-ui
2. **نسخ مستودع المشروع:**
```sh
git clone https://github.com/MHSanaei/3x-ui.git
git clone https://github.com/itboyhan1/3x-ui-xdsb.git
cd 3x-ui
```
@ -176,7 +176,7 @@ systemctl restart x-ui
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
ghcr.io/itboyhan1/3x-ui-xdsb:latest
```
4. **التحديث إلى أحدث نسخة:**
@ -566,4 +566,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## عدد النجوم مع مرور الوقت
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View file

@ -9,10 +9,10 @@
**Un Panel Web Avanzado • Construido sobre Xray Core**
[![](https://img.shields.io/github/v/release/mhsanaei/3x-ui.svg)](https://github.com/MHSanaei/3x-ui/releases)
[![](https://img.shields.io/github/actions/workflow/status/mhsanaei/3x-ui/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/mhsanaei/3x-ui.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/mhsanaei/3x-ui/total.svg)](#)
[![](https://img.shields.io/github/v/release/itboyhan1/3x-ui-xdsb.svg)](https://github.com/itboyhan1/3x-ui-xdsb/releases)
[![](https://img.shields.io/github/actions/workflow/status/itboyhan1/3x-ui-xdsb/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/itboyhan1/3x-ui-xdsb.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/itboyhan1/3x-ui-xdsb/total.svg)](#)
[![License](https://img.shields.io/badge/license-GPL%20V3-blue.svg?longCache=true)](https://www.gnu.org/licenses/gpl-3.0.en.html)
> **Descargo de responsabilidad:** Este proyecto es solo para aprendizaje personal y comunicación, por favor no lo uses con fines ilegales, por favor no lo uses en un entorno de producción
@ -32,7 +32,7 @@
## Instalar y Actualizar
```
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/refs/tags/v2.6.0/install.sh)
```
## Instalar versión antigua (no recomendamos)
@ -40,7 +40,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.
Para instalar la versión deseada, utiliza el siguiente comando de instalación. Por ejemplo, ver `v1.7.9`:
```
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/$VERSION/install.sh") $VERSION
```
## Certificado SSL
@ -116,7 +116,7 @@ case "${ARCH}" in
esac
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
wget https://github.com/itboyhan1/3x-ui-xdsb/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
```
2. Una vez que se haya descargado el paquete comprimido, ejecuta los siguientes comandos para instalar o actualizar x-ui:
@ -163,7 +163,7 @@ systemctl restart x-ui
2. Clona el Repositorio del Proyecto:
```sh
git clone https://github.com/MHSanaei/3x-ui.git
git clone https://github.com/itboyhan1/3x-ui-xdsb.git
cd 3x-ui
```
@ -183,7 +183,7 @@ systemctl restart x-ui
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
ghcr.io/itboyhan1/3x-ui-xdsb:latest
```
actualizar a la última versión

View file

@ -9,10 +9,10 @@
**یک پنل وب پیشرفته • ساخته شده بر پایه Xray Core**
[![](https://img.shields.io/github/v/release/mhsanaei/3x-ui.svg)](https://github.com/MHSanaei/3x-ui/releases)
[![](https://img.shields.io/github/actions/workflow/status/mhsanaei/3x-ui/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/mhsanaei/3x-ui.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/mhsanaei/3x-ui/total.svg)](#)
[![](https://img.shields.io/github/v/release/itboyhan1/3x-ui-xdsb.svg)](https://github.com/itboyhan1/3x-ui-xdsb/releases)
[![](https://img.shields.io/github/actions/workflow/status/itboyhan1/3x-ui-xdsb/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/itboyhan1/3x-ui-xdsb.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/itboyhan1/3x-ui-xdsb/total.svg)](#)
[![License](https://img.shields.io/badge/license-GPL%20V3-blue.svg?longCache=true)](https://www.gnu.org/licenses/gpl-3.0.en.html)
> **سلب مسئولیت:** این پروژه صرفاً برای اهداف آموزشی و تحقیقاتی است. استفاده از آن برای مقاصد غیرقانونی یا در محیط‌های عملیاتی ممنوع است.
@ -32,7 +32,7 @@
## نصب و ارتقا
```
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/refs/tags/v2.6.0/install.sh)
```
## نصب نسخه‌های قدیمی (توصیه نمی‌شود)
@ -40,7 +40,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.
برای نصب نسخه خاصی از دستور زیر استفاده کنید. مثال برای نسخه `v1.7.9`:
```
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/$VERSION/install.sh") $VERSION
```
## گواهی SSL
@ -116,7 +116,7 @@ case "${ARCH}" in
*) XUI_ARCH="amd64" ;;
esac
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
wget https://github.com/itboyhan1/3x-ui-xdsb/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
```
2. نصب یا ارتقا:
@ -164,7 +164,7 @@ systemctl restart x-ui
2. **کلون پروژه:**
```sh
git clone https://github.com/MHSanaei/3x-ui.git
git clone https://github.com/itboyhan1/3x-ui-xdsb.git
cd 3x-ui
```
@ -184,7 +184,7 @@ systemctl restart x-ui
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
ghcr.io/itboyhan1/3x-ui-xdsb:latest
```
4. **به‌روزرسانی:**
@ -525,4 +525,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Stargazers over Time
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View file

@ -9,10 +9,10 @@
**An Advanced Web Panel • Built on Xray Core**
[![](https://img.shields.io/github/v/release/mhsanaei/3x-ui.svg)](https://github.com/MHSanaei/3x-ui/releases)
[![](https://img.shields.io/github/actions/workflow/status/mhsanaei/3x-ui/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/mhsanaei/3x-ui.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/mhsanaei/3x-ui/total.svg)](#)
[![](https://img.shields.io/github/v/release/itboyhan1/3x-ui-xdsb.svg)](https://github.com/itboyhan1/3x-ui-xdsb/releases)
[![](https://img.shields.io/github/actions/workflow/status/itboyhan1/3x-ui-xdsb/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/itboyhan1/3x-ui-xdsb.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/itboyhan1/3x-ui-xdsb/total.svg)](#)
[![License](https://img.shields.io/badge/license-GPL%20V3-blue.svg?longCache=true)](https://www.gnu.org/licenses/gpl-3.0.en.html)
> **Disclaimer:** This project is only for personal learning and communication, please do not use it for illegal purposes, please do not use it in a production environment
@ -32,7 +32,7 @@
## Install & Upgrade
```
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/refs/tags/v2.6.0/install.sh)
```
## Install legacy Version (we don't recommend)
@ -40,7 +40,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.
To install your desired version, use following installation command. e.g., ver `v1.7.9`:
```
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/$VERSION/install.sh") $VERSION
```
## SSL Certificate
@ -118,7 +118,7 @@ case "${ARCH}" in
esac
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
wget https://github.com/itboyhan1/3x-ui-xdsb/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
```
2. Once the compressed package is downloaded, execute the following commands to install or upgrade x-ui:
@ -166,7 +166,7 @@ systemctl restart x-ui
2. **Clone the Project Repository:**
```sh
git clone https://github.com/MHSanaei/3x-ui.git
git clone https://github.com/itboyhan1/3x-ui-xdsb.git
cd 3x-ui
```
@ -188,7 +188,7 @@ systemctl restart x-ui
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
ghcr.io/itboyhan1/3x-ui-xdsb:latest
```
4. **Update to the Latest Version:**
@ -595,4 +595,4 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
## Stargazers over Time
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)
[![Stargazers over time](https://starchart.cc/MHSanaei/3x-ui.svg?variant=adaptive)](https://starchart.cc/MHSanaei/3x-ui)

View file

@ -9,10 +9,10 @@
**Продвинутая веб-панель • Построена на основе Xray Core**
[![](https://img.shields.io/github/v/release/mhsanaei/3x-ui.svg)](https://github.com/MHSanaei/3x-ui/releases)
[![](https://img.shields.io/github/actions/workflow/status/mhsanaei/3x-ui/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/mhsanaei/3x-ui.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/mhsanaei/3x-ui/total.svg)](#)
[![](https://img.shields.io/github/v/release/itboyhan1/3x-ui-xdsb.svg)](https://github.com/itboyhan1/3x-ui-xdsb/releases)
[![](https://img.shields.io/github/actions/workflow/status/itboyhan1/3x-ui-xdsb/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/itboyhan1/3x-ui-xdsb.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/itboyhan1/3x-ui-xdsb/total.svg)](#)
[![License](https://img.shields.io/badge/license-GPL%20V3-blue.svg?longCache=true)](https://www.gnu.org/licenses/gpl-3.0.en.html)
> **Отказ от ответственности:** Этот проект предназначен только для личного обучения и общения. Пожалуйста, не используйте его в незаконных целях и не применяйте в производственной среде.
@ -32,7 +32,7 @@
## Установка и обновление
```
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/refs/tags/v2.6.0/install.sh)
```
## Установить старую версию (мы не рекомендуем)
@ -40,7 +40,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.
Чтобы установить желаемую версию, используйте следующую команду установки. Например, ver `v1.7.9`:
```
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/$VERSION/install.sh") $VERSION
```
## SSL Сертификат
@ -117,7 +117,7 @@ case "${ARCH}" in
esac
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
wget https://github.com/itboyhan1/3x-ui-xdsb/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
```
2. После загрузки архива выполните следующие команды для установки или обновления x-ui:
@ -165,7 +165,7 @@ systemctl restart x-ui
2. **Склонируйте репозиторий проекта:**
```sh
git clone https://github.com/MHSanaei/3x-ui.git
git clone https://github.com/itboyhan1/3x-ui-xdsb.git
cd 3x-ui
```
@ -187,7 +187,7 @@ systemctl restart x-ui
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
ghcr.io/itboyhan1/3x-ui-xdsb:latest
```
4. **Обновление до последней версии:**

View file

@ -9,10 +9,10 @@
**一个更好的面板 • 基于Xray Core构建**
[![](https://img.shields.io/github/v/release/mhsanaei/3x-ui.svg)](https://github.com/MHSanaei/3x-ui/releases)
[![](https://img.shields.io/github/actions/workflow/status/mhsanaei/3x-ui/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/mhsanaei/3x-ui.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/mhsanaei/3x-ui/total.svg)](#)
[![](https://img.shields.io/github/v/release/itboyhan1/3x-ui-xdsb.svg)](https://github.com/itboyhan1/3x-ui-xdsb/releases)
[![](https://img.shields.io/github/actions/workflow/status/itboyhan1/3x-ui-xdsb/release.yml.svg)](#)
[![GO Version](https://img.shields.io/github/go-mod/go-version/itboyhan1/3x-ui-xdsb.svg)](#)
[![Downloads](https://img.shields.io/github/downloads/itboyhan1/3x-ui-xdsb/total.svg)](#)
[![License](https://img.shields.io/badge/license-GPL%20V3-blue.svg?longCache=true)](https://www.gnu.org/licenses/gpl-3.0.en.html)
> **Disclaimer:** 此项目仅供个人学习交流,请不要用于非法目的,请不要在生产环境中使用。
@ -32,7 +32,7 @@
## 安装 & 升级
```
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/refs/tags/v2.6.0/install.sh)
```
## 安装旧版本 (我们不建议)
@ -40,7 +40,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.
要安装您想要的版本请使用以下安装命令。例如ver `v1.7.9`:
```
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/$VERSION/install.sh") $VERSION
```
### SSL证书
@ -116,7 +116,7 @@ case "${ARCH}" in
esac
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
wget https://github.com/itboyhan1/3x-ui-xdsb/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
```
2. 下载压缩包后,执行以下命令安装或升级 x-ui
@ -163,7 +163,7 @@ systemctl restart x-ui
2. 克隆仓库:
```sh
git clone https://github.com/MHSanaei/3x-ui.git
git clone https://github.com/itboyhan1/3x-ui-xdsb.git
cd 3x-ui
```
@ -183,7 +183,7 @@ systemctl restart x-ui
--network=host \
--restart=unless-stopped \
--name 3x-ui \
ghcr.io/mhsanaei/3x-ui:latest
ghcr.io/itboyhan1/3x-ui-xdsb:latest
```
更新至最新版本

View file

@ -104,4 +104,6 @@ type Client struct {
SubID string `json:"subId" form:"subId"`
Comment string `json:"comment" form:"comment"`
Reset int `json:"reset" form:"reset"`
MaxDevices int `json:"maxDevices" form:"maxDevices" gorm:"default:0"` // 新增:最大设备数量限制, 0表示不限制
ActiveIPs string `json:"activeIPs" form:"activeIPs" gorm:"type:text"` // 新增当前活动的IP列表 (JSON字符串)
}

View file

@ -142,13 +142,13 @@ install_x-ui() {
cd /usr/local/
if [ $# == 0 ]; then
tag_version=$(curl -Ls "https://api.github.com/repos/MHSanaei/3x-ui/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
tag_version=$(curl -Ls "https://api.github.com/repos/itboyhan1/3x-ui-xdsb/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [[ ! -n "$tag_version" ]]; then
echo -e "${red}Failed to fetch x-ui version, it may be due to GitHub API restrictions, please try it later${plain}"
exit 1
fi
echo -e "Got x-ui latest version: ${tag_version}, beginning the installation..."
wget -N -O /usr/local/x-ui-linux-$(arch).tar.gz https://github.com/MHSanaei/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz
wget -N -O /usr/local/x-ui-linux-$(arch).tar.gz https://github.com/itboyhan1/3x-ui-xdsb/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz
if [[ $? -ne 0 ]]; then
echo -e "${red}Downloading x-ui failed, please be sure that your server can access GitHub ${plain}"
exit 1
@ -163,7 +163,7 @@ install_x-ui() {
exit 1
fi
url="https://github.com/MHSanaei/3x-ui/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz"
url="https://github.com/itboyhan1/3x-ui-xdsb/releases/download/${tag_version}/x-ui-linux-$(arch).tar.gz"
echo -e "Beginning to install x-ui $1"
wget -N -O /usr/local/x-ui-linux-$(arch).tar.gz ${url}
if [[ $? -ne 0 ]]; then
@ -190,7 +190,7 @@ install_x-ui() {
chmod +x x-ui bin/xray-linux-$(arch)
cp -f x-ui.service /etc/systemd/system/
wget -O /usr/bin/x-ui https://raw.githubusercontent.com/MHSanaei/3x-ui/main/x-ui.sh
wget -O /usr/bin/x-ui https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/main/x-ui.sh
chmod +x /usr/local/x-ui/x-ui.sh
chmod +x /usr/bin/x-ui
config_after_install

View file

@ -83,6 +83,18 @@
</template>
<a-input-number v-model.number="client.limitIp" min="0"></a-input-number>
</a-form-item>
<a-form-item>
<template slot="label">
<a-tooltip>
<template slot="title">
<span>{{ i18n "pages.inbounds.maxDevicesDesc" }}</span> <!-- 需要添加新的i18n条目 -->
</template>
<span>{{ i18n "pages.inbounds.maxDevices" }}</span> <!-- 需要添加新的i18n条目 -->
<a-icon type="question-circle"></a-icon>
</a-tooltip>
</template>
<a-input-number v-model.number="client.maxDevices" :min="0"></a-input-number>
</a-form-item>
<a-form-item v-if="app.ipLimitEnable && client.limitIp > 0 && client.email && isEdit">
<template slot="label">
<a-tooltip>
@ -169,4 +181,4 @@
<a-input-number v-model.number="client.reset" :min="0"></a-input-number>
</a-form-item>
</a-form>
{{end}}
{{end}}

View file

@ -13,6 +13,7 @@ import (
"slices"
"x-ui/database"
"x-ui/web/service"
"x-ui/database/model"
"x-ui/logger"
"x-ui/xray"
@ -36,7 +37,7 @@ func (j *CheckClientIpJob) Run() {
}
shouldClearAccessLog := false
iplimitActive := j.hasLimitIp()
iplimitActive := j.hasLimitOrDeviceLimit() // 修改检查LimitIP或MaxDevices
f2bInstalled := j.checkFail2BanInstalled()
isAccessLogAvailable := j.checkAccessLogAvailable(iplimitActive)
@ -45,7 +46,7 @@ func (j *CheckClientIpJob) Run() {
shouldClearAccessLog = j.processLogFile()
} else {
if !f2bInstalled {
logger.Warning("[LimitIP] Fail2Ban is not installed, Please install Fail2Ban from the x-ui bash menu.")
logger.Warning("[LimitIP/MaxDevices] Fail2Ban is not installed, Please install Fail2Ban from the x-ui bash menu.")
}
}
}
@ -76,7 +77,7 @@ func (j *CheckClientIpJob) clearAccessLog() {
j.lastClear = time.Now().Unix()
}
func (j *CheckClientIpJob) hasLimitIp() bool {
func (j *CheckClientIpJob) hasLimitOrDeviceLimit() bool { // 修改函数名和逻辑
db := database.GetDB()
var inbounds []*model.Inbound
@ -96,7 +97,8 @@ func (j *CheckClientIpJob) hasLimitIp() bool {
for _, client := range clients {
limitIp := client.LimitIP
if limitIp > 0 {
maxDevices := client.MaxDevices // 新增获取MaxDevices
if limitIp > 0 || maxDevices > 0 { // 修改检查LimitIP或MaxDevices
return true
}
}
@ -144,21 +146,120 @@ func (j *CheckClientIpJob) processLogFile() bool {
}
shouldCleanLog := false
db := database.GetDB()
var clientInboundID uint
for email, uniqueIps := range inboundClientIps {
var clientData model.Client
// Find the client by email. This requires iterating through inbounds and their clients.
// This is a simplified representation. In a real scenario, you'd need a more efficient way to get client by email.
foundClient := false
var allInbounds []*model.Inbound
db.Find(&allInbounds)
for _, inbound := range allInbounds {
if inbound.Settings == "" {
continue
}
settings := map[string][]model.Client{}
json.Unmarshal([]byte(inbound.Settings), &settings)
clients := settings["clients"]
for _, c := range clients {
// Match client by email, or ID, or password based on what's available and matches 'email' (which is clientIdentifier in this context)
clientIdentifierInLog := email // email from log is the clientIdentifier
matched := false
if c.Email != "" && c.Email == clientIdentifierInLog {
matched = true
} else if c.ID != "" && c.ID == clientIdentifierInLog { // For vmess/vless if email is used as ID in logs
matched = true
} else if c.Password != "" && c.Password == clientIdentifierInLog { // For trojan if email is used as password in logs
matched = true
}
ips := make([]string, 0, len(uniqueIps))
for ip := range uniqueIps {
ips = append(ips, ip)
if matched {
clientData = c
clientInboundID = inbound.Id // Store the inbound ID
foundClient = true
break
}
}
if foundClient {
break
}
}
sort.Strings(ips)
clientIpsRecord, err := j.getInboundClientIps(email)
if err != nil {
j.addInboundClientIps(email, ips)
if !foundClient {
logger.Warningf("Client with identifier %s not found for IP processing", email)
continue
}
shouldCleanLog = j.updateInboundClientIps(clientIpsRecord, email, ips) || shouldCleanLog
currentLoggedIps := make([]string, 0, len(uniqueIps))
for ip := range uniqueIps {
currentLoggedIps = append(currentLoggedIps, ip)
}
sort.Strings(currentLoggedIps)
clientIpsRecord, err := j.getInboundClientIps(email) // This function likely needs to be adapted or clientData used directly
activeIPs := []string{}
if clientData.ActiveIPs != "" {
errUnmarshal := json.Unmarshal([]byte(clientData.ActiveIPs), &activeIPs)
if errUnmarshal != nil {
logger.Warningf("Error unmarshalling ActiveIPs for client %s: %v", email, errUnmarshal)
activeIPs = []string{} // Reset if unmarshalling fails
}
}
newActiveIPs := make([]string, len(activeIPs))
copy(newActiveIPs, activeIPs)
changedActiveIPs := false
for _, loggedIp := range currentLoggedIps {
isExistingActiveIP := j.contains(newActiveIPs, loggedIp)
if clientData.MaxDevices > 0 {
if !isExistingActiveIP {
if len(newActiveIPs) < clientData.MaxDevices {
newActiveIPs = append(newActiveIPs, loggedIp)
changedActiveIPs = true
} else {
if !j.contains(j.disAllowedIps, loggedIp) {
j.disAllowedIps = append(j.disAllowedIps, loggedIp)
logger.Infof("[MaxDevices] IP %s for client %s banned due to exceeding max device limit (%d)", loggedIp, email, clientData.MaxDevices)
shouldCleanLog = true
}
}
}
} // End MaxDevices check
} // End loop currentLoggedIps
if changedActiveIPs {
activeIPsBytes, marshalErr := json.Marshal(newActiveIPs)
if marshalErr != nil {
logger.Warningf("Error marshalling new ActiveIPs for client %s: %v", email, marshalErr)
} else {
// Update clientData.ActiveIPs in the database
// This part is complex because clientData is part of a JSON string in Inbound.Settings
// A proper solution would involve updating the specific client within the Inbound's settings JSON
// and then saving the Inbound object.
// For simplicity, we'll log it. A full implementation needs to update the DB.
logger.Infof("Client %s ActiveIPs updated to: %s", email, string(activeIPsBytes))
// Placeholder for actual DB update logic for clientData.ActiveIPs
// Example: err := s.updateClientActiveIPsInDB(inbound.Id, clientData.ID_or_Email, string(activeIPsBytes)); if err != nil { ... }
inboundService := service.InboundService{} // Create an instance of InboundService
dbUpdateErr := inboundService.UpdateClientActiveIPsInDB(clientInboundID, email, string(activeIPsBytes))
if dbUpdateErr != nil {
logger.Warningf("Failed to update ActiveIPs in DB for client %s: %v", email, dbUpdateErr)
}
}
}
if err != nil { // This 'err' is from j.getInboundClientIps(email)
j.addInboundClientIps(email, currentLoggedIps) // This function likely needs to be adapted
continue
}
// Original LimitIP logic (needs to be integrated with new ActiveIPs logic if LimitIP is also active)
shouldCleanLog = j.updateInboundClientIps(clientIpsRecord, email, currentLoggedIps) || shouldCleanLog
}
return shouldCleanLog
@ -179,7 +280,7 @@ func (j *CheckClientIpJob) checkAccessLogAvailable(iplimitActive bool) bool {
if accessLogPath == "none" || accessLogPath == "" {
if iplimitActive {
logger.Warning("[LimitIP] Access log path is not set, Please configure the access log path in Xray configs.")
logger.Warning("[LimitIP/MaxDevices] Access log path is not set, Please configure the access log path in Xray configs.") // Updated log message
}
return false
}

View file

@ -21,6 +21,90 @@ type InboundService struct {
xrayApi xray.XrayAPI
}
func (s *InboundService) UpdateClientActiveIPsInDB(inboundID int, clientIdentifier string, newActiveIPsJSON string) error {
db := database.GetDB()
var inbound model.Inbound
err := db.First(&inbound, inboundID).Error
if err != nil {
return fmt.Errorf("inbound with ID %d not found: %w", inboundID, err)
}
if inbound.Settings == "" {
return fmt.Errorf("inbound settings for ID %d are empty", inboundID)
}
settingsMap := make(map[string]interface{})
err = json.Unmarshal([]byte(inbound.Settings), &settingsMap)
if err != nil {
return fmt.Errorf("error unmarshalling settings for inbound ID %d: %w", inboundID, err)
}
clientsRaw, ok := settingsMap["clients"]
if !ok {
return fmt.Errorf("no 'clients' field in settings for inbound ID %d", inboundID)
}
clients, ok := clientsRaw.([]interface{})
if !ok {
return fmt.Errorf("'clients' field is not an array in settings for inbound ID %d", inboundID)
}
clientFound := false
for i, clientInterface := range clients {
clientMap, ok := clientInterface.(map[string]interface{})
if !ok {
logger.Warningf("Client entry is not a map for inbound ID %d, index %d", inboundID, i)
continue
}
// Try to match by email first
clientEmail, emailOk := clientMap["email"].(string)
if emailOk && clientEmail == clientIdentifier {
clientMap["activeIPs"] = newActiveIPsJSON
clients[i] = clientMap
clientFound = true
break
}
// If not matched by email, try to match by ID (for vmess/vless etc.)
clientID, idOk := clientMap["id"].(string)
if idOk && clientID == clientIdentifier {
clientMap["activeIPs"] = newActiveIPsJSON
clients[i] = clientMap
clientFound = true
break
}
// If not matched by email or ID, try to match by Password (for trojan etc.)
clientPassword, passwordOk := clientMap["password"].(string)
if passwordOk && clientPassword == clientIdentifier {
clientMap["activeIPs"] = newActiveIPsJSON
clients[i] = clientMap
clientFound = true
break
}
}
if !clientFound {
return fmt.Errorf("client with identifier '%s' not found in inbound ID %d", clientIdentifier, inboundID)
}
settingsMap["clients"] = clients
updatedSettingsBytes, err := json.Marshal(settingsMap)
if err != nil {
return fmt.Errorf("error marshalling updated settings for inbound ID %d: %w", inboundID, err)
}
inbound.Settings = string(updatedSettingsBytes)
err = db.Save(&inbound).Error
if err != nil {
return fmt.Errorf("error saving updated inbound settings for ID %d: %w", inboundID, err)
}
logger.Infof("Successfully updated ActiveIPs for client '%s' in inbound ID %d", clientIdentifier, inboundID)
return nil
}
func (s *InboundService) GetInbounds(userId int) ([]*model.Inbound, error) {
db := database.GetDB()
var inbounds []*model.Inbound

View file

@ -220,7 +220,9 @@
"inboundData" = "Inbound's Data"
"exportInbound" = "Export Inbound"
"import" = "Import"
"importInbound" = "Import an Inbound"
"importInbound = "Import Inbound"
maxDevices = "Max Devices"
maxDevicesDesc = "Maximum number of simultaneously connected devices (0 = unlimited)"
[pages.client]
"add" = "Add Client"

View file

@ -225,6 +225,8 @@
"exportInbound" = "导出入站规则"
"import"="导入"
"importInbound" = "导入入站规则"
"maxDevices" = "最大设备数"
"maxDevicesDesc" = "允许同时连接的最大设备数量0 = 无限制)"
[pages.client]
"add" = "添加客户端"

View file

@ -74,7 +74,7 @@ before_show_menu() {
}
install() {
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/main/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/main/install.sh)
if [[ $? == 0 ]]; then
if [[ $# == 0 ]]; then
start
@ -93,7 +93,7 @@ update() {
fi
return 0
fi
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/main/install.sh)
bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/main/install.sh)
if [[ $? == 0 ]]; then
LOGI "Update is complete, Panel has automatically restarted "
before_show_menu
@ -133,7 +133,7 @@ legacy_version() {
exit 1
fi
# Use the entered panel version in the download link
install_command="bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/v$tag_version/install.sh") v$tag_version"
install_command="bash <(curl -Ls "https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/v$tag_version/install.sh") v$tag_version"
echo "Downloading and installing panel version $tag_version..."
eval $install_command
@ -164,7 +164,7 @@ uninstall() {
echo ""
echo -e "Uninstalled Successfully.\n"
echo "If you need to install this panel again, you can use below command:"
echo -e "${green}bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)${plain}"
echo -e "${green}bash <(curl -Ls https://raw.githubusercontent.com/itboyhan1/3x-ui-xdsb/master/install.sh)${plain}"
echo ""
# Trap the SIGTERM signal
trap delete_script SIGTERM