Merge branch 'main' into fix/two-factor-reset
2
.github/workflows/release.yml
vendored
|
@ -97,7 +97,7 @@ jobs:
|
||||||
cd x-ui/bin
|
cd x-ui/bin
|
||||||
|
|
||||||
# Download dependencies
|
# Download dependencies
|
||||||
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.5.16/"
|
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v25.6.8/"
|
||||||
if [ "${{ matrix.platform }}" == "amd64" ]; then
|
if [ "${{ matrix.platform }}" == "amd64" ]; then
|
||||||
wget -q ${Xray_URL}Xray-linux-64.zip
|
wget -q ${Xray_URL}Xray-linux-64.zip
|
||||||
unzip Xray-linux-64.zip
|
unzip Xray-linux-64.zip
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# Start fail2ban
|
# Start fail2ban
|
||||||
[ $X_UI_ENABLE_FAIL2BAN == "true" ] && fail2ban-client -x start
|
[ $XUI_ENABLE_FAIL2BAN == "true" ] && fail2ban-client -x start
|
||||||
|
|
||||||
# Run x-ui
|
# Run x-ui
|
||||||
exec /app/x-ui
|
exec /app/x-ui
|
||||||
|
|
|
@ -27,7 +27,7 @@ case $1 in
|
||||||
esac
|
esac
|
||||||
mkdir -p build/bin
|
mkdir -p build/bin
|
||||||
cd build/bin
|
cd build/bin
|
||||||
wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.5.16/Xray-linux-${ARCH}.zip"
|
wget -q "https://github.com/XTLS/Xray-core/releases/download/v25.6.8/Xray-linux-${ARCH}.zip"
|
||||||
unzip "Xray-linux-${ARCH}.zip"
|
unzip "Xray-linux-${ARCH}.zip"
|
||||||
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
|
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
|
||||||
mv xray "xray-linux-${FNAME}"
|
mv xray "xray-linux-${FNAME}"
|
||||||
|
|
|
@ -48,7 +48,7 @@ RUN chmod +x \
|
||||||
/app/x-ui \
|
/app/x-ui \
|
||||||
/usr/bin/x-ui
|
/usr/bin/x-ui
|
||||||
|
|
||||||
ENV X_UI_ENABLE_FAIL2BAN="true"
|
ENV XUI_ENABLE_FAIL2BAN="true"
|
||||||
VOLUME [ "/etc/x-ui" ]
|
VOLUME [ "/etc/x-ui" ]
|
||||||
CMD [ "./x-ui" ]
|
CMD [ "./x-ui" ]
|
||||||
ENTRYPOINT [ "/app/DockerEntrypoint.sh" ]
|
ENTRYPOINT [ "/app/DockerEntrypoint.sh" ]
|
||||||
|
|
577
README.ar_EG.md
|
@ -7,17 +7,39 @@
|
||||||
</picture>
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**لوحة تحكم ويب متقدمة • مبنية على Xray Core**
|
[](https://github.com/MHSanaei/3x-ui/releases)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/actions)
|
||||||
|
[](#)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/releases/latest)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
[](https://github.com/MHSanaei/3x-ui/releases)
|
**3X-UI** — لوحة تحكم متقدمة مفتوحة المصدر تعتمد على الويب مصممة لإدارة خادم Xray-core. توفر واجهة سهلة الاستخدام لتكوين ومراقبة بروتوكولات VPN والوكيل المختلفة.
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
|
||||||
|
|
||||||
> **تنبيه:** المشروع ده للتعلم الشخصي والتواصل فقط. رجاءً استخدمه بشكل قانوني.
|
> [!IMPORTANT]
|
||||||
|
> هذا المشروع مخصص للاستخدام الشخصي والاتصال فقط، يرجى عدم استخدامه لأغراض غير قانونية، يرجى عدم استخدامه في بيئة الإنتاج.
|
||||||
|
|
||||||
**لو المشروع عجبك وساعدك، ممكن تدعمنا بعمل** :star2:
|
كمشروع محسن من مشروع X-UI الأصلي، يوفر 3X-UI استقرارًا محسنًا ودعمًا أوسع للبروتوكولات وميزات إضافية.
|
||||||
|
|
||||||
|
## البدء السريع
|
||||||
|
|
||||||
|
```
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
للحصول على الوثائق الكاملة، يرجى زيارة [ويكي المشروع](https://github.com/MHSanaei/3x-ui/wiki).
|
||||||
|
|
||||||
|
## شكر خاص إلى
|
||||||
|
|
||||||
|
- [alireza0](https://github.com/alireza0/)
|
||||||
|
|
||||||
|
## الاعتراف
|
||||||
|
|
||||||
|
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (الترخيص: **GPL-3.0**): _قواعد توجيه v2ray/xray و v2ray/xray-clients المحسنة مع النطاقات الإيرانية المدمجة وتركيز على الأمان وحظر الإعلانات._
|
||||||
|
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (الترخيص: **GPL-3.0**): _يحتوي هذا المستودع على قواعد توجيه V2Ray محدثة تلقائيًا بناءً على بيانات النطاقات والعناوين المحظورة في روسيا._
|
||||||
|
|
||||||
|
## دعم المشروع
|
||||||
|
|
||||||
|
**إذا كان هذا المشروع مفيدًا لك، فقد ترغب في إعطائه**:star2:
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
||||||
|
@ -29,541 +51,6 @@
|
||||||
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
||||||
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
||||||
|
|
||||||
## التثبيت والتحديث
|
## النجوم عبر الزمن
|
||||||
|
|
||||||
لتثبيت المشروع أو تحديثه، نفذ الأمر ده:
|
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||||
```bash
|
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/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
|
|
||||||
```
|
|
||||||
|
|
||||||
## شهادة SSL
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل شهادة SSL</summary>
|
|
||||||
|
|
||||||
### ACME
|
|
||||||
|
|
||||||
عشان تدير شهادات SSL باستخدام ACME:
|
|
||||||
|
|
||||||
1. تأكد إن الدومين بتاعك متربط صح بالسيرفر.
|
|
||||||
2. شغّل أمر `x-ui` في الترمينال واختار خيار "إدارة شهادات SSL".
|
|
||||||
3. هتلاقي الخيارات دي:
|
|
||||||
- **Get SSL:** الحصول على شهادة SSL.
|
|
||||||
- **Revoke:** إلغاء شهادة SSL موجودة.
|
|
||||||
- **Force Renew:** تجديد شهادة SSL بالقوة.
|
|
||||||
- **Show Existing Domains:** عرض كل شهادات الدومين المتوفرة على السيرفر.
|
|
||||||
- **Set Certificate Paths for the Panel:** تعيين مسارات الشهادة عشان البانل يستخدمها.
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
لتثبيت واستخدام Certbot:
|
|
||||||
```sh
|
|
||||||
apt-get install certbot -y
|
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
|
||||||
certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloudflare
|
|
||||||
|
|
||||||
السكريبت بتاع الإدارة فيه آلية مدمجة للتقديم على شهادة SSL من خلال Cloudflare. عشان تستخدمها، هتحتاج:
|
|
||||||
- بريد إلكتروني مسجل على Cloudflare.
|
|
||||||
- الـ Global API Key بتاع Cloudflare.
|
|
||||||
- الدومين لازم يكون مربوط للسيرفر الحالي عن طريق Cloudflare.
|
|
||||||
|
|
||||||
**كيفية الحصول على Global API Key من Cloudflare:**
|
|
||||||
|
|
||||||
1. شغّل أمر `x-ui` في الترمينال واختار "Cloudflare SSL Certificate".
|
|
||||||
2. ادخل على [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens).
|
|
||||||
3. دوس على "View Global API Key" (شوف الصورة التوضيحية):
|
|
||||||

|
|
||||||
4. يمكن تحتاج تعيد تسجيل الدخول، وبعدها هتظهر الـ API Key (شوف الصورة التوضيحية):
|
|
||||||

|
|
||||||
|
|
||||||
عند الاستخدام، ادخل اسم الدومين، البريد الإلكتروني، وAPI Key. المخطط كالتالي:
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## التثبيت والتحديث يدويًا
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل التثبيت اليدوي</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
1. لتحميل أحدث نسخة من الباكدج المظغوطة مباشرة على السيرفر، نفذ الأمر التالي:
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
2. بعد تحميل الباكدج، نفذ الأوامر دي للتثبيت أو التحديث:
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cd /root/
|
|
||||||
rm -rf x-ui/ /usr/local/x-ui/ /usr/bin/x-ui
|
|
||||||
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
|
||||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
|
||||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
|
||||||
mv x-ui/ /usr/local/
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable x-ui
|
|
||||||
systemctl restart x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## التثبيت باستخدام Docker
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل Docker</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
1. **تثبيت Docker:**
|
|
||||||
```sh
|
|
||||||
bash <(curl -sSL https://get.docker.com)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **نسخ مستودع المشروع:**
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
|
||||||
cd 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **تشغيل الخدمة:**
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
ممكن تضيف الخيار ```--pull always``` عشان Docker يسحب أحدث صورة لو موجودة. (راجع [مستندات Docker](https://docs.docker.com/reference/cli/docker/container/run/#pull) للمزيد من التفاصيل).
|
|
||||||
|
|
||||||
**أو**
|
|
||||||
```sh
|
|
||||||
docker run -itd \
|
|
||||||
-e XRAY_VMESS_AEAD_FORCED=false \
|
|
||||||
-v $PWD/db/:/etc/x-ui/ \
|
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--network=host \
|
|
||||||
--restart=unless-stopped \
|
|
||||||
--name 3x-ui \
|
|
||||||
ghcr.io/mhsanaei/3x-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **التحديث إلى أحدث نسخة:**
|
|
||||||
```sh
|
|
||||||
cd 3x-ui
|
|
||||||
docker compose down
|
|
||||||
docker compose pull 3x-ui
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **إزالة 3x-ui من Docker:**
|
|
||||||
```sh
|
|
||||||
docker stop 3x-ui
|
|
||||||
docker rm 3x-ui
|
|
||||||
cd --
|
|
||||||
rm -r 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## إعدادات Nginx
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض إعدادات البروكسي العكسي (Reverse Proxy)</summary>
|
|
||||||
|
|
||||||
#### Reverse Proxy باستخدام Nginx
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### استخدام Nginx مع sub-path
|
|
||||||
- تأكد إن "URI Path" في إعدادات `/sub` للبانل متطابق.
|
|
||||||
- لازم يكون رابط `url` في إعدادات البانل منتهي بـ `/`.
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location /sub {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## نظام التشغيل الموصى به
|
|
||||||
|
|
||||||
- Ubuntu 22.04+
|
|
||||||
- Debian 12+
|
|
||||||
- CentOS 8+
|
|
||||||
- OpenEuler 22.03+
|
|
||||||
- Fedora 36+
|
|
||||||
- Arch Linux
|
|
||||||
- Parch Linux
|
|
||||||
- Manjaro
|
|
||||||
- Armbian
|
|
||||||
- AlmaLinux 9.5+
|
|
||||||
- Rocky Linux 9.5+
|
|
||||||
- Oracle Linux 8+
|
|
||||||
- OpenSUSE Tubleweed
|
|
||||||
- Amazon Linux 2023
|
|
||||||
- Virtuozzo Linux 8+
|
|
||||||
- Windows x64
|
|
||||||
|
|
||||||
## المعماريات والأجهزة المدعومة
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل المعماريات والأجهزة المدعومة</summary>
|
|
||||||
|
|
||||||
منصتنا بتدعم مجموعة متنوعة من المعماريات والأجهزة عشان تناسب بيئات مختلفة. أبرز المعماريات هي:
|
|
||||||
|
|
||||||
- **amd64:** المعمارية القياسية للكمبيوترات الشخصية والسيرفرات.
|
|
||||||
- **x86 / i386:** مستخدمة على نطاق واسع في أجهزة الديسكتوب واللاب توب.
|
|
||||||
- **armv8 / arm64 / aarch64:** موجهة للأجهزة المحمولة والمضمنة زي Raspberry Pi 4, Raspberry Pi 3, Raspberry Pi Zero 2/Zero 2 W, Orange Pi 3 LTS، وغيرها.
|
|
||||||
- **armv7 / arm / arm32:** للأجهزة المحمولة والأجهزة المضمنة القديمة، مثل Orange Pi Zero LTS, Orange Pi PC Plus, Raspberry Pi 2.
|
|
||||||
- **armv6 / arm / arm32:** للأجهزة المضمنة القديمة جداً، زي Raspberry Pi 1, Raspberry Pi Zero/Zero W.
|
|
||||||
- **armv5 / arm / arm32:** معمارية أقدم مرتبطة بالأنظمة المضمنة القديمة.
|
|
||||||
- **s390x:** مستخدمة في الحواسيب الرئيسية من IBM وتوفر أداء عالي واعتمادية للمشاريع الكبيرة.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## اللغات
|
|
||||||
|
|
||||||
- English (إنجليزي)
|
|
||||||
- Persian (فارسي)
|
|
||||||
- Traditional Chinese (الصيني التقليدي)
|
|
||||||
- Simplified Chinese (الصيني المبسط)
|
|
||||||
- Japanese (ياباني)
|
|
||||||
- Russian (روسي)
|
|
||||||
- Vietnamese (فيتنامي)
|
|
||||||
- Spanish (إسباني)
|
|
||||||
- Indonesian (إندونيسي)
|
|
||||||
- Ukrainian (أوكراني)
|
|
||||||
- Turkish (تركي)
|
|
||||||
- Português (Brazil) (برتغالي - البرازيل)
|
|
||||||
|
|
||||||
## الميزات
|
|
||||||
|
|
||||||
- مراقبة حالة النظام
|
|
||||||
- البحث داخل كل الإدخالات والعملاء
|
|
||||||
- ثيم داكن وفاتح
|
|
||||||
- دعم تعدد المستخدمين والبروتوكولات
|
|
||||||
- دعم بروتوكولات زي VMESS، VLESS، Trojan، Shadowsocks، Dokodemo-door، Socks، HTTP، wireguard
|
|
||||||
- دعم بروتوكولات XTLS الأصلية مثل RPRX-Direct، Vision، REALITY
|
|
||||||
- إحصائيات الترافيك، تحديد حد للترافيك، وتحديد فترة انتهاء الصلاحية
|
|
||||||
- قوالب إعدادات Xray قابلة للتخصيص
|
|
||||||
- دعم لوحة تحكم عبر HTTPS (بإستخدام الدومين الخاص وشهادة SSL)
|
|
||||||
- دعم التقديم على شهادات SSL بلمسة واحدة والتجديد التلقائي
|
|
||||||
- لمزيد من إعدادات التخصيص المتقدمة، راجع إعدادات البانل
|
|
||||||
- إصلاح مسارات الـ API (سيتم إنشاء إعدادات للمستخدم مع الـ API)
|
|
||||||
- دعم تغيير الإعدادات من خلال الخيارات المتوفرة في البانل
|
|
||||||
- دعم تصدير/استيراد قاعدة البيانات من خلال البانل
|
|
||||||
|
|
||||||
## إعدادات البانل الافتراضية
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل الإعدادات الافتراضية</summary>
|
|
||||||
|
|
||||||
### اسم المستخدم، الباسورد، البورت ومسار الويب الأساسي
|
|
||||||
|
|
||||||
لو مش هتعدل الإعدادات دي، هتتولد تلقائياً (ده مش بينطبق على Docker).
|
|
||||||
|
|
||||||
**الإعدادات الافتراضية لـ Docker:**
|
|
||||||
- **اسم المستخدم:** admin
|
|
||||||
- **الباسورد:** admin
|
|
||||||
- **البورت:** 2053
|
|
||||||
|
|
||||||
### إدارة قاعدة البيانات:
|
|
||||||
|
|
||||||
ممكن تعمل نسخ احتياطية واسترجاع لقاعدة البيانات مباشرة من البانل.
|
|
||||||
|
|
||||||
- **مسار قاعدة البيانات:**
|
|
||||||
- `/etc/x-ui/x-ui.db`
|
|
||||||
|
|
||||||
### المسار الأساسي للويب
|
|
||||||
|
|
||||||
1. **إعادة تعيين المسار الأساسي:**
|
|
||||||
- افتح الترمينال.
|
|
||||||
- نفذ أمر `x-ui`.
|
|
||||||
- اختار خيار "إعادة تعيين المسار الأساسي للويب".
|
|
||||||
|
|
||||||
2. **توليد أو تخصيص المسار:**
|
|
||||||
- المسار هيتولد تلقائياً، أو ممكن تدخل مسار مخصص.
|
|
||||||
|
|
||||||
3. **عرض الإعدادات الحالية:**
|
|
||||||
- لمشاهدة الإعدادات الحالية، نفذ أمر `x-ui settings` في الترمينال أو استخدم خيار "عرض الإعدادات الحالية" في البانل.
|
|
||||||
|
|
||||||
### توصية الأمان:
|
|
||||||
- لتحسين الأمان، استخدم كلمة طويلة وعشوائية في مسار URL الخاص بالبانل.
|
|
||||||
|
|
||||||
**مثال:**
|
|
||||||
- `http://ip:port/*webbasepath*/panel`
|
|
||||||
- `http://domain:port/*webbasepath*/panel`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## إعداد WARP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل إعداد WARP</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
**لإصدارات `v2.1.0` وما بعدها:**
|
|
||||||
|
|
||||||
WARP مدمج ومش محتاج تثبيت إضافي. فعل الإعدادات المطلوبة من خلال البانل.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## تحديد IP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل تحديد IP</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
**ملحوظة:** تحديد IP ممكن مايشتغلش صح مع IP Tunnel.
|
|
||||||
|
|
||||||
- **للإصدارات حتى `v1.6.1`:**
|
|
||||||
- تحديد IP مدمج في البانل.
|
|
||||||
|
|
||||||
**للإصدارات `v1.7.0` وما بعدها:**
|
|
||||||
|
|
||||||
لتفعيل وظيفة تحديد IP، هتحتاج تثبيت `fail2ban` والملفات المطلوبة من خلال الخطوات دي:
|
|
||||||
|
|
||||||
1. شغل أمر `x-ui` في الترمينال واختار "إدارة تحديد IP".
|
|
||||||
2. هتلاقي الخيارات التالية:
|
|
||||||
- **تغيير مدة الحظر:** لتعديل مدة الحظر.
|
|
||||||
- **رفع الحظر عن الجميع:** لإلغاء كل الحظر الحالي.
|
|
||||||
- **عرض السجلات:** لمراجعة السجلات.
|
|
||||||
- **حالة Fail2ban:** لمراجعة حالة fail2ban.
|
|
||||||
- **إعادة تشغيل Fail2ban:** لإعادة تشغيل خدمة fail2ban.
|
|
||||||
- **إلغاء تثبيت Fail2ban:** لإلغاء تثبيت fail2ban مع إعداداته.
|
|
||||||
|
|
||||||
3. حدد مسار سجل الوصول على البانل من خلال ضبط `Xray Configs/log/Access log` على `./access.log` ثم احفظ وأعد تشغيل x-ui.
|
|
||||||
|
|
||||||
- **للإصدارات قبل `v2.1.3`:**
|
|
||||||
- هتحتاج تضبط مسار سجل الوصول يدويًا في إعدادات Xray:
|
|
||||||
```sh
|
|
||||||
"log": {
|
|
||||||
"access": "./access.log",
|
|
||||||
"dnsLog": false,
|
|
||||||
"loglevel": "warning"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- **للإصدارات `v2.1.3` وما بعدها:**
|
|
||||||
- في خيار لضبط `access.log` مباشرة من البانل.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## بوت Telegram
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل بوت Telegram</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
تدعم لوحة التحكم إشعارات بترافيك يومي، تسجيل الدخول للبانل، نسخ احتياطية للقاعدة، حالة النظام، معلومات العملاء، وغيرها من الوظائف عن طريق بوت Telegram. عشان تستخدم البوت، لازم تضبط معلمات البوت في البانل، ومن ضمنهم:
|
|
||||||
- توكن Telegram
|
|
||||||
- ID شات الأدمن (يمكن إدخال أكثر من واحد بفواصل)
|
|
||||||
- وقت الإشعار (باستخدام صيغة cron)
|
|
||||||
- إشعار بتاريخ انتهاء الصلاحية
|
|
||||||
- إشعار حد الترافيك
|
|
||||||
- نسخ احتياطية للقاعدة
|
|
||||||
- إشعار حمل المعالج
|
|
||||||
|
|
||||||
**صيغة مرجعية:**
|
|
||||||
|
|
||||||
- `30 * * * * *` - إشعار عند الـ 30 ثانية من كل دقيقة.
|
|
||||||
- `0 */10 * * * *` - إشعار عند أول ثانية من كل 10 دقايق.
|
|
||||||
- `@hourly` - إشعار كل ساعة.
|
|
||||||
- `@daily` - إشعار يومي (في تمام منتصف الليل).
|
|
||||||
- `@weekly` - إشعار أسبوعي.
|
|
||||||
- `@every 8h` - إشعار كل 8 ساعات.
|
|
||||||
|
|
||||||
### ميزات بوت Telegram
|
|
||||||
|
|
||||||
- تقارير دورية.
|
|
||||||
- إشعارات عند تسجيل الدخول.
|
|
||||||
- إشعار عند تجاوز حمل المعالج.
|
|
||||||
- تنبيهات قبل انتهاء الصلاحية أو وصول حد الترافيك.
|
|
||||||
- دعم قوائم تقارير العملاء لو تم إضافة اسم مستخدم Telegram للمستخدم في الإعدادات.
|
|
||||||
- إمكانية البحث عن تقرير الترافيك باستخدام UUID (VMESS/VLESS) أو الباسورد (TROJAN) بشكل مجهول.
|
|
||||||
- بوت يعتمد على القوائم.
|
|
||||||
- البحث عن العملاء بالإيميل (للأدمن فقط).
|
|
||||||
- استعراض كافة الإدخالات.
|
|
||||||
- عرض حالة السيرفر.
|
|
||||||
- استعراض العملاء المستنفدين.
|
|
||||||
- استقبال النسخ الاحتياطية عند الطلب وفي التقارير الدورية.
|
|
||||||
- بوت متعدد اللغات.
|
|
||||||
|
|
||||||
### إعداد بوت Telegram
|
|
||||||
|
|
||||||
- ابدأ [Botfather](https://t.me/BotFather) في حساب Telegram بتاعك:
|
|
||||||

|
|
||||||
|
|
||||||
- أنشئ بوت جديد باستخدام أمر /newbot: هيسألك سؤالين، اسم للبوت واسم مستخدم (لازم ينتهي بكلمة "bot").
|
|
||||||

|
|
||||||
|
|
||||||
- شغل البوت اللي أنشأته. هتلاقي رابط البوت بعد كده.
|
|
||||||

|
|
||||||
|
|
||||||
- ادخل على البانل واضبط إعدادات بوت Telegram زي ما هو موضح:
|
|
||||||

|
|
||||||
|
|
||||||
ادخل توكن البوت في الحقل رقم 3.
|
|
||||||
ادخل ID المستخدم في الحقل رقم 4. الحسابات اللي بالـ ID ده هيبقى ليها صلاحية الأدمن. (يمكن إدخال أكثر من واحد بفواصل)
|
|
||||||
|
|
||||||
- كيفية الحصول على ID حساب Telegram؟ استخدم [هذا البوت](https://t.me/useridinfobot). شغله وهيدي الـ ID بتاعك.
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## مسارات API
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل مسارات API</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
- [توثيق الـ API](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
|
|
||||||
- `/login` مع بيانات المستخدم باستخدام `POST`: `{username: '', password: ''}` لتسجيل الدخول.
|
|
||||||
- المسار الأساسي لـ `/panel/api/inbounds` للعمليات التالية:
|
|
||||||
|
|
||||||
| الطريقة | المسار | الفعل |
|
|
||||||
| :-----: | ------------------------------------ | ------------------------------------------ |
|
|
||||||
| `GET` | `"/list"` | استرجاع كل الإدخالات |
|
|
||||||
| `GET` | `"/get/:id"` | استرجاع إدخال بالـ id |
|
|
||||||
| `GET` | `"/getClientTraffics/:email"` | استرجاع ترافيك عميل بالإيميل |
|
|
||||||
| `GET` | `"/getClientTrafficsById/:id"` | استرجاع ترافيك عميل بالـ id |
|
|
||||||
| `GET` | `"/createbackup"` | البوت بيرسل نسخة احتياطية للأدمن |
|
|
||||||
| `POST` | `"/add"` | إضافة إدخال |
|
|
||||||
| `POST` | `"/del/:id"` | حذف إدخال |
|
|
||||||
| `POST` | `"/update/:id"` | تحديث إدخال |
|
|
||||||
| `POST` | `"/clientIps/:email"` | استرجاع عنوان IP للعميل |
|
|
||||||
| `POST` | `"/clearClientIps/:email"` | مسح عنوان IP للعميل |
|
|
||||||
| `POST` | `"/addClient"` | إضافة عميل للإدخال |
|
|
||||||
| `POST` | `"/:id/delClient/:clientId"` | حذف عميل باستخدام clientId\* |
|
|
||||||
| `POST` | `"/updateClient/:clientId"` | تحديث بيانات عميل باستخدام clientId\* |
|
|
||||||
| `POST` | `"/:id/resetClientTraffic/:email"` | إعادة ضبط ترافيك عميل |
|
|
||||||
| `POST` | `"/resetAllTraffics"` | إعادة ضبط الترافيك لكل الإدخالات |
|
|
||||||
| `POST` | `"/resetAllClientTraffics/:id"` | إعادة ضبط ترافيك كل العملاء في إدخال معين |
|
|
||||||
| `POST` | `"/delDepletedClients/:id"` | حذف العملاء المستنفدين في الإدخال (-1: الكل) |
|
|
||||||
| `POST` | `"/onlines"` | استرجاع قائمة العملاء الأونلاين (الإيميلات) |
|
|
||||||
|
|
||||||
\*- بالنسبة لحقل `clientId`:
|
|
||||||
- استخدم `client.id` لـ VMESS و VLESS.
|
|
||||||
- استخدم `client.password` لـ TROJAN.
|
|
||||||
- استخدم `client.email` لـ Shadowsocks.
|
|
||||||
|
|
||||||
- [](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## المتغيرات البيئية
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>اضغط لعرض تفاصيل المتغيرات البيئية</summary>
|
|
||||||
|
|
||||||
#### الاستخدام
|
|
||||||
|
|
||||||
| المتغير | النوع | القيمة الافتراضية |
|
|
||||||
| ---------------- | :--------------------------------------------: | ------------------: |
|
|
||||||
| XUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
|
||||||
| XUI_DEBUG | `boolean` | `false` |
|
|
||||||
| XUI_BIN_FOLDER | `string` | `"bin"` |
|
|
||||||
| XUI_DB_FOLDER | `string` | `"/etc/x-ui"` |
|
|
||||||
| XUI_LOG_FOLDER | `string` | `"/var/log"` |
|
|
||||||
|
|
||||||
مثال:
|
|
||||||
```sh
|
|
||||||
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## المعاينة
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/01-overview-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/02-inbounds-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/04-add-client-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/05-settings-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/06-configs-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/07-bot-light.png">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## شكر خاص لـ
|
|
||||||
|
|
||||||
- [alireza0](https://github.com/alireza0/)
|
|
||||||
|
|
||||||
## التحيات
|
|
||||||
|
|
||||||
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (الرخصة: **GPL-3.0**): _قواعد محدثة لتوجيهات v2ray/xray مع تضمين دومينات إيرانية وتركيز على الأمان وحجب الإعلانات._
|
|
||||||
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (الرخصة: **GPL-3.0**): _المستودع ده بيحتوي على قواعد توجيه v2ray/xray محدثة تلقائيًا بناءً على بيانات الدومينات والعناوين المحظورة في روسيا._
|
|
||||||
|
|
||||||
## عدد النجوم مع مرور الوقت
|
|
||||||
|
|
||||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
|
||||||
|
|
597
README.es_ES.md
|
@ -7,17 +7,39 @@
|
||||||
</picture>
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**Un Panel Web Avanzado • Construido sobre Xray Core**
|
[](https://github.com/MHSanaei/3x-ui/releases)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/actions)
|
||||||
|
[](#)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/releases/latest)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
[](https://github.com/MHSanaei/3x-ui/releases)
|
**3X-UI** — panel de control avanzado basado en web de código abierto diseñado para gestionar el servidor Xray-core. Ofrece una interfaz fácil de usar para configurar y monitorear varios protocolos VPN y proxy.
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](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
|
> [!IMPORTANT]
|
||||||
|
> Este proyecto es solo para uso personal y comunicación, por favor no lo use para fines ilegales, por favor no lo use en un entorno de producción.
|
||||||
|
|
||||||
**Si este proyecto te es útil, podrías considerar darle una**:star2:
|
Como una versión mejorada del proyecto X-UI original, 3X-UI proporciona mayor estabilidad, soporte más amplio de protocolos y características adicionales.
|
||||||
|
|
||||||
|
## Inicio Rápido
|
||||||
|
|
||||||
|
```
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
Para documentación completa, visita la [Wiki del proyecto](https://github.com/MHSanaei/3x-ui/wiki).
|
||||||
|
|
||||||
|
## Un Agradecimiento Especial a
|
||||||
|
|
||||||
|
- [alireza0](https://github.com/alireza0/)
|
||||||
|
|
||||||
|
## Reconocimientos
|
||||||
|
|
||||||
|
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (Licencia: **GPL-3.0**): _Reglas de enrutamiento mejoradas para v2ray/xray y v2ray/xray-clients con dominios iraníes incorporados y un enfoque en seguridad y bloqueo de anuncios._
|
||||||
|
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (Licencia: **GPL-3.0**): _Este repositorio contiene reglas de enrutamiento V2Ray actualizadas automáticamente basadas en datos de dominios y direcciones bloqueadas en Rusia._
|
||||||
|
|
||||||
|
## Apoyar el Proyecto
|
||||||
|
|
||||||
|
**Si este proyecto te es útil, puedes darle una**:star2:
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
||||||
|
@ -29,561 +51,6 @@
|
||||||
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
||||||
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
||||||
|
|
||||||
## Instalar y Actualizar
|
## Estrellas a lo Largo del Tiempo
|
||||||
|
|
||||||
```
|
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Instalar versión antigua (no recomendamos)
|
|
||||||
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Certificado SSL
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haga clic para ver los detalles del certificado SSL</summary>
|
|
||||||
|
|
||||||
### ACME
|
|
||||||
|
|
||||||
Para gestionar certificados SSL utilizando ACME:
|
|
||||||
|
|
||||||
1. Asegúrate de que tu dominio esté correctamente resuelto al servidor.
|
|
||||||
2. Ejecuta el comando `x-ui` en la terminal y elige `Gestión de Certificados SSL`.
|
|
||||||
3. Se te presentarán las siguientes opciones:
|
|
||||||
|
|
||||||
- **Get SSL:** Obtener certificados SSL.
|
|
||||||
- **Revoke:** Revocar certificados SSL existentes.
|
|
||||||
- **Force Renew:** Forzar la renovación de certificados SSL.
|
|
||||||
- **Show Existing Domains:** Mostrar todos los certificados de dominio disponibles en el servidor.
|
|
||||||
- **Set Certificate Paths for the Panel:** Especificar el certificado para tu dominio que será utilizado por el panel.
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
Para instalar y usar Certbot:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apt-get install certbot -y
|
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
|
||||||
certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloudflare
|
|
||||||
|
|
||||||
El script de gestión incluye una aplicación de certificado SSL integrada para Cloudflare. Para usar este script para solicitar un certificado, necesitas lo siguiente:
|
|
||||||
|
|
||||||
- Correo electrónico registrado en Cloudflare
|
|
||||||
- Clave API Global de Cloudflare
|
|
||||||
- El nombre de dominio debe estar resuelto al servidor actual a través de Cloudflare
|
|
||||||
|
|
||||||
**Cómo obtener la Clave API Global de Cloudflare:**
|
|
||||||
|
|
||||||
1. Ejecuta el comando `x-ui` en la terminal y elige `Certificado SSL de Cloudflare`.
|
|
||||||
2. Visita el enlace: [Tokens de API de Cloudflare](https://dash.cloudflare.com/profile/api-tokens).
|
|
||||||
3. Haz clic en "Ver Clave API Global" (consulta la captura de pantalla a continuación):
|
|
||||||

|
|
||||||
4. Es posible que necesites volver a autenticar tu cuenta. Después de eso, se mostrará la Clave API (consulta la captura de pantalla a continuación):
|
|
||||||

|
|
||||||
|
|
||||||
Al utilizarlo, simplemente ingresa tu `nombre de dominio`, `correo electrónico` y `CLAVE API`. El diagrama es el siguiente:
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Instalación y Actualización Manual
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para más detalles de la instalación manual</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
1. Para descargar la última versión del paquete comprimido directamente en tu servidor, ejecuta el siguiente comando:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
wget https://github.com/MHSanaei/3x-ui/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:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cd /root/
|
|
||||||
rm -rf x-ui/ /usr/local/x-ui/ /usr/bin/x-ui
|
|
||||||
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
|
||||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
|
||||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
|
||||||
mv x-ui/ /usr/local/
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable x-ui
|
|
||||||
systemctl restart x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Instalar con Docker
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para más detalles del Docker</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
1. Instala Docker:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bash <(curl -sSL https://get.docker.com)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Clona el Repositorio del Proyecto:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
|
||||||
cd 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Inicia el Servicio
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
O tambien
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -itd \
|
|
||||||
-e XRAY_VMESS_AEAD_FORCED=false \
|
|
||||||
-v $PWD/db/:/etc/x-ui/ \
|
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--network=host \
|
|
||||||
--restart=unless-stopped \
|
|
||||||
--name 3x-ui \
|
|
||||||
ghcr.io/mhsanaei/3x-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
actualizar a la última versión
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd 3x-ui
|
|
||||||
docker compose down
|
|
||||||
docker compose pull 3x-ui
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
eliminar 3x-ui de docker
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker stop 3x-ui
|
|
||||||
docker rm 3x-ui
|
|
||||||
cd --
|
|
||||||
rm -r 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Configuración de Nginx
|
|
||||||
<details>
|
|
||||||
<summary>Haga clic aquí para configurar el proxy inverso</summary>
|
|
||||||
|
|
||||||
#### Proxy inverso Nginx
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Nginx sub-path
|
|
||||||
- EAsegúrese de que la "Ruta Raíz de la URL del Panel" en la configuración del panel `/sub` es la misma.
|
|
||||||
- El `url` en la configuración del panel debe terminar con `/`.
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location /sub {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## SO Recomendados
|
|
||||||
|
|
||||||
- Ubuntu 22.04+
|
|
||||||
- Debian 12+
|
|
||||||
- CentOS 8+
|
|
||||||
- OpenEuler 22.03+
|
|
||||||
- Fedora 36+
|
|
||||||
- Arch Linux
|
|
||||||
- Parch Linux
|
|
||||||
- Manjaro
|
|
||||||
- Armbian
|
|
||||||
- AlmaLinux 9.5+
|
|
||||||
- Rocky Linux 9.5+
|
|
||||||
- Oracle Linux 8+
|
|
||||||
- OpenSUSE Tubleweed
|
|
||||||
- Amazon Linux 2023
|
|
||||||
- Virtuozzo Linux 8+
|
|
||||||
- Windows x64
|
|
||||||
|
|
||||||
## Arquitecturas y Dispositivos Compatibles
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para detalles de arquitecturas y dispositivos compatibles</summary>
|
|
||||||
|
|
||||||
Nuestra plataforma ofrece compatibilidad con una amplia gama de arquitecturas y dispositivos, garantizando flexibilidad en diversos entornos informáticos. A continuación se presentan las principales arquitecturas que admitimos:
|
|
||||||
|
|
||||||
- **amd64**: Esta arquitectura predominante es la estándar para computadoras personales y servidores, y admite la mayoría de los sistemas operativos modernos sin problemas.
|
|
||||||
|
|
||||||
- **x86 / i386**: Ampliamente adoptada en computadoras de escritorio y portátiles, esta arquitectura cuenta con un amplio soporte de numerosos sistemas operativos y aplicaciones, incluidos, entre otros, Windows, macOS y sistemas Linux.
|
|
||||||
|
|
||||||
- **armv8 / arm64 / aarch64**: Diseñada para dispositivos móviles y embebidos contemporáneos, como teléfonos inteligentes y tabletas, esta arquitectura está ejemplificada por dispositivos como Raspberry Pi 4, Raspberry Pi 3, Raspberry Pi Zero 2/Zero 2 W, Orange Pi 3 LTS, entre otros.
|
|
||||||
|
|
||||||
- **armv7 / arm / arm32**: Sirve como arquitectura para dispositivos móviles y embebidos más antiguos, y sigue siendo ampliamente utilizada en dispositivos como Orange Pi Zero LTS, Orange Pi PC Plus, Raspberry Pi 2, entre otros.
|
|
||||||
|
|
||||||
- **armv6 / arm / arm32**: Orientada a dispositivos embebidos muy antiguos, esta arquitectura, aunque menos común, todavía se utiliza. Dispositivos como Raspberry Pi 1, Raspberry Pi Zero/Zero W, dependen de esta arquitectura.
|
|
||||||
|
|
||||||
- **armv5 / arm / arm32**: Una arquitectura más antigua asociada principalmente con sistemas embebidos tempranos, es menos común hoy en día pero aún puede encontrarse en dispositivos heredados como versiones antiguas de Raspberry Pi y algunos teléfonos inteligentes más antiguos.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Idiomas
|
|
||||||
|
|
||||||
- Arabic (Árabe)
|
|
||||||
- English (inglés)
|
|
||||||
- Persian (persa)
|
|
||||||
- Traditional Chinese (chino tradicional)
|
|
||||||
- Simplified Chinese (chino simplificado)
|
|
||||||
- Japanese (japonés)
|
|
||||||
- Russian (ruso)
|
|
||||||
- Vietnamese (vietnamita)
|
|
||||||
- Spanish (español)
|
|
||||||
- Indonesian (indonesio)
|
|
||||||
- Ukrainian (ucraniano)
|
|
||||||
- Turkish (turco)
|
|
||||||
- Português (Brazil) (portugués (Brasil))
|
|
||||||
|
|
||||||
|
|
||||||
## Características
|
|
||||||
|
|
||||||
- Monitoreo del Estado del Sistema
|
|
||||||
- Búsqueda dentro de todas las reglas de entrada y clientes
|
|
||||||
- Tema Oscuro/Claro
|
|
||||||
- Soporta multiusuario y multiprotocolo
|
|
||||||
- Soporta protocolos, incluyendo VMess, VLESS, Trojan, Shadowsocks, Dokodemo-door, Socks, HTTP, wireguard
|
|
||||||
- Soporta Protocolos nativos XTLS, incluyendo RPRX-Direct, Visión, REALITY
|
|
||||||
- Estadísticas de tráfico, límite de tráfico, límite de tiempo de vencimiento
|
|
||||||
- Plantillas de configuración de Xray personalizables
|
|
||||||
- Soporta acceso HTTPS al panel (dominio proporcionado por uno mismo + certificado SSL)
|
|
||||||
- Soporta la solicitud y renovación automática de certificados SSL con un clic
|
|
||||||
- Para elementos de configuración más avanzados, consulta el panel
|
|
||||||
- Corrige rutas de API (la configuración del usuario se creará con la API)
|
|
||||||
- Soporta cambiar las configuraciones por diferentes elementos proporcionados en el panel.
|
|
||||||
- Soporta exportar/importar base de datos desde el panel
|
|
||||||
|
|
||||||
|
|
||||||
## Configuración Predeterminada del Panel
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para ver los detalles de la configuración predeterminada</summary>
|
|
||||||
|
|
||||||
### Nombre de usuario, Contraseña, Puerto y Ruta Base Web
|
|
||||||
|
|
||||||
Si elige no modificar estas configuraciones, se generarán aleatoriamente (esto no se aplica a Docker).
|
|
||||||
|
|
||||||
**Configuraciones predeterminadas para Docker:**
|
|
||||||
- **Nombre de usuario:** admin
|
|
||||||
- **Contraseña:** admin
|
|
||||||
- **Puerto:** 2053
|
|
||||||
|
|
||||||
### Gestión de la Base de Datos:
|
|
||||||
|
|
||||||
Puedes realizar copias de seguridad y restauraciones de la base de datos directamente desde el panel.
|
|
||||||
|
|
||||||
- **Ruta de la Base de Datos:**
|
|
||||||
- `/etc/x-ui/x-ui.db`
|
|
||||||
|
|
||||||
### Ruta Base Web
|
|
||||||
|
|
||||||
1. **Restablecer la Ruta Base Web:**
|
|
||||||
- Abre tu terminal.
|
|
||||||
- Ejecuta el comando `x-ui`.
|
|
||||||
- Selecciona la opción `Restablecer la Ruta Base Web`.
|
|
||||||
|
|
||||||
2. **Generar o Personalizar la Ruta:**
|
|
||||||
- La ruta se generará aleatoriamente, o puedes ingresar una ruta personalizada.
|
|
||||||
|
|
||||||
3. **Ver Configuración Actual:**
|
|
||||||
- Para ver tu configuración actual, utiliza el comando `x-ui settings` en el terminal o selecciona `Ver Configuración Actual` en `x-ui`.
|
|
||||||
|
|
||||||
### Recomendación de Seguridad:
|
|
||||||
- Para mayor seguridad, utiliza una palabra larga y aleatoria en la estructura de tu URL.
|
|
||||||
|
|
||||||
**Ejemplos:**
|
|
||||||
- `http://ip:port/*webbasepath*/panel`
|
|
||||||
- `http://domain:port/*webbasepath*/panel`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Configuración de WARP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para ver los detalles de la configuración de WARP</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
**Para versiones `v2.1.0` y posteriores:**
|
|
||||||
|
|
||||||
WARP está integrado, no se requiere instalación adicional. Simplemente habilita la configuración necesaria en el panel.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Límite de IP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para ver los detalles del límite de IP</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
**Nota:** El Límite de IP no funcionará correctamente cuando uses Túnel IP.
|
|
||||||
|
|
||||||
- **Para versiones hasta `v1.6.1`:**
|
|
||||||
- El límite de IP está integrado en el panel.
|
|
||||||
|
|
||||||
**Para versiones `v1.7.0` y posteriores:**
|
|
||||||
|
|
||||||
Para habilitar la funcionalidad de límite de IP, necesitas instalar `fail2ban` y los archivos requeridos siguiendo estos pasos:
|
|
||||||
|
|
||||||
1. Ejecuta el comando `x-ui` en el terminal, luego elige `Gestión de Límite de IP`.
|
|
||||||
2. Verás las siguientes opciones:
|
|
||||||
|
|
||||||
- **Cambiar la Duración del Bloqueo:** Ajustar la duración de los bloqueos.
|
|
||||||
- **Desbloquear a Todos:** Levantar todos los bloqueos actuales.
|
|
||||||
- **Revisar los Registros:** Revisar los registros.
|
|
||||||
- **Estado de Fail2ban:** Verificar el estado de `fail2ban`.
|
|
||||||
- **Reiniciar Fail2ban:** Reiniciar el servicio `fail2ban`.
|
|
||||||
- **Desinstalar Fail2ban:** Desinstalar Fail2ban con la configuración.
|
|
||||||
|
|
||||||
3. Agrega una ruta para el registro de acceso en el panel configurando `Xray Configs/log/Access log` a `./access.log`, luego guarda y reinicia Xray.
|
|
||||||
|
|
||||||
- **Para versiones anteriores a `v2.1.3`:**
|
|
||||||
- Necesitas configurar manualmente la ruta del registro de acceso en tu configuración de Xray:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
"log": {
|
|
||||||
"access": "./access.log",
|
|
||||||
"dnsLog": false,
|
|
||||||
"loglevel": "warning"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Para versiones `v2.1.3` y posteriores:**
|
|
||||||
- Hay una opción para configurar `access.log` directamente desde el panel.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Bot de Telegram
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para más detalles del bot de Telegram</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
El panel web admite tráfico diario, inicio de sesión en el panel, copia de seguridad de la base de datos, estado del sistema, información del cliente y otras notificaciones y funciones a través del Bot de Telegram. Para usar el bot, debes establecer los parámetros relacionados con el bot en el panel, que incluyen:
|
|
||||||
|
|
||||||
- Token de Telegram
|
|
||||||
- ID de chat de administrador(es)
|
|
||||||
- Hora de Notificación (en sintaxis cron)
|
|
||||||
- Notificación de Fecha de Caducidad
|
|
||||||
- Notificación de Capacidad de Tráfico
|
|
||||||
- Copia de seguridad de la base de datos
|
|
||||||
- Notificación de Carga de CPU
|
|
||||||
|
|
||||||
|
|
||||||
**Sintaxis de referencia:**
|
|
||||||
|
|
||||||
- `30 \* \* \* \* \*` - Notifica a los 30s de cada punto
|
|
||||||
- `0 \*/10 \* \* \* \*` - Notifica en el primer segundo de cada 10 minutos
|
|
||||||
- `@hourly` - Notificación por hora
|
|
||||||
- `@daily` - Notificación diaria (00:00 de la mañana)
|
|
||||||
- `@weekly` - Notificación semanal
|
|
||||||
- `@every 8h` - Notifica cada 8 horas
|
|
||||||
|
|
||||||
### Funcionalidades del Bot de Telegram
|
|
||||||
|
|
||||||
- Reporte periódico
|
|
||||||
- Notificación de inicio de sesión
|
|
||||||
- Notificación de umbral de CPU
|
|
||||||
- Umbral de Notificación para Fecha de Caducidad y Tráfico para informar con anticipación
|
|
||||||
- Soporte para menú de reporte de cliente si el nombre de usuario de Telegram del cliente se agrega a las configuraciones de usuario
|
|
||||||
- Soporte para reporte de tráfico de Telegram buscado con UUID (VMESS/VLESS) o Contraseña (TROJAN) - anónimamente
|
|
||||||
- Bot basado en menú
|
|
||||||
- Buscar cliente por correo electrónico (solo administrador)
|
|
||||||
- Ver todas las Entradas
|
|
||||||
- Ver estado del servidor
|
|
||||||
- Ver clientes agotados
|
|
||||||
- Recibir copia de seguridad bajo demanda y en informes periódicos
|
|
||||||
- Bot multilingüe
|
|
||||||
|
|
||||||
### Configuración del Bot de Telegram
|
|
||||||
|
|
||||||
- Inicia [Botfather](https://t.me/BotFather) en tu cuenta de Telegram:
|
|
||||||

|
|
||||||
|
|
||||||
- Crea un nuevo bot usando el comando /newbot: Te hará 2 preguntas, Un nombre y un nombre de usuario para tu bot. Ten en cuenta que el nombre de usuario debe terminar con la palabra "bot".
|
|
||||||

|
|
||||||
|
|
||||||
- Inicia el bot que acabas de crear. Puedes encontrar el enlace a tu bot aquí.
|
|
||||||

|
|
||||||
|
|
||||||
- Ingresa a tu panel y configura los ajustes del bot de Telegram como se muestra a continuación:
|
|
||||||

|
|
||||||
|
|
||||||
Ingresa el token de tu bot en el campo de entrada número 3.
|
|
||||||
Ingresa el ID de chat de usuario en el campo de entrada número 4. Las cuentas de Telegram con esta ID serán los administradores del bot. (Puedes ingresar más de uno, solo sepáralos con ,)
|
|
||||||
|
|
||||||
- ¿Cómo obtener el ID de chat de Telegram? Usa este [bot](https://t.me/useridinfobot), Inicia el bot y te dará el ID de chat del usuario de Telegram.
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Rutas de API
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para más detalles de las rutas de API</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
- [Documentación de API](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
|
|
||||||
- `/login` con `POST` datos de usuario: `{username: '', password: ''}` para iniciar sesión
|
|
||||||
- `/panel/api/inbounds` base para las siguientes acciones:
|
|
||||||
|
|
||||||
| Método | Ruta | Acción |
|
|
||||||
| :----: | ---------------------------------- | --------------------------------------------------------- |
|
|
||||||
| `GET` | `"/list"` | Obtener todas los Entradas |
|
|
||||||
| `GET` | `"/get/:id"` | Obtener Entrada con inbound.id |
|
|
||||||
| `GET` | `"/getClientTraffics/:email"` | Obtener Tráficos del Cliente con email |
|
|
||||||
| `GET` | `"/createbackup"` | El bot de Telegram envía copia de seguridad a los admins |
|
|
||||||
| `POST` | `"/add"` | Agregar Entrada |
|
|
||||||
| `POST` | `"/del/:id"` | Eliminar Entrada |
|
|
||||||
| `POST` | `"/update/:id"` | Actualizar Entrada |
|
|
||||||
| `POST` | `"/clientIps/:email"` | Dirección IP del Cliente |
|
|
||||||
| `POST` | `"/clearClientIps/:email"` | Borrar Dirección IP del Cliente |
|
|
||||||
| `POST` | `"/addClient"` | Agregar Cliente a la Entrada |
|
|
||||||
| `POST` | `"/:id/delClient/:clientId"` | Eliminar Cliente por clientId\* |
|
|
||||||
| `POST` | `"/updateClient/:clientId"` | Actualizar Cliente por clientId\* |
|
|
||||||
| `POST` | `"/:id/resetClientTraffic/:email"` | Restablecer Tráfico del Cliente |
|
|
||||||
| `POST` | `"/resetAllTraffics"` | Restablecer tráfico de todos las Entradas |
|
|
||||||
| `POST` | `"/resetAllClientTraffics/:id"` | Restablecer tráfico de todos los clientes en una Entrada |
|
|
||||||
| `POST` | `"/delDepletedClients/:id"` | Eliminar clientes agotados de la entrada (-1: todos) |
|
|
||||||
| `POST` | `"/onlines"` | Obtener usuarios en línea (lista de correos electrónicos) |
|
|
||||||
|
|
||||||
\*- El campo `clientId` debe llenarse por:
|
|
||||||
|
|
||||||
- `client.id` para VMESS y VLESS
|
|
||||||
- `client.password` para TROJAN
|
|
||||||
- `client.email` para Shadowsocks
|
|
||||||
|
|
||||||
- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Variables de Entorno
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Haz clic para más detalles de las variables de entorno</summary>
|
|
||||||
|
|
||||||
#### Uso
|
|
||||||
|
|
||||||
| Variable | Tipo | Predeterminado |
|
|
||||||
| -------------- | :--------------------------------------------: | :------------- |
|
|
||||||
| XUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
|
||||||
| XUI_DEBUG | `boolean` | `false` |
|
|
||||||
| XUI_BIN_FOLDER | `string` | `"bin"` |
|
|
||||||
| XUI_DB_FOLDER | `string` | `"/etc/x-ui"` |
|
|
||||||
| XUI_LOG_FOLDER | `string` | `"/var/log"` |
|
|
||||||
|
|
||||||
Ejemplo:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Vista previa
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/01-overview-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/02-inbounds-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/04-add-client-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/05-settings-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/06-configs-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/07-bot-light.png">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## Un agradecimiento especial a
|
|
||||||
|
|
||||||
- [alireza0](https://github.com/alireza0/)
|
|
||||||
|
|
||||||
## Reconocimientos
|
|
||||||
|
|
||||||
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (Licencia: **GPL-3.0**): _Reglas de enrutamiento mejoradas de v2ray/xray y v2ray/xray-clients con dominios iraníes integrados y un enfoque en seguridad y bloqueo de anuncios._
|
|
||||||
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (License: **GPL-3.0**): _Este repositorio contiene reglas de enrutamiento de V2Ray actualizadas automáticamente basadas en datos de dominios y direcciones bloqueados en Rusia._
|
|
||||||
|
|
||||||
## Estrellas a lo largo del tiempo
|
|
||||||
|
|
||||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
|
||||||
|
|
536
README.fa_IR.md
|
@ -7,17 +7,39 @@
|
||||||
</picture>
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**یک پنل وب پیشرفته • ساخته شده بر پایه Xray Core**
|
[](https://github.com/MHSanaei/3x-ui/releases)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/actions)
|
||||||
|
[](#)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/releases/latest)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
[](https://github.com/MHSanaei/3x-ui/releases)
|
**3X-UI** — یک پنل کنترل پیشرفته مبتنی بر وب با کد باز که برای مدیریت سرور Xray-core طراحی شده است. این پنل یک رابط کاربری آسان برای پیکربندی و نظارت بر پروتکلهای مختلف VPN و پراکسی ارائه میدهد.
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
|
||||||
|
|
||||||
> **سلب مسئولیت:** این پروژه صرفاً برای اهداف آموزشی و تحقیقاتی است. استفاده از آن برای مقاصد غیرقانونی یا در محیطهای عملیاتی ممنوع است.
|
> [!IMPORTANT]
|
||||||
|
> این پروژه فقط برای استفاده شخصی و ارتباطات است، لطفاً از آن برای اهداف غیرقانونی استفاده نکنید، لطفاً از آن در محیط تولید استفاده نکنید.
|
||||||
|
|
||||||
**اگر این پروژه برای شما مفید بوده، میتوانید با دادن یک**:star2: از آن حمایت کنید.
|
به عنوان یک نسخه بهبود یافته از پروژه اصلی X-UI، 3X-UI پایداری بهتر، پشتیبانی گستردهتر از پروتکلها و ویژگیهای اضافی را ارائه میدهد.
|
||||||
|
|
||||||
|
## شروع سریع
|
||||||
|
|
||||||
|
```
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
برای مستندات کامل، لطفاً به [ویکی پروژه](https://github.com/MHSanaei/3x-ui/wiki) مراجعه کنید.
|
||||||
|
|
||||||
|
## تشکر ویژه از
|
||||||
|
|
||||||
|
- [alireza0](https://github.com/alireza0/)
|
||||||
|
|
||||||
|
## قدردانی
|
||||||
|
|
||||||
|
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (مجوز: **GPL-3.0**): _قوانین مسیریابی بهبود یافته v2ray/xray و v2ray/xray-clients با دامنههای ایرانی داخلی و تمرکز بر امنیت و مسدود کردن تبلیغات._
|
||||||
|
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (مجوز: **GPL-3.0**): _این مخزن شامل قوانین مسیریابی V2Ray بهروزرسانی شده خودکار بر اساس دادههای دامنهها و آدرسهای مسدود شده در روسیه است._
|
||||||
|
|
||||||
|
## پشتیبانی از پروژه
|
||||||
|
|
||||||
|
**اگر این پروژه برای شما مفید است، میتوانید به آن یک**:star2: بدهید
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
||||||
|
@ -29,500 +51,6 @@
|
||||||
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
||||||
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
||||||
|
|
||||||
## نصب و ارتقا
|
## ستارهها در طول زمان
|
||||||
|
|
||||||
```
|
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
## نصب نسخههای قدیمی (توصیه نمیشود)
|
|
||||||
|
|
||||||
برای نصب نسخه خاصی از دستور زیر استفاده کنید. مثال برای نسخه `v1.7.9`:
|
|
||||||
|
|
||||||
```
|
|
||||||
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
|
|
||||||
```
|
|
||||||
|
|
||||||
## گواهی SSL
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات گواهی SSL</summary>
|
|
||||||
|
|
||||||
### ACME
|
|
||||||
|
|
||||||
برای مدیریت گواهیهای SSL با استفاده از ACME:
|
|
||||||
|
|
||||||
1. اطمینان حاصل کنید دامنه شما به درستی به سرور متصل است.
|
|
||||||
2. دستور `x-ui` را در ترمینال اجرا کرده و گزینه `مدیریت گواهی SSL` را انتخاب کنید.
|
|
||||||
3. گزینههای زیر نمایش داده میشوند:
|
|
||||||
|
|
||||||
- **دریافت SSL:** دریافت گواهی SSL
|
|
||||||
- **لغو:** لغو گواهیهای موجود
|
|
||||||
- **تمدید اجباری:** تمدید اجباری گواهیها
|
|
||||||
- **نمایش دامنههای موجود:** نمایش تمام دامنههای دارای گواهی
|
|
||||||
- **تنظیم مسیر گواهی برای پنل:** تنظیم مسیر گواهی برای دامنه شما
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
نصب و استفاده از Certbot:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apt-get install certbot -y
|
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
|
||||||
certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloudflare
|
|
||||||
|
|
||||||
اسکریپت داخلی برای دریافت گواهی SSL از Cloudflare. نیازمند:
|
|
||||||
|
|
||||||
- ایمیل ثبتشده در Cloudflare
|
|
||||||
- کلید API جهانی Cloudflare
|
|
||||||
- دامنه باید از طریق Cloudflare به سرور متصل باشد
|
|
||||||
|
|
||||||
**دریافت کلید API جهانی Cloudflare:**
|
|
||||||
|
|
||||||
1. دستور `x-ui` را اجرا و گزینه `گواهی SSL کلادفلر` را انتخاب کنید.
|
|
||||||
2. به لینک [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens) مراجعه کنید.
|
|
||||||
3. روی "View Global API Key" کلیک کنید:
|
|
||||||

|
|
||||||
4. پس از احراز هویت، کلید API نمایش داده میشود:
|
|
||||||

|
|
||||||
|
|
||||||
در هنگام استفاده، نام دامنه، ایمیل و کلید API را وارد کنید:
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## نصب دستی و ارتقا
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات نصب دستی</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
1. دریافت آخرین نسخه از سرور:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
2. نصب یا ارتقا:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cd /root/
|
|
||||||
rm -rf x-ui/ /usr/local/x-ui/ /usr/bin/x-ui
|
|
||||||
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
|
||||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
|
||||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
|
||||||
mv x-ui/ /usr/local/
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable x-ui
|
|
||||||
systemctl restart x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## نصب با Docker
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات Docker</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
1. **نصب Docker:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bash <(curl -sSL https://get.docker.com)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **کلون پروژه:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
|
||||||
cd 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **راهاندازی سرویس:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
یا
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -itd \
|
|
||||||
-e XRAY_VMESS_AEAD_FORCED=false \
|
|
||||||
-v $PWD/db/:/etc/x-ui/ \
|
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--network=host \
|
|
||||||
--restart=unless-stopped \
|
|
||||||
--name 3x-ui \
|
|
||||||
ghcr.io/mhsanaei/3x-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **بهروزرسانی:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd 3x-ui
|
|
||||||
docker compose down
|
|
||||||
docker compose pull 3x-ui
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **حذف:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker stop 3x-ui
|
|
||||||
docker rm 3x-ui
|
|
||||||
cd --
|
|
||||||
rm -r 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## تنظیمات Nginx
|
|
||||||
<details>
|
|
||||||
<summary>پیکربندی Reverse Proxy</summary>
|
|
||||||
|
|
||||||
#### Nginx Reverse Proxy
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### مسیر فرعی در Nginx
|
|
||||||
- اطمینان حاصل کنید "URI Path" در تنظیمات پنل یکسان باشد.
|
|
||||||
- `url` در تنظیمات پنل باید با `/` پایان یابد.
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location /sub {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## سیستمعاملهای توصیه شده
|
|
||||||
|
|
||||||
- Ubuntu 22.04+
|
|
||||||
- Debian 12+
|
|
||||||
- CentOS 8+
|
|
||||||
- OpenEuler 22.03+
|
|
||||||
- Fedora 36+
|
|
||||||
- Arch Linux
|
|
||||||
- Parch Linux
|
|
||||||
- Manjaro
|
|
||||||
- Armbian
|
|
||||||
- AlmaLinux 9.5+
|
|
||||||
- Rocky Linux 9.5+
|
|
||||||
- Oracle Linux 8+
|
|
||||||
- OpenSUSE Tubleweed
|
|
||||||
- Amazon Linux 2023
|
|
||||||
- Virtuozzo Linux 8+
|
|
||||||
- Windows x64
|
|
||||||
|
|
||||||
## معماریها و دستگاههای پشتیبانی شده
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات معماریها و دستگاهها</summary>
|
|
||||||
|
|
||||||
- **amd64**: معماری استاندارد برای کامپیوترهای شخصی و سرورها
|
|
||||||
- **x86 / i386**: سیستمهای دسکتاپ و لپتاپ
|
|
||||||
- **armv8 / arm64 / aarch64**: دستگاههای موبایل و embedded مانند Raspberry Pi 4
|
|
||||||
- **armv7 / arm / arm32**: دستگاههای قدیمی مانند Orange Pi Zero
|
|
||||||
- **armv6 / arm / arm32**: دستگاههای بسیار قدیمی مانند Raspberry Pi 1
|
|
||||||
- **armv5 / arm / arm32**: سیستمهای embedded قدیمی
|
|
||||||
- **s390x**: کامپیوترهای IBM mainframe
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## زبانهای پشتیبانی شده
|
|
||||||
|
|
||||||
- انگلیسی
|
|
||||||
- فارسی
|
|
||||||
- چینی سنتی
|
|
||||||
- چینی سادهشده
|
|
||||||
- ژاپنی
|
|
||||||
- روسی
|
|
||||||
- ویتنامی
|
|
||||||
- اسپانیایی
|
|
||||||
- اندونزیایی
|
|
||||||
- اوکراینی
|
|
||||||
- ترکی
|
|
||||||
- پرتغالی (برزیل)
|
|
||||||
|
|
||||||
## ویژگیها
|
|
||||||
|
|
||||||
- مانیتورینگ وضعیت سیستم
|
|
||||||
- جستجو در بین inboundها و کلاینتها
|
|
||||||
- تم تاریک/روشن
|
|
||||||
- پشتیبانی از چند کاربر و پروتکل
|
|
||||||
- پروتکلهای VMESS، VLESS، Trojan، Shadowsocks، Dokodemo-door، Socks، HTTP، WireGuard
|
|
||||||
- پشتیبانی از XTLS شامل RPRX-Direct، Vision، REALITY
|
|
||||||
- آمار ترافیک، محدودیت ترافیک، محدودیت زمانی
|
|
||||||
- تنظیمات سفارشی Xray
|
|
||||||
- پشتیبانی از HTTPS برای پنل
|
|
||||||
- دریافت خودکار گواهی SSL
|
|
||||||
- مسیرهای API اصلاح شده
|
|
||||||
- پشتیبانی از تغییر تنظیمات از طریق پنل
|
|
||||||
- امکان export/import دیتابیس
|
|
||||||
|
|
||||||
## تنظیمات پیشفرض پنل
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات تنظیمات پیشفرض</summary>
|
|
||||||
|
|
||||||
### نام کاربری، رمز عبور، پورت و مسیر وب
|
|
||||||
|
|
||||||
در صورت عدم تغییر، این موارد به صورت تصادفی ایجاد میشوند (به جز Docker).
|
|
||||||
|
|
||||||
**تنظیمات پیشفرض Docker:**
|
|
||||||
- **نام کاربری:** admin
|
|
||||||
- **رمز عبور:** admin
|
|
||||||
- **پورت:** 2053
|
|
||||||
|
|
||||||
### مدیریت دیتابیس:
|
|
||||||
|
|
||||||
امکان Backup و Restore دیتابیس از طریق پنل.
|
|
||||||
|
|
||||||
- **مسیر دیتابیس:**
|
|
||||||
- `/etc/x-ui/x-ui.db`
|
|
||||||
|
|
||||||
### مسیر پایه وب
|
|
||||||
|
|
||||||
1. **بازنشانی مسیر:**
|
|
||||||
- اجرای دستور `x-ui`
|
|
||||||
- انتخاب گزینه `Reset Web Base Path`
|
|
||||||
|
|
||||||
2. **ساخت یا تنظیم مسیر:**
|
|
||||||
- مسیر به صورت تصادفی ساخته شده یا قابل تنظیم است
|
|
||||||
|
|
||||||
3. **مشاهده تنظیمات فعلی:**
|
|
||||||
- استفاده از دستور `x-ui settings` یا `View Current Settings` در `x-ui`
|
|
||||||
|
|
||||||
**توصیه امنیتی:**
|
|
||||||
- استفاده از مسیرهای طولانی و تصادفی برای افزایش امنیت
|
|
||||||
|
|
||||||
**مثال:**
|
|
||||||
- `http://ip:port/*webbasepath*/panel`
|
|
||||||
- `http://domain:port/*webbasepath*/panel`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## پیکربندی WARP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات WARP</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
**برای نسخههای `v2.1.0` و جدیدتر:**
|
|
||||||
|
|
||||||
WARP به صورت داخلی پشتیبانی میشود. تنها نیاز به فعالسازی در پنل است.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## محدودیت IP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات محدودیت IP</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
**توجه:** محدودیت IP در صورت استفاده از IP Tunnel کار نمیکند.
|
|
||||||
|
|
||||||
- **تا نسخه `v1.6.1`:**
|
|
||||||
- محدودیت IP به صورت داخلی در پنل وجود دارد
|
|
||||||
|
|
||||||
**برای نسخههای `v1.7.0` و جدیدتر:**
|
|
||||||
|
|
||||||
برای فعالسازی نیاز به نصب `fail2ban` است:
|
|
||||||
|
|
||||||
1. اجرای دستور `x-ui` و انتخاب `مدیریت محدودیت IP`
|
|
||||||
2. گزینههای موجود:
|
|
||||||
|
|
||||||
- **تغییر مدت زمان Ban**
|
|
||||||
- **حذف تمام Banها**
|
|
||||||
- **مشاهده لاگها**
|
|
||||||
- **وضعیت Fail2ban**
|
|
||||||
- **راهاندازی مجدد Fail2ban**
|
|
||||||
- **حذف Fail2ban**
|
|
||||||
|
|
||||||
3. تنظیم مسیر `Access log` در پنل به `./access.log` و ذخیره و راهاندازی مجدد Xray
|
|
||||||
|
|
||||||
- **قبل از نسخه `v2.1.3`:**
|
|
||||||
- تنظیم دستی `access.log` در تنظیمات Xray:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
"log": {
|
|
||||||
"access": "./access.log",
|
|
||||||
"dnsLog": false,
|
|
||||||
"loglevel": "warning"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- **از نسخه `v2.1.3`:**
|
|
||||||
- امکان تنظیم `access.log` از طریق پنل
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## ربات تلگرام
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات ربات تلگرام</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
ربات تلگرام برای اطلاعرسانی ترافیک، ورود به پنل، Backup دیتابیس و ... استفاده میشود. نیازمند تنظیم:
|
|
||||||
|
|
||||||
- توکن تلگرام
|
|
||||||
- Chat ID ادمینها
|
|
||||||
- زمان اطلاعرسانی (Cron syntax)
|
|
||||||
- اطلاعرسانی انقضا
|
|
||||||
- اطلاعرسانی ترافیک
|
|
||||||
- Backup دیتابیس
|
|
||||||
- اطلاعرسانی مصرف CPU
|
|
||||||
|
|
||||||
**سینتکس نمونه:**
|
|
||||||
|
|
||||||
- `30 \* \* \* \* \*` - اطلاع در ثانیه 30 هر دقیقه
|
|
||||||
- `@hourly` - هر ساعت
|
|
||||||
- `@daily` - هر روز
|
|
||||||
|
|
||||||
### ویژگیهای ربات
|
|
||||||
|
|
||||||
- گزارش دورهای
|
|
||||||
- اطلاع ورود به پنل
|
|
||||||
- اطلاع مصرف CPU
|
|
||||||
- اطلاع پیشاز موعد انقضا و ترافیک
|
|
||||||
- گزارش ترافیک کلاینتها
|
|
||||||
- منوی مبتنی بر دستور
|
|
||||||
- جستجوی کلاینت بر اساس ایمیل
|
|
||||||
- بررسی inboundها
|
|
||||||
- بررسی وضعیت سرور
|
|
||||||
- دریافت Backup
|
|
||||||
- چندزبانه
|
|
||||||
|
|
||||||
### راهاندازی ربات
|
|
||||||
|
|
||||||
- شروع [Botfather](https://t.me/BotFather) در تلگرام:
|
|
||||||

|
|
||||||
|
|
||||||
- ساخت ربات جدید با دستور /newbot:
|
|
||||||

|
|
||||||
|
|
||||||
- شروع ربات ساخته شده:
|
|
||||||

|
|
||||||
|
|
||||||
- تنظیمات پنل:
|
|
||||||

|
|
||||||
|
|
||||||
وارد کردن توکن و Chat ID (دریافت از [این ربات](https://t.me/useridinfobot)):
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## مسیرهای API
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات API</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
- [مستندات API](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
|
|
||||||
- `/login` با `POST` داده کاربر: `{username: '', password: ''}`
|
|
||||||
|
|
||||||
| Method | مسیر | عملکرد |
|
|
||||||
| :----: | ---------------------------------- | ------------------------------------------- |
|
|
||||||
| `GET` | `"/list"` | دریافت تمام inboundها |
|
|
||||||
| `GET` | `"/get/:id"` | دریافت inbound بر اساس id |
|
|
||||||
| `POST` | `"/add"` | افزودن inbound |
|
|
||||||
| `POST` | `"/del/:id"` | حذف inbound |
|
|
||||||
|
|
||||||
- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## متغیرهای محیطی
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>جزئیات متغیرها</summary>
|
|
||||||
|
|
||||||
#### استفاده
|
|
||||||
|
|
||||||
| متغیر | نوع | پیشفرض |
|
|
||||||
| ------------- | :--------------------------------------------: | :------------ |
|
|
||||||
| XUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
|
||||||
| XUI_DEBUG | `boolean` | `false` |
|
|
||||||
| XUI_BIN_FOLDER| `string` | `"bin"` |
|
|
||||||
|
|
||||||
مثال:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## پیشنمایش
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/01-overview-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/02-inbounds-light.png">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## قدردانی ویژه از
|
|
||||||
|
|
||||||
- [alireza0](https://github.com/alireza0/)
|
|
||||||
|
|
||||||
## تشکر و قدردانی
|
|
||||||
|
|
||||||
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (مجوز: **GPL-3.0**)
|
|
||||||
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (مجوز: **GPL-3.0**)
|
|
||||||
|
|
||||||
## Stargazers over Time
|
|
||||||
|
|
||||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
|
||||||
|
|
604
README.md
|
@ -1,4 +1,4 @@
|
||||||
[English](/README.md) | [فارسی](/README.fa_IR.md) | [العربية](/README.ar_EG.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
[English](/README.md) | [فارسی](/README.fa_IR.md) | [العربية](/README.ar_EG.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<picture>
|
<picture>
|
||||||
|
@ -7,15 +7,37 @@
|
||||||
</picture>
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**An Advanced Web Panel • Built on Xray Core**
|
[](https://github.com/MHSanaei/3x-ui/releases)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/actions)
|
||||||
|
[](#)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/releases/latest)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
[](https://github.com/MHSanaei/3x-ui/releases)
|
**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.
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](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
|
> [!IMPORTANT]
|
||||||
|
> This project is only for personal using, please do not use it for illegal purposes, 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
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
For full documentation, please visit the [project Wiki](https://github.com/MHSanaei/3x-ui/wiki).
|
||||||
|
|
||||||
|
## A Special Thanks to
|
||||||
|
|
||||||
|
- [alireza0](https://github.com/alireza0/)
|
||||||
|
|
||||||
|
## Acknowledgment
|
||||||
|
|
||||||
|
- [Iran v2ray rules](https://github.com/chocolate4u/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](https://github.com/runetfreedom/russia-v2ray-rules-dat) (License: **GPL-3.0**): _This repository contains automatically updated V2Ray routing rules based on data on blocked domains and addresses in Russia._
|
||||||
|
|
||||||
|
## Support project
|
||||||
|
|
||||||
**If this project is helpful to you, you may wish to give it a**:star2:
|
**If this project is helpful to you, you may wish to give it a**:star2:
|
||||||
|
|
||||||
|
@ -29,570 +51,6 @@
|
||||||
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
||||||
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
||||||
|
|
||||||
## Install & Upgrade
|
|
||||||
|
|
||||||
```
|
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Install legacy Version (we don't recommend)
|
|
||||||
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
## SSL Certificate
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for SSL Certificate details</summary>
|
|
||||||
|
|
||||||
### ACME
|
|
||||||
|
|
||||||
To manage SSL certificates using ACME:
|
|
||||||
|
|
||||||
1. Ensure your domain is correctly resolved to the server.
|
|
||||||
2. Run the `x-ui` command in the terminal, then choose `SSL Certificate Management`.
|
|
||||||
3. You will be presented with the following options:
|
|
||||||
|
|
||||||
- **Get SSL:** Obtain SSL certificates.
|
|
||||||
- **Revoke:** Revoke existing SSL certificates.
|
|
||||||
- **Force Renew:** Force renewal of SSL certificates.
|
|
||||||
- **Show Existing Domains:** Display all domain certificates available on the server.
|
|
||||||
- **Set Certificate Paths for the Panel:** Specify the certificate for your domain to be used by the panel.
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
To install and use Certbot:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apt-get install certbot -y
|
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
|
||||||
certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloudflare
|
|
||||||
|
|
||||||
The management script includes a built-in SSL certificate application for Cloudflare. To use this script to apply for a certificate, you need the following:
|
|
||||||
|
|
||||||
- Cloudflare registered email
|
|
||||||
- Cloudflare Global API Key
|
|
||||||
- The domain name must be resolved to the current server through Cloudflare
|
|
||||||
|
|
||||||
**How to get the Cloudflare Global API Key:**
|
|
||||||
|
|
||||||
1. Run the `x-ui` command in the terminal, then choose `Cloudflare SSL Certificate`.
|
|
||||||
2. Visit the link: [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens).
|
|
||||||
3. Click on "View Global API Key" (see the screenshot below):
|
|
||||||

|
|
||||||
4. You may need to re-authenticate your account. After that, the API Key will be shown (see the screenshot below):
|
|
||||||

|
|
||||||
|
|
||||||
When using, just enter your `domain name`, `email`, and `API KEY`. The diagram is as follows:
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Manual Install & Upgrade
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for manual install details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
1. To download the latest version of the compressed package directly to your server, run the following command:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
wget https://github.com/MHSanaei/3x-ui/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:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cd /root/
|
|
||||||
rm -rf x-ui/ /usr/local/x-ui/ /usr/bin/x-ui
|
|
||||||
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
|
||||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
|
||||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
|
||||||
mv x-ui/ /usr/local/
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable x-ui
|
|
||||||
systemctl restart x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Install with Docker
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for Docker details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
1. **Install Docker:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bash <(curl -sSL https://get.docker.com)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Clone the Project Repository:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
|
||||||
cd 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Start the Service:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
Add ```--pull always``` flag to make docker automatically recreate container if a newer image is pulled. See https://docs.docker.com/reference/cli/docker/container/run/#pull for more info.
|
|
||||||
|
|
||||||
**OR**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -itd \
|
|
||||||
-e XRAY_VMESS_AEAD_FORCED=false \
|
|
||||||
-v $PWD/db/:/etc/x-ui/ \
|
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--network=host \
|
|
||||||
--restart=unless-stopped \
|
|
||||||
--name 3x-ui \
|
|
||||||
ghcr.io/mhsanaei/3x-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Update to the Latest Version:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd 3x-ui
|
|
||||||
docker compose down
|
|
||||||
docker compose pull 3x-ui
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Remove 3x-ui from Docker:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker stop 3x-ui
|
|
||||||
docker rm 3x-ui
|
|
||||||
cd --
|
|
||||||
rm -r 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Nginx Settings
|
|
||||||
<details>
|
|
||||||
<summary>Click for Reverse Proxy Configuration</summary>
|
|
||||||
|
|
||||||
#### Nginx Reverse Proxy
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Nginx sub-path
|
|
||||||
- Ensure that the "URI Path" in the `/sub` panel settings is the same.
|
|
||||||
- The `url` in the panel settings needs to end with `/`.
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location /sub {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Recommended OS
|
|
||||||
|
|
||||||
- Ubuntu 22.04+
|
|
||||||
- Debian 12+
|
|
||||||
- CentOS 8+
|
|
||||||
- OpenEuler 22.03+
|
|
||||||
- Fedora 36+
|
|
||||||
- Arch Linux
|
|
||||||
- Parch Linux
|
|
||||||
- Manjaro
|
|
||||||
- Armbian
|
|
||||||
- AlmaLinux 9.5+
|
|
||||||
- Rocky Linux 9.5+
|
|
||||||
- Oracle Linux 8+
|
|
||||||
- OpenSUSE Tubleweed
|
|
||||||
- Amazon Linux 2023
|
|
||||||
- Virtuozzo Linux 8+
|
|
||||||
- Windows x64
|
|
||||||
|
|
||||||
## Supported Architectures and Devices
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for Supported Architectures and devices details</summary>
|
|
||||||
|
|
||||||
Our platform offers compatibility with a diverse range of architectures and devices, ensuring flexibility across various computing environments. The following are key architectures that we support:
|
|
||||||
|
|
||||||
- **amd64**: This prevalent architecture is the standard for personal computers and servers, accommodating most modern operating systems seamlessly.
|
|
||||||
|
|
||||||
- **x86 / i386**: Widely adopted in desktop and laptop computers, this architecture enjoys broad support from numerous operating systems and applications, including but not limited to Windows, macOS, and Linux systems.
|
|
||||||
|
|
||||||
- **armv8 / arm64 / aarch64**: Tailored for contemporary mobile and embedded devices, such as smartphones and tablets, this architecture is exemplified by devices like Raspberry Pi 4, Raspberry Pi 3, Raspberry Pi Zero 2/Zero 2 W, Orange Pi 3 LTS, and more.
|
|
||||||
|
|
||||||
- **armv7 / arm / arm32**: Serving as the architecture for older mobile and embedded devices, it remains widely utilized in devices like Orange Pi Zero LTS, Orange Pi PC Plus, Raspberry Pi 2, among others.
|
|
||||||
|
|
||||||
- **armv6 / arm / arm32**: Geared towards very old embedded devices, this architecture, while less prevalent, is still in use. Devices such as Raspberry Pi 1, Raspberry Pi Zero/Zero W, rely on this architecture.
|
|
||||||
|
|
||||||
- **armv5 / arm / arm32**: An older architecture primarily associated with early embedded systems, it is less common today but may still be found in legacy devices like early Raspberry Pi versions and some older smartphones.
|
|
||||||
|
|
||||||
- **s390x**: This architecture is commonly used in IBM mainframe computers and offers high performance and reliability for enterprise workloads.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Languages
|
|
||||||
|
|
||||||
- Arabic
|
|
||||||
- English
|
|
||||||
- Persian
|
|
||||||
- Traditional Chinese
|
|
||||||
- Simplified Chinese
|
|
||||||
- Japanese
|
|
||||||
- Russian
|
|
||||||
- Vietnamese
|
|
||||||
- Spanish
|
|
||||||
- Indonesian
|
|
||||||
- Ukrainian
|
|
||||||
- Turkish
|
|
||||||
- Português (Brazil)
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- System Status Monitoring
|
|
||||||
- Search within all inbounds and clients
|
|
||||||
- Dark/Light theme
|
|
||||||
- Supports multi-user and multi-protocol
|
|
||||||
- Supports protocols, including VMESS, VLESS, Trojan, Shadowsocks, Dokodemo-door, Socks, HTTP, wireguard
|
|
||||||
- Supports XTLS native Protocols, including RPRX-Direct, Vision, REALITY
|
|
||||||
- Traffic statistics, traffic limit, expiration time limit
|
|
||||||
- Customizable Xray configuration templates
|
|
||||||
- Supports HTTPS access panel (self-provided domain name + SSL certificate)
|
|
||||||
- Supports One-Click SSL certificate application and automatic renewal
|
|
||||||
- For more advanced configuration items, please refer to the panel
|
|
||||||
- Fixes API routes (user setting will be created with API)
|
|
||||||
- Supports changing configs by different items provided in the panel.
|
|
||||||
- Supports export/import database from the panel
|
|
||||||
|
|
||||||
|
|
||||||
## Default Panel Settings
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for default settings details</summary>
|
|
||||||
|
|
||||||
### Username, Password, Port, and Web Base Path
|
|
||||||
|
|
||||||
If you choose not to modify these settings, they will be generated randomly (this does not apply to Docker).
|
|
||||||
|
|
||||||
**Default Settings for Docker:**
|
|
||||||
- **Username:** admin
|
|
||||||
- **Password:** admin
|
|
||||||
- **Port:** 2053
|
|
||||||
|
|
||||||
### Database Management:
|
|
||||||
|
|
||||||
You can conveniently perform database Backups and Restores directly from the panel.
|
|
||||||
|
|
||||||
- **Database Path:**
|
|
||||||
- `/etc/x-ui/x-ui.db`
|
|
||||||
|
|
||||||
|
|
||||||
### Web Base Path
|
|
||||||
|
|
||||||
1. **Reset Web Base Path:**
|
|
||||||
- Open your terminal.
|
|
||||||
- Run the `x-ui` command.
|
|
||||||
- Select the option to `Reset Web Base Path`.
|
|
||||||
|
|
||||||
2. **Generate or Customize Path:**
|
|
||||||
- The path will be randomly generated, or you can enter a custom path.
|
|
||||||
|
|
||||||
3. **View Current Settings:**
|
|
||||||
- To view your current settings, use the `x-ui settings` command in the terminal or `View Current Settings` in `x-ui`
|
|
||||||
|
|
||||||
### Security Recommendation:
|
|
||||||
- For enhanced security, use a long, random word in your URL structure.
|
|
||||||
|
|
||||||
**Examples:**
|
|
||||||
- `http://ip:port/*webbasepath*/panel`
|
|
||||||
- `http://domain:port/*webbasepath*/panel`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## WARP Configuration
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for WARP configuration details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
**For versions `v2.1.0` and later:**
|
|
||||||
|
|
||||||
WARP is built-in, and no additional installation is required. Simply turn on the necessary configuration in the panel.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## IP Limit
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for IP limit details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
**Note:** IP Limit won't work correctly when using IP Tunnel.
|
|
||||||
|
|
||||||
- **For versions up to `v1.6.1`:**
|
|
||||||
- The IP limit is built-in to the panel
|
|
||||||
|
|
||||||
**For versions `v1.7.0` and newer:**
|
|
||||||
|
|
||||||
To enable the IP Limit functionality, you need to install `fail2ban` and its required files by following these steps:
|
|
||||||
|
|
||||||
1. Run the `x-ui` command in the terminal, then choose `IP Limit Management`.
|
|
||||||
2. You will see the following options:
|
|
||||||
|
|
||||||
- **Change Ban Duration:** Adjust the duration of bans.
|
|
||||||
- **Unban Everyone:** Lift all current bans.
|
|
||||||
- **Check Logs:** Review the logs.
|
|
||||||
- **Fail2ban Status:** Check the status of `fail2ban`.
|
|
||||||
- **Restart Fail2ban:** Restart the `fail2ban` service.
|
|
||||||
- **Uninstall Fail2ban:** Uninstall Fail2ban with configuration.
|
|
||||||
|
|
||||||
3. Add a path for the access log on the panel by setting `Xray Configs/log/Access log` to `./access.log` then save and restart xray.
|
|
||||||
|
|
||||||
- **For versions before `v2.1.3`:**
|
|
||||||
- You need to set the access log path manually in your Xray configuration:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
"log": {
|
|
||||||
"access": "./access.log",
|
|
||||||
"dnsLog": false,
|
|
||||||
"loglevel": "warning"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- **For versions `v2.1.3` and newer:**
|
|
||||||
- There is an option for configuring `access.log` directly from the panel.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Telegram Bot
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for Telegram bot details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
The web panel supports daily traffic, panel login, database backup, system status, client info, and other notification and functions through the Telegram Bot. To use the bot, you need to set the bot-related parameters in the panel, including:
|
|
||||||
|
|
||||||
- Telegram Token
|
|
||||||
- Admin Chat ID(s)
|
|
||||||
- Notification Time (in cron syntax)
|
|
||||||
- Expiration Date Notification
|
|
||||||
- Traffic Cap Notification
|
|
||||||
- Database Backup
|
|
||||||
- CPU Load Notification
|
|
||||||
|
|
||||||
|
|
||||||
**Reference syntax:**
|
|
||||||
|
|
||||||
- `30 \* \* \* \* \*` - Notify at the 30s of each point
|
|
||||||
- `0 \*/10 \* \* \* \*` - Notify at the first second of each 10 minutes
|
|
||||||
- `@hourly` - Hourly notification
|
|
||||||
- `@daily` - Daily notification (00:00 in the morning)
|
|
||||||
- `@weekly` - weekly notification
|
|
||||||
- `@every 8h` - Notify every 8 hours
|
|
||||||
|
|
||||||
### Telegram Bot Features
|
|
||||||
|
|
||||||
- Report periodic
|
|
||||||
- Login notification
|
|
||||||
- CPU threshold notification
|
|
||||||
- Threshold for Expiration time and Traffic to report in advance
|
|
||||||
- Support client report menu if client's telegram username added to the user's configurations
|
|
||||||
- Support telegram traffic report searched with UUID (VMESS/VLESS) or Password (TROJAN) - anonymously
|
|
||||||
- Menu-based bot
|
|
||||||
- Search client by email (only admin)
|
|
||||||
- Check all inbounds
|
|
||||||
- Check server status
|
|
||||||
- Check depleted users
|
|
||||||
- Receive backup by request and in periodic reports
|
|
||||||
- Multi-language bot
|
|
||||||
|
|
||||||
### Setting up Telegram bot
|
|
||||||
|
|
||||||
- Start [Botfather](https://t.me/BotFather) in your Telegram account:
|
|
||||||

|
|
||||||
|
|
||||||
- Create a new Bot using /newbot command: It will ask you 2 questions, A name and a username for your bot. Note that the username has to end with the word "bot".
|
|
||||||

|
|
||||||
|
|
||||||
- Start the bot you've just created. You can find the link to your bot here.
|
|
||||||

|
|
||||||
|
|
||||||
- Enter your panel and config Telegram bot settings like below:
|
|
||||||

|
|
||||||
|
|
||||||
Enter your bot token in input field number 3.
|
|
||||||
Enter the user ID in input field number 4. The Telegram accounts with this id will be the bot admin. (You can enter more than one, Just separate them with ,)
|
|
||||||
|
|
||||||
- How to get Telegram user ID? Use this [bot](https://t.me/useridinfobot), Start the bot and it will give you the Telegram user ID.
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## API Routes
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for API routes details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
- [API Documentation](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
|
|
||||||
- `/login` with `POST` user data: `{username: '', password: ''}` for login
|
|
||||||
- `/panel/api/inbounds` base for following actions:
|
|
||||||
|
|
||||||
| Method | Path | Action |
|
|
||||||
| :----: | ---------------------------------- | ------------------------------------------- |
|
|
||||||
| `GET` | `"/list"` | Get all inbounds |
|
|
||||||
| `GET` | `"/get/:id"` | Get inbound with inbound.id |
|
|
||||||
| `GET` | `"/getClientTraffics/:email"` | Get Client Traffics with email |
|
|
||||||
| `GET` | `"/getClientTrafficsById/:id"` | Get client's traffic By ID |
|
|
||||||
| `GET` | `"/createbackup"` | Telegram bot sends backup to admins |
|
|
||||||
| `POST` | `"/add"` | Add inbound |
|
|
||||||
| `POST` | `"/del/:id"` | Delete Inbound |
|
|
||||||
| `POST` | `"/update/:id"` | Update Inbound |
|
|
||||||
| `POST` | `"/clientIps/:email"` | Client Ip address |
|
|
||||||
| `POST` | `"/clearClientIps/:email"` | Clear Client Ip address |
|
|
||||||
| `POST` | `"/addClient"` | Add Client to inbound |
|
|
||||||
| `POST` | `"/:id/delClient/:clientId"` | Delete Client by clientId\* |
|
|
||||||
| `POST` | `"/updateClient/:clientId"` | Update Client by clientId\* |
|
|
||||||
| `POST` | `"/:id/resetClientTraffic/:email"` | Reset Client's Traffic |
|
|
||||||
| `POST` | `"/resetAllTraffics"` | Reset traffics of all inbounds |
|
|
||||||
| `POST` | `"/resetAllClientTraffics/:id"` | Reset traffics of all clients in an inbound |
|
|
||||||
| `POST` | `"/delDepletedClients/:id"` | Delete inbound depleted clients (-1: all) |
|
|
||||||
| `POST` | `"/onlines"` | Get Online users ( list of emails ) |
|
|
||||||
|
|
||||||
\*- The field `clientId` should be filled by:
|
|
||||||
|
|
||||||
- `client.id` for VMESS and VLESS
|
|
||||||
- `client.password` for TROJAN
|
|
||||||
- `client.email` for Shadowsocks
|
|
||||||
|
|
||||||
- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Click for environment variables details</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
| Variable | Type | Default |
|
|
||||||
| -------------- | :--------------------------------------------: | :------------ |
|
|
||||||
| XUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
|
||||||
| XUI_DEBUG | `boolean` | `false` |
|
|
||||||
| XUI_BIN_FOLDER | `string` | `"bin"` |
|
|
||||||
| XUI_DB_FOLDER | `string` | `"/etc/x-ui"` |
|
|
||||||
| XUI_LOG_FOLDER | `string` | `"/var/log"` |
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Preview
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/01-overview-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/02-inbounds-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/04-add-client-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/05-settings-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/06-configs-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/07-bot-light.png">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## A Special Thanks to
|
|
||||||
|
|
||||||
- [alireza0](https://github.com/alireza0/)
|
|
||||||
|
|
||||||
## Acknowledgment
|
|
||||||
|
|
||||||
- [Iran v2ray rules](https://github.com/chocolate4u/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](https://github.com/runetfreedom/russia-v2ray-rules-dat) (License: **GPL-3.0**): _This repository contains automatically updated V2Ray routing rules based on data on blocked domains and addresses in Russia._
|
|
||||||
|
|
||||||
## Stargazers over Time
|
## Stargazers over Time
|
||||||
|
|
||||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||||
|
|
604
README.ru_RU.md
|
@ -7,17 +7,39 @@
|
||||||
</picture>
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**Продвинутая веб-панель • Построена на основе Xray Core**
|
[](https://github.com/MHSanaei/3x-ui/releases)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/actions)
|
||||||
|
[](#)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/releases/latest)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
[](https://github.com/MHSanaei/3x-ui/releases)
|
**3X-UI** — продвинутая панель управления с открытым исходным кодом на основе веб-интерфейса, разработанная для управления сервером Xray-core. Предоставляет удобный интерфейс для настройки и мониторинга различных VPN и прокси-протоколов.
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
|
||||||
|
|
||||||
> **Отказ от ответственности:** Этот проект предназначен только для личного обучения и общения. Пожалуйста, не используйте его в незаконных целях и не применяйте в производственной среде.
|
> [!IMPORTANT]
|
||||||
|
> Этот проект предназначен только для личного использования, пожалуйста, не используйте его в незаконных целях и в производственной среде.
|
||||||
|
|
||||||
**Если этот проект оказался полезным для вас, вы можете оценить его, поставив звёздочку** :star2:
|
Как улучшенная версия оригинального проекта X-UI, 3X-UI обеспечивает повышенную стабильность, более широкую поддержку протоколов и дополнительные функции.
|
||||||
|
|
||||||
|
## Быстрый старт
|
||||||
|
|
||||||
|
```
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
Полную документацию смотрите в [вики проекта](https://github.com/MHSanaei/3x-ui/wiki).
|
||||||
|
|
||||||
|
## Особая благодарность
|
||||||
|
|
||||||
|
- [alireza0](https://github.com/alireza0/)
|
||||||
|
|
||||||
|
## Благодарности
|
||||||
|
|
||||||
|
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (Лицензия: **GPL-3.0**): _Улучшенные правила маршрутизации для v2ray/xray и v2ray/xray-clients со встроенными иранскими доменами и фокусом на безопасность и блокировку рекламы._
|
||||||
|
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (Лицензия: **GPL-3.0**): _Этот репозиторий содержит автоматически обновляемые правила маршрутизации V2Ray на основе данных о заблокированных доменах и адресах в России._
|
||||||
|
|
||||||
|
## Поддержка проекта
|
||||||
|
|
||||||
|
**Если этот проект полезен для вас, вы можете поставить ему**:star2:
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
||||||
|
@ -29,568 +51,6 @@
|
||||||
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
||||||
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
||||||
|
|
||||||
## Установка и обновление
|
## Звезды с течением времени
|
||||||
|
|
||||||
```
|
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Установить старую версию (мы не рекомендуем)
|
|
||||||
|
|
||||||
Чтобы установить желаемую версию, используйте следующую команду установки. Например, ver `v1.7.9`:
|
|
||||||
|
|
||||||
```
|
|
||||||
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
|
|
||||||
```
|
|
||||||
|
|
||||||
## SSL Сертификат
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации об SSL сертификате</summary>
|
|
||||||
|
|
||||||
### ACME
|
|
||||||
|
|
||||||
Для управления SSL сертификатами с помощью ACME:
|
|
||||||
|
|
||||||
1. Убедитесь, что ваш домен правильно настроен и указывает на сервер.
|
|
||||||
2. Выполните команду `x-ui` в терминале, затем выберите `SSL Certificate Management`.
|
|
||||||
3. Вам будут предложены следующие опции:
|
|
||||||
|
|
||||||
- **Get SSL:** Получить SSL сертификаты.
|
|
||||||
- **Revoke:** Отозвать существующие SSL сертификаты.
|
|
||||||
- **Force Renew:** Принудительно перевыпустить SSL сертификаты.
|
|
||||||
- **Show Existing Domains:** Отобразить все сертификаты доменов, доступные на сервере.
|
|
||||||
- **Set Certificate Paths for the Panel:** Укажите сертификат для вашего домена, который будет использоваться панелью.
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
Для установки и использования Certbot:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apt-get install certbot -y
|
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d вашдомен.com
|
|
||||||
certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloudflare
|
|
||||||
|
|
||||||
Скрипт управления включает встроенное приложение для получения SSL сертификата через Cloudflare. Чтобы использовать этот скрипт для запроса сертификата, вам потребуется следующее:
|
|
||||||
|
|
||||||
- Email, зарегистрированный в Cloudflare
|
|
||||||
- Глобальный API-ключ Cloudflare
|
|
||||||
- Доменное имя должно указывать на текущий сервер через Cloudflare
|
|
||||||
|
|
||||||
**Как получить глобальный API-ключ Cloudflare:**
|
|
||||||
|
|
||||||
1. Выполните команду `x-ui` в терминале, затем выберите `Cloudflare SSL Certificate`.
|
|
||||||
2. Перейдите по ссылке: [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens).
|
|
||||||
3. Нажмите на "View Global API Key" (см. скриншот ниже):
|
|
||||||

|
|
||||||
4. Возможно, вам потребуется повторно пройти аутентификацию. После этого ключ API будет отображён (см. скриншот ниже):
|
|
||||||

|
|
||||||
|
|
||||||
При использовании просто введите ваше `доменное имя`, `email` и `API-ключ`. Схема приведена ниже:
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Ручная установка и обновление
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о ручной установке</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
1. Чтобы скачать последнюю версию архива напрямую на ваш сервер, выполните следующую команду:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
2. После загрузки архива выполните следующие команды для установки или обновления x-ui:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
s390x) echo 's390x' ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cd /root/
|
|
||||||
rm -rf x-ui/ /usr/local/x-ui/ /usr/bin/x-ui
|
|
||||||
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
|
||||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
|
||||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
|
||||||
mv x-ui/ /usr/local/
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable x-ui
|
|
||||||
systemctl restart x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Установка с помощью Docker
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о Docker</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
1. **Установите Docker:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bash <(curl -sSL https://get.docker.com)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Склонируйте репозиторий проекта:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
|
||||||
cd 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Запустите сервис:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
Добавьте параметр ```--pull always``` для автоматического обновления контейнера, когда публикуется новый образ. Подробности: https://docs.docker.com/reference/cli/docker/container/run/#pull
|
|
||||||
|
|
||||||
**ИЛИ**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -itd \
|
|
||||||
-e XRAY_VMESS_AEAD_FORCED=false \
|
|
||||||
-v $PWD/db/:/etc/x-ui/ \
|
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--network=host \
|
|
||||||
--restart=unless-stopped \
|
|
||||||
--name 3x-ui \
|
|
||||||
ghcr.io/mhsanaei/3x-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Обновление до последней версии:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd 3x-ui
|
|
||||||
docker compose down
|
|
||||||
docker compose pull 3x-ui
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
5. **Удаление 3x-ui из Docker:**
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker stop 3x-ui
|
|
||||||
docker rm 3x-ui
|
|
||||||
cd --
|
|
||||||
rm -r 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Настройки Nginx
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите чтобы просмотреть конфигурацию обратного прокси-сервера</summary>
|
|
||||||
|
|
||||||
#### Обратный прокси-сервер Nginx
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Nginx sub-path
|
|
||||||
- Убедитесь, что "корневой путь URL адреса панели" в настройках панели и `/sub` совпадают.
|
|
||||||
- В настройках панели `url` должен заканчиваться на `/`.
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location /sub {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Рекомендуемые ОС
|
|
||||||
|
|
||||||
- Ubuntu 22.04+
|
|
||||||
- Debian 12+
|
|
||||||
- CentOS 8+
|
|
||||||
- OpenEuler 22.03+
|
|
||||||
- Fedora 36+
|
|
||||||
- Arch Linux
|
|
||||||
- Parch Linux
|
|
||||||
- Manjaro
|
|
||||||
- Armbian
|
|
||||||
- AlmaLinux 9.5+
|
|
||||||
- Rocky Linux 9.5+
|
|
||||||
- Oracle Linux 8+
|
|
||||||
- OpenSUSE Tubleweed
|
|
||||||
- Amazon Linux 2023
|
|
||||||
- Virtuozzo Linux 8+
|
|
||||||
- Windows x64
|
|
||||||
|
|
||||||
## Поддерживаемые архитектуры и устройства
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о поддерживаемых архитектурах и устройствах</summary>
|
|
||||||
|
|
||||||
Наша платформа поддерживает разнообразные архитектуры и устройства, обеспечивая гибкость в различных вычислительных средах. Вот основные архитектуры, которые мы поддерживаем:
|
|
||||||
|
|
||||||
- **amd64**: Эта распространенная архитектура является стандартом для персональных компьютеров и серверов, обеспечивая беспроблемную работу большинства современных операционных систем.
|
|
||||||
|
|
||||||
- **x86 / i386**: Широко используется в настольных и портативных компьютерах. Эта архитектура имеет широкую поддержку со стороны множества операционных систем и приложений, включая, но не ограничиваясь, Windows, macOS и Linux.
|
|
||||||
|
|
||||||
- **armv8 / arm64 / aarch64**: Предназначена для современных мобильных и встроенных устройств, таких как смартфоны и планшеты. Эта архитектура представлена устройствами, такими как Raspberry Pi 4, Raspberry Pi 3, Raspberry Pi Zero 2/Zero 2 W, Orange Pi 3 LTS и другими.
|
|
||||||
|
|
||||||
- **armv7 / arm / arm32**: Служит архитектурой для старых мобильных и встроенных устройств, оставаясь широко используемой в таких устройствах, как Orange Pi Zero LTS, Orange Pi PC Plus, Raspberry Pi 2 и других.
|
|
||||||
|
|
||||||
- **armv6 / arm / arm32**: Ориентирована на очень старые встроенные устройства, эта архитектура, хотя и менее распространенная, всё ещё используется. Например, такие устройства, как Raspberry Pi 1, Raspberry Pi Zero/Zero W, полагаются на эту архитектуру.
|
|
||||||
|
|
||||||
- **armv5 / arm / arm32**: Более старая архитектура, ассоциируемая с ранними встроенными системами, сегодня менее распространена, но всё ещё может быть найдена в устаревших устройствах, таких как ранние версии Raspberry Pi и некоторые старые смартфоны.
|
|
||||||
|
|
||||||
- **s390x**: Эта архитектура обычно используется в мейнфреймах IBM и обеспечивает высокую производительность и надежность для корпоративных рабочих нагрузок.
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Языки
|
|
||||||
|
|
||||||
- Arabic (арабский)
|
|
||||||
- English (английский)
|
|
||||||
- Persian (персидский)
|
|
||||||
- Traditional Chinese (традиционный китайский)
|
|
||||||
- Simplified Chinese (упрощенный китайский)
|
|
||||||
- Japanese (японский)
|
|
||||||
- Russian (русский)
|
|
||||||
- Vietnamese (вьетнамский)
|
|
||||||
- Spanish (испанский)
|
|
||||||
- Indonesian (индонезийский)
|
|
||||||
- Ukrainian (украинский)
|
|
||||||
- Turkish (турецкий)
|
|
||||||
- Português (Brazil) (португальский (Бразилия))
|
|
||||||
|
|
||||||
## Возможности
|
|
||||||
|
|
||||||
- Мониторинг состояния системы
|
|
||||||
- Поиск по всем входящим подключениям и клиентам
|
|
||||||
- Тёмная/светлая тема
|
|
||||||
- Поддержка нескольких пользователей и протоколов
|
|
||||||
- Поддержка протоколов, включая VMESS, VLESS, Trojan, Shadowsocks, Dokodemo-door, Socks, HTTP, WireGuard
|
|
||||||
- Поддержка протоколов XTLS, включая RPRX-Direct, Vision, REALITY
|
|
||||||
- Статистика трафика, ограничение трафика, ограничение по времени истечения
|
|
||||||
- Настраиваемые шаблоны конфигурации Xray
|
|
||||||
- Поддержка HTTPS доступа к панели (ваше доменное имя + SSL сертификат)
|
|
||||||
- Поддержка установки SSL-сертификата в один клик и автоматического перевыпуска
|
|
||||||
- Для получения более продвинутых настроек обращайтесь к панели
|
|
||||||
- Исправляет маршруты API (настройка пользователя будет создана через API)
|
|
||||||
- Поддержка изменения конфигураций по различным элементам, предоставленным в панели
|
|
||||||
- Поддержка экспорта/импорта базы данных из панели
|
|
||||||
|
|
||||||
## Настройки панели по умолчанию
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о настройках по умолчанию</summary>
|
|
||||||
|
|
||||||
### Имя пользователя, Пароль, Порт и Web Base Path
|
|
||||||
|
|
||||||
Если вы не измените эти настройки, они будут сгенерированы случайным образом (это не относится к Docker).
|
|
||||||
|
|
||||||
**Настройки по умолчанию для Docker:**
|
|
||||||
- **Имя пользователя:** admin
|
|
||||||
- **Пароль:** admin
|
|
||||||
- **Порт:** 2053
|
|
||||||
|
|
||||||
### Управление базой данных:
|
|
||||||
|
|
||||||
Вы можете удобно выполнять резервное копирование и восстановление базы данных прямо из панели.
|
|
||||||
|
|
||||||
- **Путь к базе данных:**
|
|
||||||
- `/etc/x-ui/x-ui.db`
|
|
||||||
|
|
||||||
### Webbasepath
|
|
||||||
|
|
||||||
1. **Сбросить webbasepath:**
|
|
||||||
- Откройте терминал.
|
|
||||||
- Выполните команду `x-ui`.
|
|
||||||
- Выберите опцию `Reset Web Base Path`.
|
|
||||||
|
|
||||||
2. **Генерация или настройка пути:**
|
|
||||||
- Путь будет сгенерирован случайным образом, или вы можете ввести собственный путь.
|
|
||||||
|
|
||||||
3. **Просмотр текущих настроек:**
|
|
||||||
- Чтобы просмотреть текущие настройки, используйте команду `x-ui settings` в терминале или опцию `View Current Settings` в `x-ui`.
|
|
||||||
|
|
||||||
### Рекомендации по безопасности:
|
|
||||||
- Для повышения безопасности используйте длинное случайное слово в структуре вашего URL.
|
|
||||||
|
|
||||||
**Примеры:**
|
|
||||||
- `http://ip_адрес:порт/*webbasepath*/panel`
|
|
||||||
- `http://домен:порт/*webbasepath*/panel`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Настройка WARP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о настройке WARP</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
**Для версий `v2.1.0` и новее:**
|
|
||||||
|
|
||||||
WARP встроен, и дополнительная установка не требуется. Просто включите необходимую конфигурацию в панели.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Ограничение IP
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации об ограничении IP</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
**Примечание:** Ограничение IP не будет работать корректно при использовании IP Tunnel.
|
|
||||||
|
|
||||||
- **Для версий до `v1.6.1`:**
|
|
||||||
- Ограничение IP встроено в панель.
|
|
||||||
|
|
||||||
**Для версий `v1.7.0` и новее:**
|
|
||||||
|
|
||||||
Чтобы включить функциональность ограничения IP, вам нужно установить `fail2ban` и его необходимые файлы, выполнив следующие шаги:
|
|
||||||
|
|
||||||
1. Выполните команду `x-ui` в терминале, затем выберите `IP Limit Management`.
|
|
||||||
2. Вам будут предложены следующие опции:
|
|
||||||
|
|
||||||
- **Change Ban Duration:** Отрегулировать длительность блокировок.
|
|
||||||
- **Unban Everyone:** Снять все текущие блокировки.
|
|
||||||
- **Check Logs:** Просмотреть логи.
|
|
||||||
- **Fail2ban Status:** Проверить статус `fail2ban`.
|
|
||||||
- **Restart Fail2ban:** Перезапустить службу `fail2ban`.
|
|
||||||
- **Uninstall Fail2ban:** Удалить Fail2ban с его конфигурацией.
|
|
||||||
|
|
||||||
3. Добавьте путь к логам доступа в панели, установив `Xray Configs/log/Access log` в `./access.log`, затем сохраните и перезапустите xray.
|
|
||||||
|
|
||||||
- **Для версий до `v2.1.3`:**
|
|
||||||
- Вам нужно вручную установить путь к логам доступа в вашей конфигурации Xray:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
"log": {
|
|
||||||
"access": "./access.log",
|
|
||||||
"dnsLog": false,
|
|
||||||
"loglevel": "warning"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Для версий `v2.1.3` и новее:**
|
|
||||||
- Есть возможность настройки `access.log` непосредственно из панели.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Телеграм-бот
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о телеграм-боте</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
Веб-панель поддерживает уведомления и функции, такие как ежедневный трафик, вход в панель, резервное копирование базы данных, состояние системы, информация о клиентах и другие, через телеграм-бота. Чтобы использовать бота, вам нужно настроить параметры, связанные с ботом, в панели, включая:
|
|
||||||
|
|
||||||
- Токен Telegram
|
|
||||||
- ID чата админа(-ов)
|
|
||||||
- Время уведомлений (в синтаксисе cron)
|
|
||||||
- Уведомления о дате истечения
|
|
||||||
- Уведомления о лимите трафика
|
|
||||||
- Резервное копирование базы данных
|
|
||||||
- Уведомления о загрузке CPU
|
|
||||||
|
|
||||||
**Примеры синтаксиса:**
|
|
||||||
|
|
||||||
- `30 * * * * *` - Уведомлять на 30-й секунде каждого часа
|
|
||||||
- `0 */10 * * * *` - Уведомлять на первой секунде каждых 10 минут
|
|
||||||
- `@hourly` - Ежечасное уведомление
|
|
||||||
- `@daily` - Ежедневное уведомление (в 00:00)
|
|
||||||
- `@weekly` - Еженедельное уведомление
|
|
||||||
- `@every 8h` - Уведомлять каждые 8 часов
|
|
||||||
|
|
||||||
### Возможности телеграм-бота
|
|
||||||
|
|
||||||
- Периодические отчеты
|
|
||||||
- Уведомления о входе
|
|
||||||
- Уведомления о пороге загруженности процессора
|
|
||||||
- Уведомления о времени истечения и трафике заранее
|
|
||||||
- Поддерживает меню отчетов клиента, если имя пользователя телеграм клиента добавлено в конфигурации пользователя
|
|
||||||
- Поддержка отчета о трафике через Telegram, поиск по UUID (VMESS/VLESS) или паролю (TROJAN) - анонимно
|
|
||||||
- Бот, основанный на меню
|
|
||||||
- Поиск клиента по email (только администратор)
|
|
||||||
- Проверка всех входящих соединений
|
|
||||||
- Проверка состояния сервера
|
|
||||||
- Проверка истекших пользователей
|
|
||||||
- Получение резервных копий по запросу и в периодических отчётах
|
|
||||||
- Многоязычный бот
|
|
||||||
|
|
||||||
### Настройка телеграм-бота
|
|
||||||
|
|
||||||
- Запустите [Botfather](https://t.me/BotFather) в вашем аккаунте Telegram:
|
|
||||||

|
|
||||||
|
|
||||||
- Создайте нового бота с помощью команды /newbot: у вас спросят 2 вопроса: отображаемое имя и имя пользователя для вашего бота. Обратите внимание, что имя пользователя должно заканчиваться на слово "bot".
|
|
||||||

|
|
||||||
|
|
||||||
- Запустите созданного бота. Ссылку на вашего бота можно найти здесь.
|
|
||||||

|
|
||||||
|
|
||||||
- Перейдите в панель и настройте параметры телеграм-бота следующим образом:
|
|
||||||

|
|
||||||
|
|
||||||
Введите токен вашего бота в поле ввода номер 3.
|
|
||||||
Введите ID пользователя в поле ввода номер 4. Telegram-аккаунты с этим ID будут администраторами бота. (Вы можете ввести несколько ID, разделяя их запятой)
|
|
||||||
|
|
||||||
- Как получить ID пользователя Telegram? Используйте этот [бот](https://t.me/useridinfobot). Запустите бота, и он отобразит ваш ID пользователя Telegram.
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Маршруты API
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о маршрутах API</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
- [API документация](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
|
|
||||||
- `/login` с `POST`-данными: `{username: '', password: ''}` для входа
|
|
||||||
- `/panel/api/inbounds` это базовый путь для следующих действий:
|
|
||||||
|
|
||||||
| Метод | Путь | Действие
|
|
||||||
| :----: | -----------------------------------| -------------------------------------------
|
|
||||||
| `GET` | `"/list"` | Получить все входящие соединения
|
|
||||||
| `GET` | `"/get/:id"` | Получить входящее соединение с inbound.id
|
|
||||||
| `GET` | `"/getClientTraffics/:email"` | Получить трафик клиента по email
|
|
||||||
| `GET` | `"/getClientTrafficsById/:id"` | Получить трафик клиента по ID
|
|
||||||
| `GET` | `"/createbackup"` | Telegram-бот отправит резервную копию администраторам
|
|
||||||
| `POST` | `"/add"` | Добавить входящее соединение
|
|
||||||
| `POST` | `"/del/:id"` | Удалить входящее соединение
|
|
||||||
| `POST` | `"/update/:id"` | Обновить входящее соединение
|
|
||||||
| `POST` | `"/clientIps/:email"` | IP-адрес клиента
|
|
||||||
| `POST` | `"/clearClientIps/:email"` | Очистить IP-адреса клиента
|
|
||||||
| `POST` | `"/addClient"` | Добавить клиента к входящему соединению
|
|
||||||
| `POST` | `"/:id/delClient/:clientId"` | Удалить клиента по clientId\*
|
|
||||||
| `POST` | `"/updateClient/:clientId"` | Обновить клиента по clientId\*
|
|
||||||
| `POST` | `"/:id/resetClientTraffic/:email"` | Сбросить трафик клиента
|
|
||||||
| `POST` | `"/resetAllTraffics"` | Сбросить трафик всех входящих соединений
|
|
||||||
| `POST` | `"/resetAllClientTraffics/:id"` | Сбросить трафик всех клиентов в входящем соединении
|
|
||||||
| `POST` | `"/delDepletedClients/:id"` | Удалить истекших клиентов в входящем соединении (-1: всех)
|
|
||||||
| `POST` | `"/onlines"` | Получить пользователей, которые находятся онлайн (список email'ов)
|
|
||||||
|
|
||||||
\*- Поле `clientId` должно быть заполнено следующим образом:
|
|
||||||
|
|
||||||
- `client.id` для VMESS и VLESS
|
|
||||||
- `client.password` для TROJAN
|
|
||||||
- `client.email` для Shadowsocks
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Переменные среды
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Нажмите для получения информации о переменных среды</summary>
|
|
||||||
|
|
||||||
#### Использование
|
|
||||||
|
|
||||||
| Переменная | Тип | Значение по умолчанию |
|
|
||||||
| ---------------- | :------------------------------------------: | :-------------------- |
|
|
||||||
| XUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
|
||||||
| XUI_DEBUG | `boolean` | `false` |
|
|
||||||
| XUI_BIN_FOLDER | `string` | `"bin"` |
|
|
||||||
| XUI_DB_FOLDER | `string` | `"/etc/x-ui"` |
|
|
||||||
| XUI_LOG_FOLDER | `string` | `"/var/log"` |
|
|
||||||
|
|
||||||
Пример:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Предварительный Просмотр
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/01-overview-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/02-inbounds-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/04-add-client-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/05-settings-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/06-configs-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/07-bot-light.png">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## Особая благодарность
|
|
||||||
|
|
||||||
- [alireza0](https://github.com/alireza0/)
|
|
||||||
|
|
||||||
## Благодарности
|
|
||||||
|
|
||||||
- [Iran v2ray rules](https://github.com/chocolate4u/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](https://github.com/runetfreedom/russia-v2ray-rules-dat) (License: **GPL-3.0**): _Этот репозиторий содержит автоматически обновляемые правила маршрутизации V2Ray на основе данных о заблокированных доменах и адресах в России._
|
|
||||||
|
|
||||||
## Число звёзд со временем
|
|
||||||
|
|
||||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
|
||||||
|
|
597
README.zh_CN.md
|
@ -7,17 +7,39 @@
|
||||||
</picture>
|
</picture>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**一个更好的面板 • 基于Xray Core构建**
|
[](https://github.com/MHSanaei/3x-ui/releases)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/actions)
|
||||||
|
[](#)
|
||||||
|
[](https://github.com/MHSanaei/3x-ui/releases/latest)
|
||||||
|
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
|
||||||
[](https://github.com/MHSanaei/3x-ui/releases)
|
**3X-UI** — 一个基于网页的高级开源控制面板,专为管理 Xray-core 服务器而设计。它提供了用户友好的界面,用于配置和监控各种 VPN 和代理协议。
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](#)
|
|
||||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
|
||||||
|
|
||||||
> **Disclaimer:** 此项目仅供个人学习交流,请不要用于非法目的,请不要在生产环境中使用。
|
> [!IMPORTANT]
|
||||||
|
> 本项目仅用于个人使用和通信,请勿将其用于非法目的,请勿在生产环境中使用。
|
||||||
|
|
||||||
**如果此项目对你有用,请给一个**:star2:
|
作为原始 X-UI 项目的增强版本,3X-UI 提供了更好的稳定性、更广泛的协议支持和额外的功能。
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
```
|
||||||
|
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||||
|
```
|
||||||
|
|
||||||
|
完整文档请参阅 [项目Wiki](https://github.com/MHSanaei/3x-ui/wiki)。
|
||||||
|
|
||||||
|
## 特别感谢
|
||||||
|
|
||||||
|
- [alireza0](https://github.com/alireza0/)
|
||||||
|
|
||||||
|
## 致谢
|
||||||
|
|
||||||
|
- [Iran v2ray rules](https://github.com/chocolate4u/Iran-v2ray-rules) (许可证: **GPL-3.0**): _增强的 v2ray/xray 和 v2ray/xray-clients 路由规则,内置伊朗域名,专注于安全性和广告拦截。_
|
||||||
|
- [Russia v2ray rules](https://github.com/runetfreedom/russia-v2ray-rules-dat) (许可证: **GPL-3.0**): _此仓库包含基于俄罗斯被阻止域名和地址数据自动更新的 V2Ray 路由规则。_
|
||||||
|
|
||||||
|
## 支持项目
|
||||||
|
|
||||||
|
**如果这个项目对您有帮助,您可以给它一个**:star2:
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
||||||
|
@ -29,561 +51,6 @@
|
||||||
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
- MATIC (polygon): `0x41C9548675D044c6Bfb425786C765bc37427256A`
|
||||||
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
- LTC (Litecoin): `ltc1q2ach7x6d2zq0n4l0t4zl7d7xe2s6fs7a3vspwv`
|
||||||
|
|
||||||
## 安装 & 升级
|
## 随时间变化的星标数
|
||||||
|
|
||||||
```
|
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.6.0/install.sh)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 安装旧版本 (我们不建议)
|
|
||||||
|
|
||||||
要安装您想要的版本,请使用以下安装命令。例如,ver `v1.7.9`:
|
|
||||||
|
|
||||||
```
|
|
||||||
VERSION=v1.7.9 && bash <(curl -Ls "https://raw.githubusercontent.com/mhsanaei/3x-ui/$VERSION/install.sh") $VERSION
|
|
||||||
```
|
|
||||||
|
|
||||||
### SSL证书
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看SSL证书详情</summary>
|
|
||||||
|
|
||||||
### ACME
|
|
||||||
|
|
||||||
使用ACME管理SSL证书:
|
|
||||||
|
|
||||||
1. 确保您的域名正确解析到服务器。
|
|
||||||
2. 在终端中运行 `x-ui` 命令,然后选择 `SSL证书管理`。
|
|
||||||
3. 您将看到以下选项:
|
|
||||||
|
|
||||||
- **Get SSL:** 获取SSL证书。
|
|
||||||
- **Revoke:** 吊销现有的SSL证书。
|
|
||||||
- **Force Renew:** 强制更新SSL证书。
|
|
||||||
- **Show Existing Domains:** 显示服务器上所有可用的域证书。
|
|
||||||
- **Set Certificate Paths for the Panel:** 指定用于面板的域证书。
|
|
||||||
|
|
||||||
### Certbot
|
|
||||||
|
|
||||||
安装并使用Certbot:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apt-get install certbot -y
|
|
||||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
|
||||||
certbot renew --dry-run
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloudflare
|
|
||||||
|
|
||||||
管理脚本内置了Cloudflare的SSL证书申请。要使用此脚本申请证书,您需要以下信息:
|
|
||||||
|
|
||||||
- Cloudflare注册的电子邮件
|
|
||||||
- Cloudflare全局API密钥
|
|
||||||
- 域名必须通过Cloudflare解析到当前服务器
|
|
||||||
|
|
||||||
**如何获取Cloudflare全局API密钥:**
|
|
||||||
|
|
||||||
1. 在终端中运行 `x-ui` 命令,然后选择 `Cloudflare SSL证书`。
|
|
||||||
2. 访问链接:[Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)。
|
|
||||||
3. 点击“查看全局API密钥”(参见下图):
|
|
||||||

|
|
||||||
4. 您可能需要重新验证您的账户。之后将显示API密钥(参见下图):
|
|
||||||

|
|
||||||
|
|
||||||
使用时,只需输入您的 `域名`、`电子邮件` 和 `API密钥`。如下图所示:
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 手动安装 & 升级
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 手动安装 & 升级</summary>
|
|
||||||
|
|
||||||
#### 使用
|
|
||||||
|
|
||||||
1. 若要将最新版本的压缩包直接下载到服务器,请运行以下命令:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
|
|
||||||
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 下载压缩包后,执行以下命令安装或升级 x-ui:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ARCH=$(uname -m)
|
|
||||||
case "${ARCH}" in
|
|
||||||
x86_64 | x64 | amd64) XUI_ARCH="amd64" ;;
|
|
||||||
i*86 | x86) XUI_ARCH="386" ;;
|
|
||||||
armv8* | armv8 | arm64 | aarch64) XUI_ARCH="arm64" ;;
|
|
||||||
armv7* | armv7) XUI_ARCH="armv7" ;;
|
|
||||||
armv6* | armv6) XUI_ARCH="armv6" ;;
|
|
||||||
armv5* | armv5) XUI_ARCH="armv5" ;;
|
|
||||||
*) XUI_ARCH="amd64" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
cd /root/
|
|
||||||
rm -rf x-ui/ /usr/local/x-ui/ /usr/bin/x-ui
|
|
||||||
tar zxvf x-ui-linux-${XUI_ARCH}.tar.gz
|
|
||||||
chmod +x x-ui/x-ui x-ui/bin/xray-linux-* x-ui/x-ui.sh
|
|
||||||
cp x-ui/x-ui.sh /usr/bin/x-ui
|
|
||||||
cp -f x-ui/x-ui.service /etc/systemd/system/
|
|
||||||
mv x-ui/ /usr/local/
|
|
||||||
systemctl daemon-reload
|
|
||||||
systemctl enable x-ui
|
|
||||||
systemctl restart x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 通过Docker安装
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 通过Docker安装</summary>
|
|
||||||
|
|
||||||
#### 使用
|
|
||||||
|
|
||||||
1. 安装Docker:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
bash <(curl -sSL https://get.docker.com)
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 克隆仓库:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/MHSanaei/3x-ui.git
|
|
||||||
cd 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 运行服务:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
或
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -itd \
|
|
||||||
-e XRAY_VMESS_AEAD_FORCED=false \
|
|
||||||
-v $PWD/db/:/etc/x-ui/ \
|
|
||||||
-v $PWD/cert/:/root/cert/ \
|
|
||||||
--network=host \
|
|
||||||
--restart=unless-stopped \
|
|
||||||
--name 3x-ui \
|
|
||||||
ghcr.io/mhsanaei/3x-ui:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
更新至最新版本
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cd 3x-ui
|
|
||||||
docker compose down
|
|
||||||
docker compose pull 3x-ui
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
从Docker中删除3x-ui
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker stop 3x-ui
|
|
||||||
docker rm 3x-ui
|
|
||||||
cd --
|
|
||||||
rm -r 3x-ui
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
## Nginx 设置
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 反向代理配置</summary>
|
|
||||||
|
|
||||||
#### Nginx反向代理
|
|
||||||
```nginx
|
|
||||||
location / {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Nginx子路径
|
|
||||||
- 确保 `/sub` 面板设置中的"面板url根路径"一致
|
|
||||||
- 面板设置中的 `url` 需要以 `/` 结尾
|
|
||||||
|
|
||||||
```nginx
|
|
||||||
location /sub {
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header Range $http_range;
|
|
||||||
proxy_set_header If-Range $http_if_range;
|
|
||||||
proxy_redirect off;
|
|
||||||
proxy_pass http://127.0.0.1:2053;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 建议使用的操作系统
|
|
||||||
|
|
||||||
- Ubuntu 22.04+
|
|
||||||
- Debian 12+
|
|
||||||
- CentOS 8+
|
|
||||||
- OpenEuler 22.03+
|
|
||||||
- Fedora 36+
|
|
||||||
- Arch Linux
|
|
||||||
- Parch Linux
|
|
||||||
- Manjaro
|
|
||||||
- Armbian
|
|
||||||
- AlmaLinux 9.5+
|
|
||||||
- Rocky Linux 9.5+
|
|
||||||
- Oracle Linux 8+
|
|
||||||
- OpenSUSE Tubleweed
|
|
||||||
- Amazon Linux 2023
|
|
||||||
- Virtuozzo Linux 8+
|
|
||||||
- Windows x64
|
|
||||||
|
|
||||||
## 支持的架构和设备
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 支持的架构和设备</summary>
|
|
||||||
|
|
||||||
我们的平台提供与各种架构和设备的兼容性,确保在各种计算环境中的灵活性。以下是我们支持的关键架构:
|
|
||||||
|
|
||||||
- **amd64**: 这种流行的架构是个人计算机和服务器的标准,可以无缝地适应大多数现代操作系统。
|
|
||||||
|
|
||||||
- **x86 / i386**: 这种架构在台式机和笔记本电脑中被广泛采用,得到了众多操作系统和应用程序的广泛支持,包括但不限于 Windows、macOS 和 Linux 系统。
|
|
||||||
|
|
||||||
- **armv8 / arm64 / aarch64**: 这种架构专为智能手机和平板电脑等当代移动和嵌入式设备量身定制,以 Raspberry Pi 4、Raspberry Pi 3、Raspberry Pi Zero 2/Zero 2 W、Orange Pi 3 LTS 等设备为例。
|
|
||||||
|
|
||||||
- **armv7 / arm / arm32**: 作为较旧的移动和嵌入式设备的架构,它仍然广泛用于Orange Pi Zero LTS、Orange Pi PC Plus、Raspberry Pi 2等设备。
|
|
||||||
|
|
||||||
- **armv6 / arm / arm32**: 这种架构面向非常老旧的嵌入式设备,虽然不太普遍,但仍在使用中。Raspberry Pi 1、Raspberry Pi Zero/Zero W 等设备都依赖于这种架构。
|
|
||||||
|
|
||||||
- **armv5 / arm / arm32**: 它是一种主要与早期嵌入式系统相关的旧架构,目前不太常见,但仍可能出现在早期 Raspberry Pi 版本和一些旧智能手机等传统设备中。
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Languages
|
|
||||||
|
|
||||||
- Arabic (阿拉伯)
|
|
||||||
- English(英语)
|
|
||||||
- Persian(波斯语)
|
|
||||||
- Traditional Chinese(繁体中文)
|
|
||||||
- Simplified Chinese(简体中文)
|
|
||||||
- Japanese(日语)
|
|
||||||
- Russian(俄语)
|
|
||||||
- Vietnamese(越南语)
|
|
||||||
- Spanish(西班牙语)
|
|
||||||
- Indonesian(印尼语)
|
|
||||||
- Ukrainian(乌克兰语)
|
|
||||||
- Turkish(土耳其语)
|
|
||||||
- Português (Brazil)(葡萄牙语(巴西))
|
|
||||||
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- 系统状态监控
|
|
||||||
- 在所有入站和客户端中搜索
|
|
||||||
- 深色/浅色主题
|
|
||||||
- 支持多用户和多协议
|
|
||||||
- 支持多种协议,包括 VMess、VLESS、Trojan、Shadowsocks、Dokodemo-door、Socks、HTTP、wireguard
|
|
||||||
- 支持 XTLS 原生协议,包括 RPRX-Direct、Vision、REALITY
|
|
||||||
- 流量统计、流量限制、过期时间限制
|
|
||||||
- 可自定义的 Xray配置模板
|
|
||||||
- 支持HTTPS访问面板(自建域名+SSL证书)
|
|
||||||
- 支持一键式SSL证书申请和自动续费
|
|
||||||
- 更多高级配置项目请参考面板
|
|
||||||
- 修复了 API 路由(用户设置将使用 API 创建)
|
|
||||||
- 支持通过面板中提供的不同项目更改配置。
|
|
||||||
- 支持从面板导出/导入数据库
|
|
||||||
|
|
||||||
|
|
||||||
## 默认面板设置
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看默认设置详情</summary>
|
|
||||||
|
|
||||||
### 用户名、密码、端口和 Web Base Path
|
|
||||||
|
|
||||||
如果您选择不修改这些设置,它们将随机生成(不适用于 Docker)。
|
|
||||||
|
|
||||||
**Docker 的默认设置:**
|
|
||||||
- **用户名:** admin
|
|
||||||
- **密码:** admin
|
|
||||||
- **端口:** 2053
|
|
||||||
|
|
||||||
### 数据库管理:
|
|
||||||
|
|
||||||
您可以直接在面板中方便地进行数据库备份和还原。
|
|
||||||
|
|
||||||
- **数据库路径:**
|
|
||||||
- `/etc/x-ui/x-ui.db`
|
|
||||||
|
|
||||||
### Web 基础路径
|
|
||||||
|
|
||||||
1. **重置 Web 基础路径:**
|
|
||||||
- 打开终端。
|
|
||||||
- 运行 `x-ui` 命令。
|
|
||||||
- 选择 `重置 Web 基础路径` 选项。
|
|
||||||
|
|
||||||
2. **生成或自定义路径:**
|
|
||||||
- 路径将会随机生成,或者您可以输入自定义路径。
|
|
||||||
|
|
||||||
3. **查看当前设置:**
|
|
||||||
- 要查看当前设置,请在终端中使用 `x-ui settings` 命令,或在 `x-ui` 面板中点击 `查看当前设置`。
|
|
||||||
|
|
||||||
### 安全建议:
|
|
||||||
- 为了提高安全性,建议在URL结构中使用一个长的随机词。
|
|
||||||
|
|
||||||
**示例:**
|
|
||||||
- `http://ip:port/*webbasepath*/panel`
|
|
||||||
- `http://domain:port/*webbasepath*/panel`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## WARP 配置
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 WARP 配置详情</summary>
|
|
||||||
|
|
||||||
#### 使用方法
|
|
||||||
|
|
||||||
**对于 `v2.1.0` 及之后的版本:**
|
|
||||||
|
|
||||||
WARP 已内置,无需额外安装。只需在面板中开启相关配置即可。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## IP 限制
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 IP 限制详情</summary>
|
|
||||||
|
|
||||||
#### 使用方法
|
|
||||||
|
|
||||||
**注意:** 当使用 IP 隧道时,IP 限制将无法正常工作。
|
|
||||||
|
|
||||||
- **对于 `v1.6.1` 及之前的版本:**
|
|
||||||
- IP 限制功能已内置于面板中。
|
|
||||||
|
|
||||||
**对于 `v1.7.0` 及更新的版本:**
|
|
||||||
|
|
||||||
要启用 IP 限制功能,您需要安装 `fail2ban` 及其所需的文件,步骤如下:
|
|
||||||
|
|
||||||
1. 在终端中运行 `x-ui` 命令,然后选择 `IP 限制管理`。
|
|
||||||
2. 您将看到以下选项:
|
|
||||||
|
|
||||||
- **更改封禁时长:** 调整封禁时长。
|
|
||||||
- **解除所有封禁:** 解除当前的所有封禁。
|
|
||||||
- **查看日志:** 查看日志。
|
|
||||||
- **Fail2ban 状态:** 检查 `fail2ban` 的状态。
|
|
||||||
- **重启 Fail2ban:** 重启 `fail2ban` 服务。
|
|
||||||
- **卸载 Fail2ban:** 卸载带有配置的 Fail2ban。
|
|
||||||
|
|
||||||
3. 在面板中通过设置 `Xray 配置/log/访问日志` 为 `./access.log` 添加访问日志路径,然后保存并重启 Xray。
|
|
||||||
|
|
||||||
- **对于 `v2.1.3` 之前的版本:**
|
|
||||||
- 您需要在 Xray 配置中手动设置访问日志路径:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
"log": {
|
|
||||||
"access": "./access.log",
|
|
||||||
"dnsLog": false,
|
|
||||||
"loglevel": "warning"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- **对于 `v2.1.3` 及之后的版本:**
|
|
||||||
- 面板中直接提供了配置 `access.log` 的选项。
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Telegram 机器人
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 Telegram 机器人</summary>
|
|
||||||
|
|
||||||
#### 使用
|
|
||||||
|
|
||||||
Web 面板通过 Telegram Bot 支持每日流量、面板登录、数据库备份、系统状态、客户端信息等通知和功能。要使用机器人,您需要在面板中设置机器人相关参数,包括:
|
|
||||||
|
|
||||||
- 电报令牌
|
|
||||||
- 管理员聊天 ID
|
|
||||||
- 通知时间(cron 语法)
|
|
||||||
- 到期日期通知
|
|
||||||
- 流量上限通知
|
|
||||||
- 数据库备份
|
|
||||||
- CPU 负载通知
|
|
||||||
|
|
||||||
|
|
||||||
**参考:**
|
|
||||||
|
|
||||||
- `30 \* \* \* \* \*` - 在每个点的 30 秒处通知
|
|
||||||
- `0 \*/10 \* \* \* \*` - 每 10 分钟的第一秒通知
|
|
||||||
- `@hourly` - 每小时通知
|
|
||||||
- `@daily` - 每天通知 (00:00)
|
|
||||||
- `@weekly` - 每周通知
|
|
||||||
- `@every 8h` - 每8小时通知
|
|
||||||
|
|
||||||
### Telegram Bot 功能
|
|
||||||
|
|
||||||
- 定期报告
|
|
||||||
- 登录通知
|
|
||||||
- CPU 阈值通知
|
|
||||||
- 提前报告的过期时间和流量阈值
|
|
||||||
- 如果将客户的电报用户名添加到用户的配置中,则支持客户端报告菜单
|
|
||||||
- 支持使用UUID(VMESS/VLESS)或密码(TROJAN)搜索报文流量报告 - 匿名
|
|
||||||
- 基于菜单的机器人
|
|
||||||
- 通过电子邮件搜索客户端(仅限管理员)
|
|
||||||
- 检查所有入库
|
|
||||||
- 检查服务器状态
|
|
||||||
- 检查耗尽的用户
|
|
||||||
- 根据请求和定期报告接收备份
|
|
||||||
- 多语言机器人
|
|
||||||
|
|
||||||
### 注册 Telegram bot
|
|
||||||
|
|
||||||
- 与 [Botfather](https://t.me/BotFather) 对话:
|
|
||||||

|
|
||||||
|
|
||||||
- 使用 /newbot 创建新机器人:你需要提供机器人名称以及用户名,注意名称中末尾要包含“bot”
|
|
||||||

|
|
||||||
|
|
||||||
- 启动您刚刚创建的机器人。可以在此处找到机器人的链接。
|
|
||||||

|
|
||||||
|
|
||||||
- 输入您的面板并配置 Telegram 机器人设置,如下所示:
|
|
||||||

|
|
||||||
|
|
||||||
在输入字段编号 3 中输入机器人令牌。
|
|
||||||
在输入字段编号 4 中输入用户 ID。具有此 id 的 Telegram 帐户将是机器人管理员。 (您可以输入多个,只需将它们用“ ,”分开即可)
|
|
||||||
|
|
||||||
- 如何获取TG ID? 使用 [bot](https://t.me/useridinfobot), 启动机器人,它会给你 Telegram 用户 ID。
|
|
||||||

|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## API 路由
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 API 路由</summary>
|
|
||||||
|
|
||||||
#### 使用
|
|
||||||
|
|
||||||
- [API 文档](https://www.postman.com/hsanaei/3x-ui/collection/q1l5l0u/3x-ui)
|
|
||||||
- `/login` 使用 `POST` 用户名称 & 密码: `{username: '', password: ''}` 登录
|
|
||||||
- `/panel/api/inbounds` 以下操作的基础:
|
|
||||||
|
|
||||||
| 方法 | 路径 | 操作 |
|
|
||||||
| :----: | ---------------------------------- | --------------------------------- |
|
|
||||||
| `GET` | `"/list"` | 获取所有入站 |
|
|
||||||
| `GET` | `"/get/:id"` | 获取所有入站以及inbound.id |
|
|
||||||
| `GET` | `"/getClientTraffics/:email"` | 通过电子邮件获取客户端流量 |
|
|
||||||
| `GET` | `"/createbackup"` | Telegram 机器人向管理员发送备份 |
|
|
||||||
| `POST` | `"/add"` | 添加入站 |
|
|
||||||
| `POST` | `"/del/:id"` | 删除入站 |
|
|
||||||
| `POST` | `"/update/:id"` | 更新入站 |
|
|
||||||
| `POST` | `"/clientIps/:email"` | 客户端 IP 地址 |
|
|
||||||
| `POST` | `"/clearClientIps/:email"` | 清除客户端 IP 地址 |
|
|
||||||
| `POST` | `"/addClient"` | 将客户端添加到入站 |
|
|
||||||
| `POST` | `"/:id/delClient/:clientId"` | 通过 clientId\* 删除客户端 |
|
|
||||||
| `POST` | `"/updateClient/:clientId"` | 通过 clientId\* 更新客户端 |
|
|
||||||
| `POST` | `"/:id/resetClientTraffic/:email"` | 重置客户端的流量 |
|
|
||||||
| `POST` | `"/resetAllTraffics"` | 重置所有入站的流量 |
|
|
||||||
| `POST` | `"/resetAllClientTraffics/:id"` | 重置入站中所有客户端的流量 |
|
|
||||||
| `POST` | `"/delDepletedClients/:id"` | 删除入站耗尽的客户端 (-1: all) |
|
|
||||||
| `POST` | `"/onlines"` | 获取在线用户 ( 电子邮件列表 ) |
|
|
||||||
|
|
||||||
\*- `clientId` 项应该使用下列数据
|
|
||||||
|
|
||||||
- `client.id` VMESS and VLESS
|
|
||||||
- `client.password` TROJAN
|
|
||||||
- `client.email` Shadowsocks
|
|
||||||
|
|
||||||
- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D5146551-dda3cab3-0e33-485f-96f9-d4262f437ac5%26entityType%3Dcollection%26workspaceId%3Dd64f609f-485a-4951-9b8f-876b3f917124)
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 环境变量
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>点击查看 环境变量</summary>
|
|
||||||
|
|
||||||
#### Usage
|
|
||||||
|
|
||||||
| 变量 | Type | 默认 |
|
|
||||||
| -------------- | :--------------------------------------------: | :------------ |
|
|
||||||
| XUI_LOG_LEVEL | `"debug"` \| `"info"` \| `"warn"` \| `"error"` | `"info"` |
|
|
||||||
| XUI_DEBUG | `boolean` | `false` |
|
|
||||||
| XUI_BIN_FOLDER | `string` | `"bin"` |
|
|
||||||
| XUI_DB_FOLDER | `string` | `"/etc/x-ui"` |
|
|
||||||
| XUI_LOG_FOLDER | `string` | `"/var/log"` |
|
|
||||||
|
|
||||||
例子:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 预览
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/01-overview-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/01-overview-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/02-inbounds-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/02-inbounds-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/03-add-inbound-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/03-add-inbound-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/04-add-client-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/04-add-client-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/05-settings-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/05-settings-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/06-configs-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/06-configs-light.png">
|
|
||||||
</picture>
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./media/07-bot-dark.png">
|
|
||||||
<img alt="3x-ui" src="./media/07-bot-light.png">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## 特别感谢
|
|
||||||
|
|
||||||
- [alireza0](https://github.com/alireza0/)
|
|
||||||
|
|
||||||
## 致谢
|
|
||||||
|
|
||||||
- [Iran v2ray rules](https://github.com/chocolate4u/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](https://github.com/runetfreedom/russia-v2ray-rules-dat) (License: **GPL-3.0**): _This repository contains automatically updated V2Ray routing rules based on data on blocked domains and addresses in Russia._
|
|
||||||
|
|
||||||
## Star趋势
|
|
||||||
|
|
||||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
services:
|
services:
|
||||||
3x-ui:
|
3xui:
|
||||||
image: ghcr.io/mhsanaei/3x-ui:latest
|
build:
|
||||||
container_name: 3x-ui
|
context: .
|
||||||
hostname: yourhostname
|
dockerfile: ./Dockerfile
|
||||||
|
container_name: 3xui_app
|
||||||
|
# hostname: yourhostname <- optional
|
||||||
volumes:
|
volumes:
|
||||||
- $PWD/db/:/etc/x-ui/
|
- $PWD/db/:/etc/x-ui/
|
||||||
- $PWD/cert/:/root/cert/
|
- $PWD/cert/:/root/cert/
|
||||||
environment:
|
environment:
|
||||||
XRAY_VMESS_AEAD_FORCED: "false"
|
XRAY_VMESS_AEAD_FORCED: "false"
|
||||||
X_UI_ENABLE_FAIL2BAN: "true"
|
XUI_ENABLE_FAIL2BAN: "true"
|
||||||
tty: true
|
tty: true
|
||||||
network_mode: host
|
network_mode: host
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
55
go.mod
|
@ -1,11 +1,11 @@
|
||||||
module x-ui
|
module x-ui
|
||||||
|
|
||||||
go 1.24.3
|
go 1.24.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-contrib/gzip v1.2.3
|
github.com/gin-contrib/gzip v1.2.3
|
||||||
github.com/gin-contrib/sessions v1.0.3
|
github.com/gin-contrib/sessions v1.0.4
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.1
|
||||||
github.com/goccy/go-json v0.10.5
|
github.com/goccy/go-json v0.10.5
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
|
@ -14,36 +14,36 @@ require (
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4
|
github.com/pelletier/go-toml/v2 v2.2.4
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/shirou/gopsutil/v4 v4.25.4
|
github.com/shirou/gopsutil/v4 v4.25.6
|
||||||
github.com/valyala/fasthttp v1.62.0
|
github.com/valyala/fasthttp v1.63.0
|
||||||
github.com/xlzd/gotp v0.1.0
|
github.com/xlzd/gotp v0.1.0
|
||||||
github.com/xtls/xray-core v1.250306.1-0.20250516121834-800b8b50cc01
|
github.com/xtls/xray-core v1.250608.0
|
||||||
go.uber.org/atomic v1.11.0
|
go.uber.org/atomic v1.11.0
|
||||||
golang.org/x/crypto v0.38.0
|
golang.org/x/crypto v0.39.0
|
||||||
golang.org/x/text v0.25.0
|
golang.org/x/text v0.26.0
|
||||||
google.golang.org/grpc v1.72.1
|
google.golang.org/grpc v1.73.0
|
||||||
gorm.io/driver/sqlite v1.5.7
|
gorm.io/driver/sqlite v1.6.0
|
||||||
gorm.io/gorm v1.25.12
|
gorm.io/gorm v1.30.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||||
github.com/bytedance/sonic v1.13.2 // indirect
|
github.com/bytedance/sonic v1.13.3 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||||
github.com/cloudflare/circl v1.6.1 // indirect
|
github.com/cloudflare/circl v1.6.1 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||||
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 // indirect
|
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 // indirect
|
||||||
github.com/ebitengine/purego v0.8.3 // indirect
|
github.com/ebitengine/purego v0.8.4 // indirect
|
||||||
github.com/fasthttp/router v1.5.4 // indirect
|
github.com/fasthttp/router v1.5.4 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.9 // indirect
|
||||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/pprof v0.0.0-20250501235452-c0086092b71a // indirect
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 // indirect
|
||||||
github.com/gorilla/context v1.1.2 // indirect
|
github.com/gorilla/context v1.1.2 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/gorilla/sessions v1.4.0 // indirect
|
github.com/gorilla/sessions v1.4.0 // indirect
|
||||||
|
@ -52,8 +52,9 @@ require (
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/juju/ratelimit v1.0.2 // indirect
|
||||||
github.com/klauspost/compress v1.18.0 // indirect
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
@ -64,7 +65,7 @@ require (
|
||||||
github.com/pires/go-proxyproto v0.8.1 // indirect
|
github.com/pires/go-proxyproto v0.8.1 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/quic-go/quic-go v0.51.0 // indirect
|
github.com/quic-go/quic-go v0.52.0 // indirect
|
||||||
github.com/refraction-networking/utls v1.7.3 // indirect
|
github.com/refraction-networking/utls v1.7.3 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
github.com/rogpeppe/go-internal v1.14.1 // indirect
|
||||||
|
@ -75,27 +76,27 @@ require (
|
||||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fastjson v1.6.4 // indirect
|
github.com/valyala/fastjson v1.6.4 // indirect
|
||||||
github.com/vishvananda/netlink v1.3.1 // indirect
|
github.com/vishvananda/netlink v1.3.1 // indirect
|
||||||
github.com/vishvananda/netns v0.0.5 // indirect
|
github.com/vishvananda/netns v0.0.5 // indirect
|
||||||
github.com/xtls/reality v0.0.0-20250516070713-4df2ec9a5b47 // indirect
|
github.com/xtls/reality v0.0.0-20250627141458-e62c4aed0d57 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
go.uber.org/automaxprocs v1.6.0 // indirect
|
go.uber.org/automaxprocs v1.6.0 // indirect
|
||||||
go.uber.org/mock v0.5.2 // indirect
|
go.uber.org/mock v0.5.2 // indirect
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||||
golang.org/x/arch v0.17.0 // indirect
|
golang.org/x/arch v0.18.0 // indirect
|
||||||
golang.org/x/mod v0.24.0 // indirect
|
golang.org/x/mod v0.25.0 // indirect
|
||||||
golang.org/x/net v0.40.0 // indirect
|
golang.org/x/net v0.41.0 // indirect
|
||||||
golang.org/x/sync v0.14.0 // indirect
|
golang.org/x/sync v0.15.0 // indirect
|
||||||
golang.org/x/sys v0.33.0 // indirect
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
golang.org/x/time v0.11.0 // indirect
|
golang.org/x/time v0.12.0 // indirect
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.34.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 // indirect
|
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 // indirect
|
||||||
|
|
126
go.sum
|
@ -2,10 +2,10 @@ github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I=
|
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I=
|
||||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
||||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
|
||||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||||
|
@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||||
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||||
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 h1:ucRHb6/lvW/+mTEIGbvhcYU3S8+uSNkuMjx/qZFfhtM=
|
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33 h1:ucRHb6/lvW/+mTEIGbvhcYU3S8+uSNkuMjx/qZFfhtM=
|
||||||
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
github.com/dgryski/go-metro v0.0.0-20250106013310-edb8663e5e33/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||||
github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc=
|
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||||
github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
github.com/fasthttp/router v1.5.4 h1:oxdThbBwQgsDIYZ3wR1IavsNl6ZS9WdjKukeMikOnC8=
|
github.com/fasthttp/router v1.5.4 h1:oxdThbBwQgsDIYZ3wR1IavsNl6ZS9WdjKukeMikOnC8=
|
||||||
github.com/fasthttp/router v1.5.4/go.mod h1:3/hysWq6cky7dTfzaaEPZGdptwjwx0qzTgFCKEWRjgc=
|
github.com/fasthttp/router v1.5.4/go.mod h1:3/hysWq6cky7dTfzaaEPZGdptwjwx0qzTgFCKEWRjgc=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||||
|
@ -30,12 +30,12 @@ github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3
|
||||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||||
github.com/gin-contrib/gzip v1.2.3 h1:dAhT722RuEG330ce2agAs75z7yB+NKvX/ZM1r8w0u2U=
|
github.com/gin-contrib/gzip v1.2.3 h1:dAhT722RuEG330ce2agAs75z7yB+NKvX/ZM1r8w0u2U=
|
||||||
github.com/gin-contrib/gzip v1.2.3/go.mod h1:ad72i4Bzmaypk8M762gNXa2wkxxjbz0icRNnuLJ9a/c=
|
github.com/gin-contrib/gzip v1.2.3/go.mod h1:ad72i4Bzmaypk8M762gNXa2wkxxjbz0icRNnuLJ9a/c=
|
||||||
github.com/gin-contrib/sessions v1.0.3 h1:AZ4j0AalLsGqdrKNbbrKcXx9OJZqViirvNGsJTxcQps=
|
github.com/gin-contrib/sessions v1.0.4 h1:ha6CNdpYiTOK/hTp05miJLbpTSNfOnFg5Jm2kbcqy8U=
|
||||||
github.com/gin-contrib/sessions v1.0.3/go.mod h1:5i4XMx4KPtQihnzxEqG9u1K446lO3G19jAi2GtbfsAI=
|
github.com/gin-contrib/sessions v1.0.4/go.mod h1:ccmkrb2z6iU2osiAHZG3x3J4suJK+OU27oqzlWOqQgs=
|
||||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
@ -49,8 +49,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
|
||||||
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
|
@ -66,8 +66,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/pprof v0.0.0-20250501235452-c0086092b71a h1:rDA3FfmxwXR+BVKKdz55WwMJ1pD2hJQNW31d+l3mPk4=
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ=
|
||||||
github.com/google/pprof v0.0.0-20250501235452-c0086092b71a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
|
github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o=
|
||||||
|
@ -88,11 +88,13 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI=
|
||||||
|
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
|
@ -137,8 +139,8 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4
|
||||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.51.0 h1:K8exxe9zXxeRKxaXxi/GpUqYiTrtdiWP8bo1KFya6Wc=
|
github.com/quic-go/quic-go v0.52.0 h1:/SlHrCRElyaU6MaEPKqKr9z83sBg2v4FLLvWM+Z47pA=
|
||||||
github.com/quic-go/quic-go v0.51.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
github.com/quic-go/quic-go v0.52.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
||||||
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
|
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
|
||||||
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
|
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
|
@ -155,8 +157,8 @@ github.com/savsgio/gotils v0.0.0-20250408102913-196191ec6287 h1:qIQ0tWF9vxGtkJa2
|
||||||
github.com/savsgio/gotils v0.0.0-20250408102913-196191ec6287/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
github.com/savsgio/gotils v0.0.0-20250408102913-196191ec6287/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
||||||
github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw=
|
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
|
||||||
github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA=
|
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
@ -174,14 +176,14 @@ github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfj
|
||||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.62.0 h1:8dKRBX/y2rCzyc6903Zu1+3qN0H/d2MsxPPmVNamiH0=
|
github.com/valyala/fasthttp v1.63.0 h1:DisIL8OjB7ul2d7cBaMRcKTQDYnrGy56R4FCiuDP0Ns=
|
||||||
github.com/valyala/fasthttp v1.62.0/go.mod h1:FCINgr4GKdKqV8Q0xv8b+UxPV+H/O5nNFo3D+r54Htg=
|
github.com/valyala/fasthttp v1.63.0/go.mod h1:REc4IeW+cAEyLrRPa5A81MIjvz0QE1laoTX2EaPHKJM=
|
||||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
|
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
|
||||||
|
@ -190,26 +192,26 @@ github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zd
|
||||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po=
|
github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po=
|
||||||
github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg=
|
github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg=
|
||||||
github.com/xtls/reality v0.0.0-20250516070713-4df2ec9a5b47 h1:9aJWkgWBwZ83l3j7+hBh3SurvRKuNfCgsSner5n6BcM=
|
github.com/xtls/reality v0.0.0-20250627141458-e62c4aed0d57 h1:CJzC54UytAYnNbJSlAFi9MXOofSUAtpoQTKIA3hUpj8=
|
||||||
github.com/xtls/reality v0.0.0-20250516070713-4df2ec9a5b47/go.mod h1:bJdU3ExzfUlY40Xxfibq3THW9IHiE8mHu/tEzud5JWM=
|
github.com/xtls/reality v0.0.0-20250627141458-e62c4aed0d57/go.mod h1:yD47RN65bDLZgyHWMfFDiqlzrq4usDMt/Xzsk6tMbhw=
|
||||||
github.com/xtls/xray-core v1.250306.1-0.20250516121834-800b8b50cc01 h1:zthqg0MKk0yJBguuUmE+/Ya0nXGEz8OV7YucmkT2zII=
|
github.com/xtls/xray-core v1.250608.0 h1:/M0LwzFeFAZf+vdZQhqNYjUXDfPv5hOeYw6jsiAdgWI=
|
||||||
github.com/xtls/xray-core v1.250306.1-0.20250516121834-800b8b50cc01/go.mod h1:BNFvL6I5sEaw1bZELtteqijPEugqfQaG+dH75gSaHrc=
|
github.com/xtls/xray-core v1.250608.0/go.mod h1:MkfIs2WZ5VLtZHAwDKosSS05Kx5zFFOzvly7Hy6pfPs=
|
||||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||||
|
@ -218,16 +220,16 @@ go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
|
golang.org/x/arch v0.18.0 h1:WN9poc33zL4AzGxqf8VtpKUnGvMi8O9lhNyBMF/85qc=
|
||||||
golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.18.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -236,20 +238,20 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a h1:GIqLhp/cYUkuGuiT+vJk8vhOP86L4+SP5j8yXgeVpvI=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250409194420-de1ac958c67a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
|
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
||||||
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -261,10 +263,10 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I=
|
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||||
gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
|
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
|
||||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h1:sfK5nHuG7lRFZ2FdTT3RimOqWBg8IrVm+/Vko1FVOsk=
|
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h1:sfK5nHuG7lRFZ2FdTT3RimOqWBg8IrVm+/Vko1FVOsk=
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g=
|
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g=
|
||||||
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||||
|
|
|
@ -57,7 +57,7 @@ install_base() {
|
||||||
ubuntu | debian | armbian)
|
ubuntu | debian | armbian)
|
||||||
apt-get update && apt-get install -y -q wget curl tar tzdata
|
apt-get update && apt-get install -y -q wget curl tar tzdata
|
||||||
;;
|
;;
|
||||||
centos | almalinux | rocky | ol)
|
centos | rhel | almalinux | rocky | ol)
|
||||||
yum -y update && yum install -y -q wget curl tar tzdata
|
yum -y update && yum install -y -q wget curl tar tzdata
|
||||||
;;
|
;;
|
||||||
fedora | amzn | virtuozzo)
|
fedora | amzn | virtuozzo)
|
||||||
|
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 253 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 248 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 240 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 240 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 277 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 266 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 202 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 206 KiB |
|
@ -2150,7 +2150,7 @@ Inbound.TrojanSettings.Fallback = class extends XrayCommonClass {
|
||||||
Inbound.ShadowsocksSettings = class extends Inbound.Settings {
|
Inbound.ShadowsocksSettings = class extends Inbound.Settings {
|
||||||
constructor(protocol,
|
constructor(protocol,
|
||||||
method = SSMethods.BLAKE3_AES_256_GCM,
|
method = SSMethods.BLAKE3_AES_256_GCM,
|
||||||
password = RandomUtil.randomShadowsocksPassword(),
|
password = '',
|
||||||
network = 'tcp,udp',
|
network = 'tcp,udp',
|
||||||
shadowsockses = [new Inbound.ShadowsocksSettings.Shadowsocks()],
|
shadowsockses = [new Inbound.ShadowsocksSettings.Shadowsocks()],
|
||||||
ivCheck = false,
|
ivCheck = false,
|
||||||
|
@ -2188,7 +2188,7 @@ Inbound.ShadowsocksSettings = class extends Inbound.Settings {
|
||||||
Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
|
Inbound.ShadowsocksSettings.Shadowsocks = class extends XrayCommonClass {
|
||||||
constructor(
|
constructor(
|
||||||
method = '',
|
method = '',
|
||||||
password = RandomUtil.randomShadowsocksPassword(),
|
password = '',
|
||||||
email = RandomUtil.randomLowerAndNum(8),
|
email = RandomUtil.randomLowerAndNum(8),
|
||||||
limitIp = 0,
|
limitIp = 0,
|
||||||
totalGB = 0,
|
totalGB = 0,
|
||||||
|
|
|
@ -138,8 +138,14 @@ class RandomUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static randomShadowsocksPassword() {
|
static randomShadowsocksPassword(method = SSMethods.BLAKE3_AES_256_GCM) {
|
||||||
const array = new Uint8Array(32);
|
let length = 32;
|
||||||
|
|
||||||
|
if ([SSMethods.BLAKE3_AES_128_GCM].includes(method)) {
|
||||||
|
length = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
const array = new Uint8Array(length);
|
||||||
|
|
||||||
window.crypto.getRandomValues(array);
|
window.crypto.getRandomValues(array);
|
||||||
|
|
||||||
|
@ -789,6 +795,25 @@ class LanguageManager {
|
||||||
if (window.navigator) {
|
if (window.navigator) {
|
||||||
lang = window.navigator.language || window.navigator.userLanguage;
|
lang = window.navigator.language || window.navigator.userLanguage;
|
||||||
|
|
||||||
|
const simularLangs = [
|
||||||
|
["ar", this.supportedLanguages[0].value],
|
||||||
|
["fa", this.supportedLanguages[2].value],
|
||||||
|
["ja", this.supportedLanguages[5].value],
|
||||||
|
["ru", this.supportedLanguages[6].value],
|
||||||
|
["vi", this.supportedLanguages[7].value],
|
||||||
|
["es", this.supportedLanguages[8].value],
|
||||||
|
["id", this.supportedLanguages[9].value],
|
||||||
|
["uk", this.supportedLanguages[10].value],
|
||||||
|
["tr", this.supportedLanguages[11].value],
|
||||||
|
["pt", this.supportedLanguages[12].value],
|
||||||
|
]
|
||||||
|
|
||||||
|
simularLangs.forEach((pair) => {
|
||||||
|
if (lang === pair[0]) {
|
||||||
|
lang = pair[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (LanguageManager.isSupportLanguage(lang)) {
|
if (LanguageManager.isSupportLanguage(lang)) {
|
||||||
CookieManager.setCookie("lang", lang, 150);
|
CookieManager.setCookie("lang", lang, 150);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"math"
|
||||||
|
|
||||||
"x-ui/util/common"
|
"x-ui/util/common"
|
||||||
)
|
)
|
||||||
|
@ -78,11 +79,11 @@ func (s *AllSetting) CheckValid() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.WebPort <= 0 || s.WebPort > 65535 {
|
if s.WebPort <= 0 || s.WebPort > math.MaxUint16 {
|
||||||
return common.NewError("web port is not a valid port:", s.WebPort)
|
return common.NewError("web port is not a valid port:", s.WebPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.SubPort <= 0 || s.SubPort > 65535 {
|
if s.SubPort <= 0 || s.SubPort > math.MaxUint16 {
|
||||||
return common.NewError("Sub port is not a valid port:", s.SubPort)
|
return common.NewError("Sub port is not a valid port:", s.SubPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
{{define "head"}}
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="renderer" content="webkit">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="robots" content="noindex,nofollow">
|
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue/antd.min.css">
|
|
||||||
<link rel="stylesheet" href="{{ .base_path }}assets/css/custom.min.css?{{ .cur_ver }}">
|
|
||||||
<style>
|
|
||||||
[v-cloak] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
/* vazirmatn-regular - arabic_latin_latin-ext */
|
|
||||||
@font-face {
|
|
||||||
font-display: swap;
|
|
||||||
font-family: 'Vazirmatn';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
src: url('{{ .base_path }}assets/Vazirmatn-UI-NL-Regular.woff2') format('woff2');
|
|
||||||
unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC, U+0030-0039;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Vazirmatn', 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
|
|
||||||
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif, 'Apple Color Emoji',
|
|
||||||
'Segoe UI Emoji', 'Segoe UI Symbol';
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<title>{{ .host }} – {{ i18n .title}}</title>
|
|
||||||
</head>
|
|
||||||
<div id="message"></div>
|
|
||||||
{{end}}
|
|
|
@ -1,14 +0,0 @@
|
||||||
{{define "js"}}
|
|
||||||
<script src="{{ .base_path }}assets/vue/vue.min.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/moment/moment.min.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/ant-design-vue/antd.min.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/axios/axios.min.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/qs/qs.min.js"></script>
|
|
||||||
<script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
|
|
||||||
<script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
|
|
||||||
<script>
|
|
||||||
const basePath = '{{ .base_path }}';
|
|
||||||
axios.defaults.baseURL = basePath;
|
|
||||||
</script>
|
|
||||||
{{end}}
|
|
58
web/html/common/page.html
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{{ define "page/head_start" }}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="renderer" content="webkit">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="robots" content="noindex,nofollow">
|
||||||
|
<link rel="stylesheet" href="{{ .base_path }}assets/ant-design-vue/antd.min.css">
|
||||||
|
<link rel="stylesheet" href="{{ .base_path }}assets/css/custom.min.css?{{ .cur_ver }}">
|
||||||
|
<style>
|
||||||
|
[v-cloak] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
/* vazirmatn-regular - arabic_latin_latin-ext */
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: 'Vazirmatn';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url('{{ .base_path }}assets/Vazirmatn-UI-NL-Regular.woff2') format('woff2');
|
||||||
|
unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC, U+0030-0039;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Vazirmatn', 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<title>{{ .host }} – {{ i18n .title}}</title>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/head_end" }}
|
||||||
|
</head>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/body_start" }}
|
||||||
|
<body>
|
||||||
|
<div id="message"></div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/body_scripts" }}
|
||||||
|
<script src="{{ .base_path }}assets/vue/vue.min.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/moment/moment.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/ant-design-vue/antd.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/axios/axios.min.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/qs/qs.min.js"></script>
|
||||||
|
<script src="{{ .base_path }}assets/js/axios-init.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/js/util/date-util.js?{{ .cur_ver }}"></script>
|
||||||
|
<script src="{{ .base_path }}assets/js/util/index.js?{{ .cur_ver }}"></script>
|
||||||
|
<script>
|
||||||
|
const basePath = '{{ .base_path }}';
|
||||||
|
axios.defaults.baseURL = basePath;
|
||||||
|
</script>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "page/body_end" }}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{ end }}
|
|
@ -41,14 +41,28 @@
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template slot="client" slot-scope="text, client">
|
<template slot="client" slot-scope="text, client">
|
||||||
<a-tooltip>
|
<a-space direction="horizontal" :size="2">
|
||||||
<template slot="title">
|
<a-tooltip>
|
||||||
<template v-if="!isClientEnabled(record, client.email)">{{ i18n "depleted" }}</template>
|
<template slot="title">
|
||||||
<template v-else-if="!client.enable">{{ i18n "disabled" }}</template>
|
<template v-if="!isClientEnabled(record, client.email)">{{ i18n "depleted" }}</template>
|
||||||
<template v-else-if="client.enable && isClientOnline(client.email)">{{ i18n "online" }}</template>
|
<template v-else-if="!client.enable">{{ i18n "disabled" }}</template>
|
||||||
</template>
|
<template v-else-if="client.enable && isClientOnline(client.email)">{{ i18n "online" }}</template>
|
||||||
<a-badge :class="isClientOnline(client.email)? 'online-animation' : ''" :color="client.enable ? statsExpColor(record, client.email) : themeSwitcher.isDarkTheme ? '#2c3950' : '#bcbcbc'"></a-badge>
|
</template>
|
||||||
</a-tooltip> [[ client.email ]]
|
<a-badge :class="isClientOnline(client.email)? 'online-animation' : ''" :color="client.enable ? statsExpColor(record, client.email) : themeSwitcher.isDarkTheme ? '#2c3950' : '#bcbcbc'"></a-badge>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-space direction="vertical" :size="2">
|
||||||
|
<span class="client-email">[[ client.email ]]</span>
|
||||||
|
<template v-if="client.comment && client.comment.trim()">
|
||||||
|
<a-tooltip v-if="client.comment.length > 50" :overlay-class-name="themeSwitcher.currentTheme">
|
||||||
|
<template slot="title">
|
||||||
|
[[ client.comment ]]
|
||||||
|
</template>
|
||||||
|
<span class="client-comment">[[ client.comment.substring(0, 47) + '...' ]]</span>
|
||||||
|
</a-tooltip>
|
||||||
|
<span v-else class="client-comment">[[ client.comment ]]</span>
|
||||||
|
</template>
|
||||||
|
</a-space>
|
||||||
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<template slot="traffic" slot-scope="text, client">
|
<template slot="traffic" slot-scope="text, client">
|
||||||
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<span>{{ i18n "reset" }}</span>
|
<span>{{ i18n "reset" }}</span>
|
||||||
</template>
|
</template>
|
||||||
{{ i18n "password" }}
|
{{ i18n "password" }}
|
||||||
<a-icon v-if="inbound.protocol === Protocols.SHADOWSOCKS"@click="client.password = RandomUtil.randomShadowsocksPassword()" type="sync"></a-icon>
|
<a-icon v-if="inbound.protocol === Protocols.SHADOWSOCKS" @click="client.password = RandomUtil.randomShadowsocksPassword(inbound.settings.method)" type="sync"></a-icon>
|
||||||
<a-icon v-if="inbound.protocol === Protocols.TROJAN" @click="client.password = RandomUtil.randomSeq(10)"type="sync"> </a-icon>
|
<a-icon v-if="inbound.protocol === Protocols.TROJAN" @click="client.password = RandomUtil.randomSeq(10)"type="sync"> </a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<span>{{ i18n "reset" }}</span>
|
<span>{{ i18n "reset" }}</span>
|
||||||
</template> Password <a-icon @click="inbound.settings.password = RandomUtil.randomShadowsocksPassword()" type="sync"></a-icon>
|
</template> Password <a-icon @click="inbound.settings.password = RandomUtil.randomShadowsocksPassword(inbound.settings.method)" type="sync"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</template>
|
</template>
|
||||||
<a-input v-model.trim="inbound.settings.password"></a-input>
|
<a-input v-model.trim="inbound.settings.password"></a-input>
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 769px) {
|
||||||
.ant-layout-content {
|
.ant-layout-content {
|
||||||
margin: 24px 16px;
|
margin: 24px 16px;
|
||||||
}
|
}
|
||||||
.ant-card-hoverable {
|
|
||||||
margin-inline: 0.3rem;
|
|
||||||
}
|
|
||||||
.ant-alert-error {
|
|
||||||
margin-inline: 0.3rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-col-sm-24 {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
}
|
||||||
.ant-card-dark h2 {
|
.ant-card-dark h2 {
|
||||||
color: var(--dark-color-text-primary);
|
color: var(--dark-color-text-primary);
|
||||||
|
@ -79,371 +68,385 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
{{ template "page/head_end" .}}
|
||||||
|
|
||||||
<body>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-sidebar></a-sidebar>
|
<a-sidebar></a-sidebar>
|
||||||
<a-layout id="content-layout">
|
<a-layout id="content-layout">
|
||||||
<a-layout-content>
|
<a-layout-content>
|
||||||
<a-spin :spinning="spinning" :delay="200" :tip="loadingTip">
|
<a-spin :spinning="loadingStates.spinning" :delay="200" :tip="loadingTip">
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-alert type="error" v-if="showAlert" :style="{ marginBottom: '10px' }"
|
<a-alert type="error" v-if="showAlert && loadingStates.fetched" :style="{ marginBottom: '10px' }"
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
color="red"
|
color="red"
|
||||||
description='{{ i18n "secAlertSsl" }}'
|
description='{{ i18n "secAlertSsl" }}'
|
||||||
show-icon closable>
|
show-icon closable>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</transition>
|
</transition>
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<template>
|
<template>
|
||||||
<a-row v-if="!status.isLoaded">
|
<a-row v-if="!loadingStates.fetched">
|
||||||
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
|
</a-card>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||||
|
<a-col>
|
||||||
|
<a-card hoverable>
|
||||||
|
<a-row :gutter="[0, isMobile ? 16 : 0]">
|
||||||
|
<a-col :sm="24" :md="12">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.cpu.color"
|
||||||
|
:percent="status.cpu.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.cpu" }}:</b> [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]]
|
||||||
|
<a-tooltip>
|
||||||
|
<a-icon type="area-chart"></a-icon>
|
||||||
|
<template slot="title">
|
||||||
|
<div><b>{{ i18n "pages.index.logicalProcessors" }}:</b> [[ (status.logicalPro) ]]</div>
|
||||||
|
<div><b>{{ i18n "pages.index.frequency" }}:</b> [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
||||||
|
</template>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.mem.color"
|
||||||
|
:percent="status.mem.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.memory"}}:</b> [[ SizeFormatter.sizeFormat(status.mem.current) ]] / [[ SizeFormatter.sizeFormat(status.mem.total) ]]
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-col>
|
||||||
|
<a-col :sm="24" :md="12">
|
||||||
|
<a-row>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.swap.color"
|
||||||
|
:percent="status.swap.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.swap" }}:</b> [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'center' }">
|
||||||
|
<a-progress type="dashboard" status="normal"
|
||||||
|
:stroke-color="status.disk.color"
|
||||||
|
:percent="status.disk.percent"></a-progress>
|
||||||
|
<div>
|
||||||
|
<b>{{ i18n "pages.index.storage"}}:</b> [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-row>
|
</a-col>
|
||||||
<a-row v-else>
|
<a-col :sm="24" :lg="12">
|
||||||
<a-row>
|
<a-card hoverable>
|
||||||
<a-card hoverable>
|
<template #title>
|
||||||
<a-row>
|
<a-space direction="horizontal">
|
||||||
<a-col :sm="24" :md="12">
|
<span>{{ i18n "pages.index.xrayStatus" }}</span>
|
||||||
<a-row>
|
<a-tag v-if="isMobile && status.xray.version != 'Unknown'" color="green">
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
v[[ status.xray.version ]]
|
||||||
<a-progress type="dashboard" status="normal"
|
</a-tag>
|
||||||
:stroke-color="status.cpu.color"
|
</a-space>
|
||||||
:percent="status.cpu.percent"></a-progress>
|
</template>
|
||||||
<div>
|
<template #extra>
|
||||||
<b>{{ i18n "pages.index.cpu" }}:</b> [[ CPUFormatter.cpuCoreFormat(status.cpuCores) ]]
|
<template v-if="status.xray.state != 'error'">
|
||||||
<a-tooltip>
|
<a-badge status="processing" class="running-animation" :text="status.xray.stateMsg" :color="status.xray.color"/>
|
||||||
<a-icon type="area-chart"></a-icon>
|
|
||||||
<template slot="title">
|
|
||||||
<div><b>{{ i18n "pages.index.logicalProcessors" }}:</b> [[ (status.logicalPro) ]]</div>
|
|
||||||
<div><b>{{ i18n "pages.index.frequency" }}:</b> [[ CPUFormatter.cpuSpeedFormat(status.cpuSpeedMhz) ]]</div>
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
|
||||||
<a-progress type="dashboard" status="normal"
|
|
||||||
:stroke-color="status.mem.color"
|
|
||||||
:percent="status.mem.percent"></a-progress>
|
|
||||||
<div>
|
|
||||||
<b>{{ i18n "pages.index.memory"}}:</b> [[ SizeFormatter.sizeFormat(status.mem.current) ]] / [[ SizeFormatter.sizeFormat(status.mem.total) ]]
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-col>
|
|
||||||
<a-col :sm="24" :md="12">
|
|
||||||
<a-row>
|
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
|
||||||
<a-progress type="dashboard" status="normal"
|
|
||||||
:stroke-color="status.swap.color"
|
|
||||||
:percent="status.swap.percent"></a-progress>
|
|
||||||
<div>
|
|
||||||
<b>{{ i18n "pages.index.swap" }}:</b> [[ SizeFormatter.sizeFormat(status.swap.current) ]] / [[ SizeFormatter.sizeFormat(status.swap.total) ]]
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
<a-col :span="12" :style="{ textAlign: 'center' }">
|
|
||||||
<a-progress type="dashboard" status="normal"
|
|
||||||
:stroke-color="status.disk.color"
|
|
||||||
:percent="status.disk.percent"></a-progress>
|
|
||||||
<div>
|
|
||||||
<b>{{ i18n "pages.index.storage"}}:</b> [[ SizeFormatter.sizeFormat(status.disk.current) ]] / [[ SizeFormatter.sizeFormat(status.disk.total) ]]
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-row>
|
|
||||||
<a-col :sm="24" :lg="12">
|
|
||||||
<a-card hoverable>
|
|
||||||
<template #title>
|
|
||||||
<a-space direction="horizontal">
|
|
||||||
<span>{{ i18n "pages.index.xrayStatus" }}</span>
|
|
||||||
<a-tag v-if="isMobile && status.xray.version != 'Unknown'" color="green">
|
|
||||||
v[[ status.xray.version ]]
|
|
||||||
</a-tag>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
</template>
|
||||||
<template #extra>
|
<template v-else>
|
||||||
<template v-if="status.xray.state != 'error'">
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
||||||
<a-badge status="processing" class="running-animation" :text="status.xray.stateMsg" :color="status.xray.color"/>
|
<span slot="title">
|
||||||
</template>
|
<a-row type="flex" align="middle" justify="space-between">
|
||||||
<template v-else>
|
<a-col>
|
||||||
<a-popover :overlay-class-name="themeSwitcher.currentTheme">
|
<span>{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
||||||
<span slot="title">
|
</a-col>
|
||||||
<a-row type="flex" align="middle" justify="space-between">
|
<a-col>
|
||||||
<a-col>
|
<a-icon type="bars" :style="{ cursor: 'pointer', float: 'right' }" @click="openLogs()"></a-tag>
|
||||||
<span>{{ i18n "pages.index.xrayErrorPopoverTitle" }}</span>
|
</a-col>
|
||||||
</a-col>
|
</a-row>
|
||||||
<a-col>
|
|
||||||
<a-icon type="bars" :style="{ cursor: 'pointer', float: 'right' }" @click="openLogs()"></a-tag>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</span>
|
|
||||||
<template slot="content">
|
|
||||||
<span :style="{ maxWidth: '400px' }" v-for="line in status.xray.errorMsg.split('\n')">[[ line ]]</span>
|
|
||||||
</template>
|
|
||||||
<a-badge :text="status.xray.stateMsg" :color="status.xray.color"/>
|
|
||||||
</a-popover>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
<template #actions>
|
|
||||||
<a-space direction="horizontal" @click="stopXrayService" :style="{ justifyContent: 'center' }">
|
|
||||||
<a-icon type="poweroff"></a-icon>
|
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.stopXray" }}</span>
|
|
||||||
</a-space>
|
|
||||||
<a-space direction="horizontal" @click="restartXrayService" :style="{ justifyContent: 'center' }">
|
|
||||||
<a-icon type="reload"></a-icon>
|
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.restartXray" }}</span>
|
|
||||||
</a-space>
|
|
||||||
<a-space direction="horizontal" @click="openSelectV2rayVersion" :style="{ justifyContent: 'center' }">
|
|
||||||
<a-icon type="tool"></a-icon>
|
|
||||||
<span v-if="!isMobile">
|
|
||||||
[[ status.xray.version != 'Unknown' ? `v${status.xray.version}` : '{{ i18n "pages.index.xraySwitch" }}' ]]
|
|
||||||
</span>
|
</span>
|
||||||
</a-space>
|
<template slot="content">
|
||||||
|
<span :style="{ maxWidth: '400px' }" v-for="line in status.xray.errorMsg.split('\n')">[[ line ]]</span>
|
||||||
|
</template>
|
||||||
|
<a-badge :text="status.xray.stateMsg" :color="status.xray.color"/>
|
||||||
|
</a-popover>
|
||||||
</template>
|
</template>
|
||||||
</a-card>
|
</template>
|
||||||
</a-col>
|
<template #actions>
|
||||||
<a-col :sm="24" :lg="12">
|
<a-space direction="horizontal" @click="stopXrayService" :style="{ justifyContent: 'center' }">
|
||||||
<a-card title='{{ i18n "menu.link" }}' hoverable>
|
<a-icon type="poweroff"></a-icon>
|
||||||
<template #actions>
|
<span v-if="!isMobile">{{ i18n "pages.index.stopXray" }}</span>
|
||||||
<a-space direction="horizontal" @click="openLogs()" :style="{ justifyContent: 'center' }">
|
</a-space>
|
||||||
<a-icon type="bars"></a-icon>
|
<a-space direction="horizontal" @click="restartXrayService" :style="{ justifyContent: 'center' }">
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.logs" }}</span>
|
<a-icon type="reload"></a-icon>
|
||||||
</a-space>
|
<span v-if="!isMobile">{{ i18n "pages.index.restartXray" }}</span>
|
||||||
<a-space direction="horizontal" @click="openConfig" :style="{ justifyContent: 'center' }">
|
</a-space>
|
||||||
<a-icon type="control"></a-icon>
|
<a-space direction="horizontal" @click="openSelectV2rayVersion" :style="{ justifyContent: 'center' }">
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.config" }}</span>
|
<a-icon type="tool"></a-icon>
|
||||||
</a-space>
|
<span v-if="!isMobile">
|
||||||
<a-space direction="horizontal" @click="openBackup" :style="{ justifyContent: 'center' }">
|
[[ status.xray.version != 'Unknown' ? `v${status.xray.version}` : '{{ i18n "pages.index.xraySwitch" }}' ]]
|
||||||
<a-icon type="cloud-server"></a-icon>
|
</span>
|
||||||
<span v-if="!isMobile">{{ i18n "pages.index.backup" }}</span>
|
</a-space>
|
||||||
</a-space>
|
</template>
|
||||||
</template>
|
</a-card>
|
||||||
</a-card>
|
</a-col>
|
||||||
</a-col>
|
<a-col :sm="24" :lg="12">
|
||||||
<a-col :sm="24" :lg="12">
|
<a-card title='{{ i18n "menu.link" }}' hoverable>
|
||||||
<a-card title='3X-UI' hoverable>
|
<template #actions>
|
||||||
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/releases" target="_blank"><a-tag color="green">v{{ .cur_ver }}</a-tag></a>
|
<a-space direction="horizontal" @click="openLogs()" :style="{ justifyContent: 'center' }">
|
||||||
<a rel="noopener" href="https://t.me/XrayUI" target="_blank"><a-tag color="green">@XrayUI</a-tag></a>
|
<a-icon type="bars"></a-icon>
|
||||||
</a-card>
|
<span v-if="!isMobile">{{ i18n "pages.index.logs" }}</span>
|
||||||
</a-col>
|
</a-space>
|
||||||
<a-col :sm="24" :lg="12">
|
<a-space direction="horizontal" @click="openConfig" :style="{ justifyContent: 'center' }">
|
||||||
<a-card title='{{ i18n "pages.index.operationHours" }}' hoverable>
|
<a-icon type="control"></a-icon>
|
||||||
<a-tag :color="status.xray.color">Xray: [[ TimeFormatter.formatSecond(status.appStats.uptime) ]]</a-tag>
|
<span v-if="!isMobile">{{ i18n "pages.index.config" }}</span>
|
||||||
<a-tag color="green">OS: [[ TimeFormatter.formatSecond(status.uptime) ]]</a-tag>
|
</a-space>
|
||||||
</a-card>
|
<a-space direction="horizontal" @click="openBackup" :style="{ justifyContent: 'center' }">
|
||||||
</a-col>
|
<a-icon type="cloud-server"></a-icon>
|
||||||
<a-col :sm="24" :lg="12">
|
<span v-if="!isMobile">{{ i18n "pages.index.backup" }}</span>
|
||||||
<a-card title='{{ i18n "pages.index.systemLoad" }}' hoverable>
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col :sm="24" :lg="12">
|
||||||
|
<a-card title='3X-UI' hoverable>
|
||||||
|
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/releases" target="_blank">
|
||||||
<a-tag color="green">
|
<a-tag color="green">
|
||||||
<a-tooltip>
|
<span>v{{ .cur_ver }}</span>
|
||||||
[[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
|
|
||||||
<template slot="title">
|
|
||||||
{{ i18n "pages.index.systemLoadDesc" }}
|
|
||||||
</template>
|
|
||||||
</a-tooltip>
|
|
||||||
</a-tag>
|
</a-tag>
|
||||||
</a-card>
|
</a>
|
||||||
</a-col>
|
<a rel="noopener" href="https://t.me/XrayUI" target="_blank">
|
||||||
<a-col :sm="24" :lg="12">
|
<a-tag color="green">
|
||||||
<a-card title='{{ i18n "usage"}}' hoverable>
|
<span>@XrayUI</span>
|
||||||
<a-tag color="green"> {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
|
</a-tag>
|
||||||
<a-tag color="green"> {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]] </a-tag>
|
</a>
|
||||||
</a-card>
|
<a rel="noopener" href="https://github.com/MHSanaei/3x-ui/wiki" target="_blank">
|
||||||
</a-col>
|
<a-tag color="purple">
|
||||||
<a-col :sm="24" :lg="12">
|
<span>{{ i18n "pages.index.documentation" }}</span>
|
||||||
<a-card title='{{ i18n "pages.index.overallSpeed" }}' hoverable>
|
</a-tag>
|
||||||
<a-row :gutter="isMobile ? [8,8] : 0">
|
</a>
|
||||||
<a-col :span="12">
|
</a-card>
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.upload" }}' :value="SizeFormatter.sizeFormat(status.netIO.up)">
|
</a-col>
|
||||||
<template #prefix>
|
<a-col :sm="24" :lg="12">
|
||||||
<a-icon type="arrow-up" />
|
<a-card title='{{ i18n "pages.index.operationHours" }}' hoverable>
|
||||||
</template>
|
<a-tag :color="status.xray.color">Xray: [[ TimeFormatter.formatSecond(status.appStats.uptime) ]]</a-tag>
|
||||||
<template #suffix>
|
<a-tag color="green">OS: [[ TimeFormatter.formatSecond(status.uptime) ]]</a-tag>
|
||||||
/s
|
</a-card>
|
||||||
</template>
|
</a-col>
|
||||||
</a-custom-statistic>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-col>
|
<a-card title='{{ i18n "pages.index.systemLoad" }}' hoverable>
|
||||||
<a-col :span="12">
|
<a-tag color="green">
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.download" }}' :value="SizeFormatter.sizeFormat(status.netIO.down)">
|
<a-tooltip>
|
||||||
<template #prefix>
|
[[ status.loads[0] ]] | [[ status.loads[1] ]] | [[ status.loads[2] ]]
|
||||||
<a-icon type="arrow-down" />
|
<template slot="title">
|
||||||
</template>
|
{{ i18n "pages.index.systemLoadDesc" }}
|
||||||
<template #suffix>
|
</template>
|
||||||
/s
|
</a-tooltip>
|
||||||
</template>
|
</a-tag>
|
||||||
</a-custom-statistic>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-card>
|
<a-card title='{{ i18n "usage"}}' hoverable>
|
||||||
</a-col>
|
<a-tag color="green"> {{ i18n "pages.index.memory" }}: [[ SizeFormatter.sizeFormat(status.appStats.mem) ]] </a-tag>
|
||||||
<a-col :sm="24" :lg="12">
|
<a-tag color="green"> {{ i18n "pages.index.threads" }}: [[ status.appStats.threads ]] </a-tag>
|
||||||
<a-card title='{{ i18n "pages.index.totalData" }}' hoverable>
|
</a-card>
|
||||||
<a-row :gutter="isMobile ? [8,8] : 0">
|
</a-col>
|
||||||
<a-col :span="12">
|
<a-col :sm="24" :lg="12">
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.sent" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.sent)">
|
<a-card title='{{ i18n "pages.index.overallSpeed" }}' hoverable>
|
||||||
<template #prefix>
|
<a-row :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-icon type="cloud-upload" />
|
<a-col :span="12">
|
||||||
</template>
|
<a-custom-statistic title='{{ i18n "pages.index.upload" }}' :value="SizeFormatter.sizeFormat(status.netIO.up)">
|
||||||
</a-custom-statistic>
|
<template #prefix>
|
||||||
</a-col>
|
<a-icon type="arrow-up" />
|
||||||
<a-col :span="12">
|
|
||||||
<a-custom-statistic title='{{ i18n "pages.index.received" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.recv)">
|
|
||||||
<template #prefix>
|
|
||||||
<a-icon type="cloud-download" />
|
|
||||||
</template>
|
|
||||||
</a-custom-statistic>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-card>
|
|
||||||
</a-col>
|
|
||||||
<a-col :sm="24" :lg="12">
|
|
||||||
<a-card title='{{ i18n "pages.index.ipAddresses" }}' hoverable>
|
|
||||||
<template #extra>
|
|
||||||
<a-tooltip>
|
|
||||||
<template #title>
|
|
||||||
{{ i18n "pages.index.toggleIpVisibility" }}
|
|
||||||
</template>
|
</template>
|
||||||
<a-icon :type="showIp ? 'eye' : 'eye-invisible'" :style="{ fontSize: '1rem' }" @click="showIp = !showIp"></a-icon>
|
<template #suffix>
|
||||||
</a-tooltip>
|
/s
|
||||||
</template>
|
</template>
|
||||||
<a-row :class="showIp ? 'ip-visible' : 'ip-hidden'" :gutter="isMobile ? [8,8] : 0">
|
</a-custom-statistic>
|
||||||
<a-col :span="isMobile ? 24 : 12">
|
</a-col>
|
||||||
<a-custom-statistic title="IPv4" :value="status.publicIP.ipv4">
|
<a-col :span="12">
|
||||||
<template #prefix>
|
<a-custom-statistic title='{{ i18n "pages.index.download" }}' :value="SizeFormatter.sizeFormat(status.netIO.down)">
|
||||||
<a-icon type="global" />
|
<template #prefix>
|
||||||
</template>
|
<a-icon type="arrow-down" />
|
||||||
</a-custom-statistic>
|
</template>
|
||||||
</a-col>
|
<template #suffix>
|
||||||
<a-col :span="isMobile ? 24 : 12">
|
/s
|
||||||
<a-custom-statistic title="IPv6" :value="status.publicIP.ipv6">
|
</template>
|
||||||
<template #prefix>
|
</a-custom-statistic>
|
||||||
<a-icon type="global" />
|
</a-col>
|
||||||
</template>
|
</a-row>
|
||||||
</a-custom-statistic>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-card>
|
<a-card title='{{ i18n "pages.index.totalData" }}' hoverable>
|
||||||
</a-col>
|
<a-row :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-col :sm="24" :lg="12">
|
<a-col :span="12">
|
||||||
<a-card title='{{ i18n "pages.index.connectionCount" }}' hoverable>
|
<a-custom-statistic title='{{ i18n "pages.index.sent" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.sent)">
|
||||||
<a-row :gutter="isMobile ? [8,8] : 0">
|
<template #prefix>
|
||||||
<a-col :span="12">
|
<a-icon type="cloud-upload" />
|
||||||
<a-custom-statistic title="TCP" :value="status.tcpCount">
|
</template>
|
||||||
<template #prefix>
|
</a-custom-statistic>
|
||||||
<a-icon type="swap" />
|
</a-col>
|
||||||
</template>
|
<a-col :span="12">
|
||||||
</a-custom-statistic>
|
<a-custom-statistic title='{{ i18n "pages.index.received" }}' :value="SizeFormatter.sizeFormat(status.netTraffic.recv)">
|
||||||
</a-col>
|
<template #prefix>
|
||||||
<a-col :span="12">
|
<a-icon type="cloud-download" />
|
||||||
<a-custom-statistic title="UDP" :value="status.udpCount">
|
</template>
|
||||||
<template #prefix>
|
</a-custom-statistic>
|
||||||
<a-icon type="swap" />
|
</a-col>
|
||||||
</template>
|
</a-row>
|
||||||
</a-custom-statistic>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-card>
|
<a-card title='{{ i18n "pages.index.ipAddresses" }}' hoverable>
|
||||||
</a-col>
|
<template #extra>
|
||||||
</a-row>
|
<a-tooltip :placement="isMobile ? 'topRight' : 'top'">
|
||||||
</template>
|
<template #title>
|
||||||
</transition>
|
{{ i18n "pages.index.toggleIpVisibility" }}
|
||||||
</a-spin>
|
</template>
|
||||||
</a-layout-content>
|
<a-icon :type="showIp ? 'eye' : 'eye-invisible'" :style="{ fontSize: '1rem' }" @click="showIp = !showIp"></a-icon>
|
||||||
</a-layout>
|
</a-tooltip>
|
||||||
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
|
</template>
|
||||||
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
|
<a-row :class="showIp ? 'ip-visible' : 'ip-hidden'" :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-collapse default-active-key="1">
|
<a-col :span="isMobile ? 24 : 12">
|
||||||
<a-collapse-panel key="1" header='Xray'>
|
<a-custom-statistic title="IPv4" :value="status.publicIP.ipv4">
|
||||||
<a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }" message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
<template #prefix>
|
||||||
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
<a-icon type="global" />
|
||||||
<a-list-item class="ant-version-list-item" v-for="version, index in versionModal.versions">
|
</template>
|
||||||
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ version ]]</a-tag>
|
</a-custom-statistic>
|
||||||
<a-radio :class="themeSwitcher.currentTheme" :checked="version === `v${status.xray.version}`" @click="switchV2rayVersion(version)"></a-radio>
|
</a-col>
|
||||||
</a-list-item>
|
<a-col :span="isMobile ? 24 : 12">
|
||||||
</a-list>
|
<a-custom-statistic title="IPv6" :value="status.publicIP.ipv6">
|
||||||
</a-collapse-panel>
|
<template #prefix>
|
||||||
<a-collapse-panel key="2" header='Geofiles'>
|
<a-icon type="global" />
|
||||||
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
</template>
|
||||||
<a-list-item class="ant-version-list-item" v-for="file, index in ['geosite.dat', 'geoip.dat', 'geosite_IR.dat', 'geoip_IR.dat', 'geosite_RU.dat', 'geoip_RU.dat']">
|
</a-custom-statistic>
|
||||||
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ file ]]</a-tag>
|
</a-col>
|
||||||
<a-icon type="reload" @click="updateGeofile(file)" :style="{ marginRight: '8px' }"/>
|
</a-row>
|
||||||
</a-list-item>
|
</a-card>
|
||||||
</a-list>
|
</a-col>
|
||||||
</a-collapse-panel>
|
<a-col :sm="24" :lg="12">
|
||||||
</a-collapse>
|
<a-card title='{{ i18n "pages.index.connectionCount" }}' hoverable>
|
||||||
</a-modal>
|
<a-row :gutter="isMobile ? [8,8] : 0">
|
||||||
<a-modal id="log-modal" v-model="logModal.visible"
|
<a-col :span="12">
|
||||||
:closable="true" @cancel="() => logModal.visible = false"
|
<a-custom-statistic title="TCP" :value="status.tcpCount">
|
||||||
:class="themeSwitcher.currentTheme"
|
<template #prefix>
|
||||||
width="800px" footer="">
|
<a-icon type="swap" />
|
||||||
<template slot="title">
|
</template>
|
||||||
{{ i18n "pages.index.logs" }}
|
</a-custom-statistic>
|
||||||
<a-icon :spin="logModal.loading"
|
</a-col>
|
||||||
type="sync"
|
<a-col :span="12">
|
||||||
:style="{ verticalAlign: 'middle', marginLeft: '10px' }"
|
<a-custom-statistic title="UDP" :value="status.udpCount">
|
||||||
:disabled="logModal.loading"
|
<template #prefix>
|
||||||
@click="openLogs()">
|
<a-icon type="swap" />
|
||||||
</a-icon>
|
</template>
|
||||||
</template>
|
</a-custom-statistic>
|
||||||
<a-form layout="inline">
|
</a-col>
|
||||||
<a-form-item :style="{ marginRight: '0.5rem' }">
|
</a-row>
|
||||||
<a-input-group compact>
|
</a-card>
|
||||||
<a-select size="small" v-model="logModal.rows" :style="{ width: '70px' }"
|
</a-col>
|
||||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
</a-row>
|
||||||
<a-select-option value="10">10</a-select-option>
|
</template>
|
||||||
<a-select-option value="20">20</a-select-option>
|
</transition>
|
||||||
<a-select-option value="50">50</a-select-option>
|
</a-spin>
|
||||||
<a-select-option value="100">100</a-select-option>
|
</a-layout-content>
|
||||||
<a-select-option value="500">500</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
<a-select size="small" v-model="logModal.level" :style="{ width: '95px' }"
|
|
||||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option value="debug">Debug</a-select-option>
|
|
||||||
<a-select-option value="info">Info</a-select-option>
|
|
||||||
<a-select-option value="notice">Notice</a-select-option>
|
|
||||||
<a-select-option value="warning">Warning</a-select-option>
|
|
||||||
<a-select-option value="err">Error</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-input-group>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item>
|
|
||||||
<a-checkbox v-model="logModal.syslog" @change="openLogs()">SysLog</a-checkbox>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item :style="{ float: 'right' }">
|
|
||||||
<a-button type="primary" icon="download" @click="FileManager.downloadTextFile(logModal.logs?.join('\n'), 'x-ui.log')"></a-button>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
<div class="ant-input" :style="{ height: 'auto', maxHeight: '500px', overflow: 'auto', marginTop: '0.5rem' }" v-html="logModal.formattedLogs"></div>
|
|
||||||
</a-modal>
|
|
||||||
<a-modal id="backup-modal"
|
|
||||||
v-model="backupModal.visible"
|
|
||||||
title='{{ i18n "pages.index.backupTitle" }}'
|
|
||||||
:closable="true"
|
|
||||||
footer=""
|
|
||||||
:class="themeSwitcher.currentTheme">
|
|
||||||
<a-list class="ant-backup-list" bordered :style="{ width: '100%' }">
|
|
||||||
<a-list-item class="ant-backup-list-item">
|
|
||||||
<a-list-item-meta>
|
|
||||||
<template #title>{{ i18n "pages.index.exportDatabase" }}</template>
|
|
||||||
<template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template>
|
|
||||||
</a-list-item-meta>
|
|
||||||
<a-button @click="exportDatabase()" type="primary" icon="download"/>
|
|
||||||
</a-list-item>
|
|
||||||
<a-list-item class="ant-backup-list-item">
|
|
||||||
<a-list-item-meta>
|
|
||||||
<template #title>{{ i18n "pages.index.importDatabase" }}</template>
|
|
||||||
<template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template>
|
|
||||||
</a-list-item-meta>
|
|
||||||
<a-button @click="importDatabase()" type="primary" icon="upload" />
|
|
||||||
</a-list-item>
|
|
||||||
</a-list>
|
|
||||||
</a-modal>
|
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
|
||||||
|
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
|
||||||
|
<a-collapse default-active-key="1">
|
||||||
|
<a-collapse-panel key="1" header='Xray'>
|
||||||
|
<a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }" message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
||||||
|
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-version-list-item" v-for="version, index in versionModal.versions">
|
||||||
|
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ version ]]</a-tag>
|
||||||
|
<a-radio :class="themeSwitcher.currentTheme" :checked="version === `v${status.xray.version}`" @click="switchV2rayVersion(version)"></a-radio>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
<a-collapse-panel key="2" header='Geofiles'>
|
||||||
|
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-version-list-item" v-for="file, index in ['geosite.dat', 'geoip.dat', 'geosite_IR.dat', 'geoip_IR.dat', 'geosite_RU.dat', 'geoip_RU.dat']">
|
||||||
|
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ file ]]</a-tag>
|
||||||
|
<a-icon type="reload" @click="updateGeofile(file)" :style="{ marginRight: '8px' }"/>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
</a-collapse>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal id="log-modal" v-model="logModal.visible"
|
||||||
|
:closable="true" @cancel="() => logModal.visible = false"
|
||||||
|
:class="themeSwitcher.currentTheme"
|
||||||
|
width="800px" footer="">
|
||||||
|
<template slot="title">
|
||||||
|
{{ i18n "pages.index.logs" }}
|
||||||
|
<a-icon :spin="logModal.loading"
|
||||||
|
type="sync"
|
||||||
|
:style="{ verticalAlign: 'middle', marginLeft: '10px' }"
|
||||||
|
:disabled="logModal.loading"
|
||||||
|
@click="openLogs()">
|
||||||
|
</a-icon>
|
||||||
|
</template>
|
||||||
|
<a-form layout="inline">
|
||||||
|
<a-form-item :style="{ marginRight: '0.5rem' }">
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-select size="small" v-model="logModal.rows" :style="{ width: '70px' }"
|
||||||
|
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="10">10</a-select-option>
|
||||||
|
<a-select-option value="20">20</a-select-option>
|
||||||
|
<a-select-option value="50">50</a-select-option>
|
||||||
|
<a-select-option value="100">100</a-select-option>
|
||||||
|
<a-select-option value="500">500</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-select size="small" v-model="logModal.level" :style="{ width: '95px' }"
|
||||||
|
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option value="debug">Debug</a-select-option>
|
||||||
|
<a-select-option value="info">Info</a-select-option>
|
||||||
|
<a-select-option value="notice">Notice</a-select-option>
|
||||||
|
<a-select-option value="warning">Warning</a-select-option>
|
||||||
|
<a-select-option value="err">Error</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-checkbox v-model="logModal.syslog" @change="openLogs()">SysLog</a-checkbox>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :style="{ float: 'right' }">
|
||||||
|
<a-button type="primary" icon="download" @click="FileManager.downloadTextFile(logModal.logs?.join('\n'), 'x-ui.log')"></a-button>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
<div class="ant-input" :style="{ height: 'auto', maxHeight: '500px', overflow: 'auto', marginTop: '0.5rem' }" v-html="logModal.formattedLogs"></div>
|
||||||
|
</a-modal>
|
||||||
|
<a-modal id="backup-modal"
|
||||||
|
v-model="backupModal.visible"
|
||||||
|
title='{{ i18n "pages.index.backupTitle" }}'
|
||||||
|
:closable="true"
|
||||||
|
footer=""
|
||||||
|
:class="themeSwitcher.currentTheme">
|
||||||
|
<a-list class="ant-backup-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-backup-list-item">
|
||||||
|
<a-list-item-meta>
|
||||||
|
<template #title>{{ i18n "pages.index.exportDatabase" }}</template>
|
||||||
|
<template #description>{{ i18n "pages.index.exportDatabaseDesc" }}</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
<a-button @click="exportDatabase()" type="primary" icon="download"/>
|
||||||
|
</a-list-item>
|
||||||
|
<a-list-item class="ant-backup-list-item">
|
||||||
|
<a-list-item-meta>
|
||||||
|
<template #title>{{ i18n "pages.index.importDatabase" }}</template>
|
||||||
|
<template #description>{{ i18n "pages.index.importDatabaseDesc" }}</template>
|
||||||
|
</a-list-item-meta>
|
||||||
|
<a-button @click="importDatabase()" type="primary" icon="upload" />
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-modal>
|
||||||
|
</a-layout>
|
||||||
|
{{template "page/body_scripts" .}}
|
||||||
{{template "component/aSidebar" .}}
|
{{template "component/aSidebar" .}}
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
{{template "component/aCustomStatistic" .}}
|
{{template "component/aCustomStatistic" .}}
|
||||||
|
@ -476,7 +479,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
class Status {
|
class Status {
|
||||||
constructor(data, isLoaded = false) {
|
constructor(data) {
|
||||||
this.cpu = new CurTotal(0, 0);
|
this.cpu = new CurTotal(0, 0);
|
||||||
this.cpuCores = 0;
|
this.cpuCores = 0;
|
||||||
this.logicalPro = 0;
|
this.logicalPro = 0;
|
||||||
|
@ -500,7 +503,6 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isLoaded = isLoaded;
|
|
||||||
this.cpu = new CurTotal(data.cpu, 100);
|
this.cpu = new CurTotal(data.cpu, 100);
|
||||||
this.cpuCores = data.cpuCores;
|
this.cpuCores = data.cpuCores;
|
||||||
this.logicalPro = data.logicalPro;
|
this.logicalPro = data.logicalPro;
|
||||||
|
@ -620,32 +622,39 @@
|
||||||
mixins: [MediaQueryMixin],
|
mixins: [MediaQueryMixin],
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
|
loadingStates: {
|
||||||
|
fetched: false,
|
||||||
|
spinning: false
|
||||||
|
},
|
||||||
status: new Status(),
|
status: new Status(),
|
||||||
versionModal,
|
versionModal,
|
||||||
logModal,
|
logModal,
|
||||||
backupModal,
|
backupModal,
|
||||||
spinning: false,
|
|
||||||
loadingTip: '{{ i18n "loading"}}',
|
loadingTip: '{{ i18n "loading"}}',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
showIp: false
|
showIp: false
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning, tip = '{{ i18n "loading"}}') {
|
loading(spinning, tip = '{{ i18n "loading"}}') {
|
||||||
this.spinning = spinning;
|
this.loadingStates.spinning = spinning;
|
||||||
this.loadingTip = tip;
|
this.loadingTip = tip;
|
||||||
},
|
},
|
||||||
async getStatus() {
|
async getStatus() {
|
||||||
try {
|
try {
|
||||||
const msg = await HttpUtil.post('/server/status');
|
const msg = await HttpUtil.post('/server/status');
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
if (!this.loadingStates.fetched) {
|
||||||
|
this.loadingStates.fetched = true;
|
||||||
|
}
|
||||||
|
|
||||||
this.setStatus(msg.obj, true);
|
this.setStatus(msg.obj, true);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to get status:", e);
|
console.error("Failed to get status:", e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setStatus(data, isLoaded = false) {
|
setStatus(data) {
|
||||||
this.status = new Status(data, isLoaded);
|
this.status = new Status(data);
|
||||||
},
|
},
|
||||||
async openSelectV2rayVersion() {
|
async openSelectV2rayVersion() {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
|
@ -775,5 +784,4 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
{{ template "page/body_end" .}}
|
||||||
</html>
|
|
|
@ -1,6 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
html * {
|
html * {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
@ -299,6 +297,12 @@
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.title {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.words-wrapper {
|
.words-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -447,174 +451,174 @@
|
||||||
margin: 2px 0 4px;
|
margin: 2px 0 4px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
{{ template "page/head_end" .}}
|
||||||
|
|
||||||
<body>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<transition name="list" appear>
|
<transition name="list" appear>
|
||||||
<a-layout-content class="under" :style="{ minHeight: '0' }">
|
<a-layout-content class="under" :style="{ minHeight: '0' }">
|
||||||
<div class="waves-header">
|
<div class="waves-header">
|
||||||
<div class="waves-inner-header"></div>
|
<div class="waves-inner-header"></div>
|
||||||
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
<svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
|
viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto">
|
||||||
<defs>
|
<defs>
|
||||||
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
|
<path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z" />
|
||||||
</defs>
|
</defs>
|
||||||
<g class="parallax">
|
<g class="parallax">
|
||||||
<use xlink:href="#gentle-wave" x="48" y="0" fill="rgba(0, 135, 113, 0.08)" />
|
<use xlink:href="#gentle-wave" x="48" y="0" fill="rgba(0, 135, 113, 0.08)" />
|
||||||
<use xlink:href="#gentle-wave" x="48" y="3" fill="rgba(0, 135, 113, 0.08)" />
|
<use xlink:href="#gentle-wave" x="48" y="3" fill="rgba(0, 135, 113, 0.08)" />
|
||||||
<use xlink:href="#gentle-wave" x="48" y="5" fill="rgba(0, 135, 113, 0.08)" />
|
<use xlink:href="#gentle-wave" x="48" y="5" fill="rgba(0, 135, 113, 0.08)" />
|
||||||
<use xlink:href="#gentle-wave" x="48" y="7" fill="#c7ebe2" />
|
<use xlink:href="#gentle-wave" x="48" y="7" fill="#c7ebe2" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<a-row type="flex" justify="center" align="middle" :style="{ height: '100%', overflow: 'auto', overflowX: 'hidden' }">
|
<a-row type="flex" justify="center" align="middle" :style="{ height: '100%', overflow: 'auto', overflowX: 'hidden' }">
|
||||||
<a-col :xs="22" :sm="12" :md="10" :lg="8" :xl="6" :xxl="5" id="login" :style="{ margin: '3rem 0' }">
|
<a-col :xs="22" :sm="12" :md="10" :lg="8" :xl="6" :xxl="5" id="login" :style="{ margin: '3rem 0' }">
|
||||||
<div class="setting-section">
|
<div class="setting-section">
|
||||||
<a-popover :overlay-class-name="themeSwitcher.currentTheme" title='{{ i18n "menu.settings" }}' placement="bottomRight" trigger="click">
|
<a-popover :overlay-class-name="themeSwitcher.currentTheme" title='{{ i18n "menu.settings" }}' placement="bottomRight" trigger="click">
|
||||||
<template slot="content">
|
<template slot="content">
|
||||||
<a-space direction="vertical" :size="10">
|
<a-space direction="vertical" :size="10">
|
||||||
<a-theme-switch-login></a-theme-switch-login>
|
<a-theme-switch-login></a-theme-switch-login>
|
||||||
<span>{{ i18n "pages.settings.language" }}</span>
|
<span>{{ i18n "pages.settings.language" }}</span>
|
||||||
<a-select ref="selectLang" :style="{ width: '100%' }" v-model="lang" @change="LanguageManager.setLanguage(lang)" :dropdown-class-name="themeSwitcher.currentTheme">
|
<a-select ref="selectLang" :style="{ width: '100%' }" v-model="lang" @change="LanguageManager.setLanguage(lang)" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option :value="l.value" label="English" v-for="l in LanguageManager.supportedLanguages">
|
<a-select-option :value="l.value" label="English" v-for="l in LanguageManager.supportedLanguages">
|
||||||
<span role="img" aria-label="l.name" v-text="l.icon"></span>
|
<span role="img" aria-label="l.name" v-text="l.icon"></span>
|
||||||
<span v-text="l.name"></span>
|
<span v-text="l.name"></span>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
<a-button shape="circle" icon="setting"></a-button>
|
<a-button shape="circle" icon="setting"></a-button>
|
||||||
</a-popover>
|
</a-popover>
|
||||||
</div>
|
</div>
|
||||||
<a-row type="flex" justify="center">
|
<a-row type="flex" justify="center">
|
||||||
<a-col :style="{ width: '100%' }">
|
<a-col :style="{ width: '100%' }">
|
||||||
<h2 class="title headline zoom">
|
<h2 class="title headline zoom">
|
||||||
<span class="words-wrapper">
|
<span class="words-wrapper">
|
||||||
<b class="is-visible">{{ i18n "pages.login.hello" }}</b>
|
<b class="is-visible">{{ i18n "pages.login.hello" }}</b>
|
||||||
<b>{{ i18n "pages.login.title" }}</b>
|
<b>{{ i18n "pages.login.title" }}</b>
|
||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row type="flex" justify="center">
|
<a-row type="flex" justify="center">
|
||||||
<a-col span="24">
|
<a-col span="24">
|
||||||
<a-form>
|
<a-form>
|
||||||
<a-space direction="vertical" size="middle">
|
<a-space direction="vertical" size="middle">
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-input autocomplete="username" name="username" v-model.trim="user.username"
|
<a-input autocomplete="username" name="username" v-model.trim="user.username"
|
||||||
placeholder='{{ i18n "username" }}' @keydown.enter.native="login" autofocus>
|
placeholder='{{ i18n "username" }}' @keydown.enter.native="login" autofocus>
|
||||||
<a-icon slot="prefix" type="user" :style="{ fontSize: '1rem' }"></a-icon>
|
<a-icon slot="prefix" type="user" :style="{ fontSize: '1rem' }"></a-icon>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-input-password autocomplete="password" name="password" v-model.trim="user.password"
|
<a-input-password autocomplete="password" name="password" v-model.trim="user.password"
|
||||||
placeholder='{{ i18n "password" }}' @keydown.enter.native="login">
|
placeholder='{{ i18n "password" }}' @keydown.enter.native="login">
|
||||||
<a-icon slot="prefix" type="lock" :style="{ fontSize: '1rem' }"></a-icon>
|
<a-icon slot="prefix" type="lock" :style="{ fontSize: '1rem' }"></a-icon>
|
||||||
</a-input-password>
|
</a-input-password>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item v-if="twoFactorEnable">
|
<a-form-item v-if="twoFactorEnable">
|
||||||
<a-input autocomplete="totp" name="twoFactorCode" v-model.trim="user.twoFactorCode"
|
<a-input autocomplete="totp" name="twoFactorCode" v-model.trim="user.twoFactorCode"
|
||||||
placeholder='{{ i18n "twoFactorCode" }}' @keydown.enter.native="login">
|
placeholder='{{ i18n "twoFactorCode" }}' @keydown.enter.native="login">
|
||||||
<a-icon slot="prefix" type="key" :style="{ fontSize: '1rem' }"></a-icon>
|
<a-icon slot="prefix" type="key" :style="{ fontSize: '1rem' }"></a-icon>
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item>
|
<a-form-item>
|
||||||
<a-row justify="center" class="centered">
|
<a-row justify="center" class="centered">
|
||||||
<div :style="{ height: '50px', marginTop: '1rem', ...loading ? { width: '52px' } : { display: 'inline-block' } }" class="wave-btn-bg wave-btn-bg-cl">
|
<div :style="{ height: '50px', marginTop: '1rem', ...loading ? { width: '52px' } : { display: 'inline-block' } }" class="wave-btn-bg wave-btn-bg-cl">
|
||||||
<a-button class="ant-btn-primary-login" type="primary" :loading="loading" @click="login"
|
<a-button class="ant-btn-primary-login" type="primary" :loading="loading" @click="login"
|
||||||
:icon="loading ? 'poweroff' : undefined">
|
:icon="loading ? 'poweroff' : undefined">
|
||||||
[[ loading ? '' : '{{ i18n "login" }}' ]]
|
[[ loading ? '' : '{{ i18n "login" }}' ]]
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-space>
|
</a-space>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</a-layout-content>
|
</a-layout-content>
|
||||||
</transition>
|
</transition>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
{{template "page/body_scripts" .}}
|
||||||
{{template "component/aThemeSwitch" .}}
|
{{template "component/aThemeSwitch" .}}
|
||||||
<script>
|
<script>
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
loading: false,
|
loading: false,
|
||||||
user: {
|
user: {
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
twoFactorCode: ""
|
twoFactorCode: ""
|
||||||
},
|
|
||||||
twoFactorEnable: false,
|
|
||||||
lang: ""
|
|
||||||
},
|
},
|
||||||
async mounted() {
|
twoFactorEnable: false,
|
||||||
this.lang = LanguageManager.getLanguage();
|
lang: ""
|
||||||
this.twoFactorEnable = await this.getTwoFactorEnable();
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.lang = LanguageManager.getLanguage();
|
||||||
|
this.twoFactorEnable = await this.getTwoFactorEnable();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async login() {
|
||||||
|
this.loading = true;
|
||||||
|
const msg = await HttpUtil.post('/login', this.user);
|
||||||
|
this.loading = false;
|
||||||
|
if (msg.success) {
|
||||||
|
location.href = basePath + 'panel/';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
async getTwoFactorEnable() {
|
||||||
async login() {
|
this.loading = true;
|
||||||
this.loading = true;
|
const msg = await HttpUtil.post('/getTwoFactorEnable');
|
||||||
const msg = await HttpUtil.post('/login', this.user);
|
this.loading = false;
|
||||||
this.loading = false;
|
if (msg.success) {
|
||||||
if (msg.success) {
|
this.twoFactorEnable = msg.obj;
|
||||||
location.href = basePath + 'panel/';
|
return msg.obj;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
async getTwoFactorEnable() {
|
|
||||||
this.loading = true;
|
|
||||||
const msg = await HttpUtil.post('/getTwoFactorEnable');
|
|
||||||
this.loading = false;
|
|
||||||
if (msg.success) {
|
|
||||||
this.twoFactorEnable = msg.obj;
|
|
||||||
return msg.obj;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
var animationDelay = 2000;
|
var animationDelay = 2000;
|
||||||
initHeadline();
|
initHeadline();
|
||||||
|
|
||||||
function initHeadline() {
|
function initHeadline() {
|
||||||
animateHeadline(document.querySelectorAll('.headline'));
|
animateHeadline(document.querySelectorAll('.headline'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function animateHeadline(headlines) {
|
function animateHeadline(headlines) {
|
||||||
var duration = animationDelay;
|
var duration = animationDelay;
|
||||||
headlines.forEach(function (headline) {
|
headlines.forEach(function (headline) {
|
||||||
setTimeout(function () {
|
|
||||||
hideWord(headline.querySelector('.is-visible'));
|
|
||||||
}, duration);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideWord(word) {
|
|
||||||
var nextWord = takeNext(word);
|
|
||||||
switchWord(word, nextWord);
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
hideWord(nextWord);
|
hideWord(headline.querySelector('.is-visible'));
|
||||||
}, animationDelay);
|
}, duration);
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function takeNext(word) {
|
function hideWord(word) {
|
||||||
return word.nextElementSibling ? word.nextElementSibling : word.parentElement.firstElementChild;
|
var nextWord = takeNext(word);
|
||||||
}
|
switchWord(word, nextWord);
|
||||||
|
setTimeout(function () {
|
||||||
|
hideWord(nextWord);
|
||||||
|
}, animationDelay);
|
||||||
|
}
|
||||||
|
|
||||||
function switchWord(oldWord, newWord) {
|
function takeNext(word) {
|
||||||
oldWord.classList.remove('is-visible');
|
return word.nextElementSibling ? word.nextElementSibling : word.parentElement.firstElementChild;
|
||||||
oldWord.classList.add('is-hidden');
|
}
|
||||||
newWord.classList.remove('is-hidden');
|
|
||||||
newWord.classList.add('is-visible');
|
function switchWord(oldWord, newWord) {
|
||||||
}
|
oldWord.classList.remove('is-visible');
|
||||||
});
|
oldWord.classList.add('is-hidden');
|
||||||
</script>
|
newWord.classList.remove('is-hidden');
|
||||||
</body>
|
newWord.classList.add('is-visible');
|
||||||
</html>
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{ template "page/body_end" .}}
|
110
web/html/modals/dns_presets_modal.html
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
{{define "modals/dnsPresetsModal"}}
|
||||||
|
<a-modal id="dnsPresets-modal" v-model="dnsPresetsModal.visible" :title="dnsPresetsModal.title" :closable="true"
|
||||||
|
:mask-closable="false" :footer="null" :class="themeSwitcher.currentTheme">
|
||||||
|
<a-list class="ant-dns-presets-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item v-for="dns in dnsPresetsDatabase" :style="{ padding: '12px 16px' }">
|
||||||
|
<a-row justify="space-between" align="middle">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-space direction="vertical" size="small">
|
||||||
|
<span class="ant-dns-presets-list-name">[[ dns.name ]]</span>
|
||||||
|
<a-tag :color="dns.family ? 'purple' : 'green'">[[ dns.family ? '{{ i18n "pages.xray.dns.dnsPresetFamily" }}' : 'DNS' ]]</a-tag>
|
||||||
|
</a-space>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12" :style="{ textAlign: 'right' }">
|
||||||
|
<a-button type="primary" @click="dnsPresetsModal.install(dns.data)">{{ i18n "install" }}</a-button>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-modal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dark .ant-dns-presets-list {
|
||||||
|
border-color: var(--dark-color-stroke)
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .ant-dns-presets-list-name {
|
||||||
|
color: var(--dark-color-text-primary);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const dnsPresetsDatabase = [
|
||||||
|
{
|
||||||
|
name: 'Google DNS',
|
||||||
|
family: false,
|
||||||
|
data: [
|
||||||
|
"8.8.8.8",
|
||||||
|
"8.8.4.4",
|
||||||
|
"2001:4860:4860::8888",
|
||||||
|
"2001:4860:4860::8844"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cloudflare DNS',
|
||||||
|
family: false,
|
||||||
|
data: [
|
||||||
|
"1.1.1.1",
|
||||||
|
"1.0.0.1",
|
||||||
|
"2606:4700:4700::1111",
|
||||||
|
"2606:4700:4700::1001"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Adguard DNS',
|
||||||
|
family: false,
|
||||||
|
data: [
|
||||||
|
"94.140.14.14",
|
||||||
|
"94.140.15.15",
|
||||||
|
"2a10:50c0::ad1:ff",
|
||||||
|
"2a10:50c0::ad2:ff"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Adguard Family DNS',
|
||||||
|
family: true,
|
||||||
|
data: [
|
||||||
|
"94.140.14.14",
|
||||||
|
"94.140.15.15",
|
||||||
|
"2a10:50c0::ad1:ff",
|
||||||
|
"2a10:50c0::ad2:ff"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cloudflare Family DNS',
|
||||||
|
family: true,
|
||||||
|
data: [
|
||||||
|
"1.1.1.3",
|
||||||
|
"1.0.0.3",
|
||||||
|
"2606:4700:4700::1113",
|
||||||
|
"2606:4700:4700::1003"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const dnsPresetsModal = {
|
||||||
|
title: '',
|
||||||
|
visible: false,
|
||||||
|
selected: null,
|
||||||
|
install(selectedPreset) {
|
||||||
|
return ObjectUtil.execute(dnsPresetsModal.selected, selectedPreset);
|
||||||
|
},
|
||||||
|
show({ title = '', selected = (selectedPreset) => { }, isEdit = false }) {
|
||||||
|
this.title = title;
|
||||||
|
this.selected = selected;
|
||||||
|
this.visible = true;
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
dnsPresetsModal.visible = false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
delimiters: ['[[', ']]'],
|
||||||
|
el: '#dnsPresets-modal',
|
||||||
|
data: {
|
||||||
|
dnsPresetsModal: dnsPresetsModal,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{end}}
|
|
@ -1,57 +0,0 @@
|
||||||
{{define "modals/fakednsModal"}}
|
|
||||||
<a-modal id="fakedns-modal" v-model="fakednsModal.visible" :title="fakednsModal.title" @ok="fakednsModal.ok"
|
|
||||||
:closable="true" :mask-closable="false"
|
|
||||||
:ok-text="fakednsModal.okText" cancel-text='{{ i18n "close" }}' :class="themeSwitcher.currentTheme">
|
|
||||||
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
|
|
||||||
<a-form-item label='{{ i18n "pages.xray.fakedns.ipPool" }}'>
|
|
||||||
<a-input v-model.trim="fakednsModal.fakeDns.ipPool"></a-input>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label='{{ i18n "pages.xray.fakedns.poolSize" }}'>
|
|
||||||
<a-input-number v-model.number="fakednsModal.fakeDns.poolSize" :min="1"></a-input-number>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-modal>
|
|
||||||
<script>
|
|
||||||
const fakednsModal = {
|
|
||||||
title: '',
|
|
||||||
visible: false,
|
|
||||||
okText: '{{ i18n "confirm" }}',
|
|
||||||
isEdit: false,
|
|
||||||
confirm: null,
|
|
||||||
fakeDns: {
|
|
||||||
ipPool: "198.18.0.0/16",
|
|
||||||
poolSize: 65535,
|
|
||||||
},
|
|
||||||
ok() {
|
|
||||||
ObjectUtil.execute(fakednsModal.confirm, fakednsModal.fakeDns);
|
|
||||||
},
|
|
||||||
show({ title='', okText='{{ i18n "confirm" }}', fakeDns, confirm=(fakeDns)=>{}, isEdit=false }) {
|
|
||||||
this.title = title;
|
|
||||||
this.okText = okText;
|
|
||||||
this.confirm = confirm;
|
|
||||||
this.visible = true;
|
|
||||||
if(isEdit) {
|
|
||||||
this.fakeDns = fakeDns;
|
|
||||||
} else {
|
|
||||||
this.fakeDns = {
|
|
||||||
ipPool: "198.18.0.0/16",
|
|
||||||
poolSize: 65535,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.isEdit = isEdit;
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
fakednsModal.visible = false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
new Vue({
|
|
||||||
delimiters: ['[[', ']]'],
|
|
||||||
el: '#fakedns-modal',
|
|
||||||
data: {
|
|
||||||
fakednsModal: fakednsModal,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
{{end}}
|
|
|
@ -433,6 +433,9 @@
|
||||||
<a-tooltip title='{{ i18n "copy" }}'>
|
<a-tooltip title='{{ i18n "copy" }}'>
|
||||||
<a-button :style="{ minWidth: '24px' }" size="small" icon="snippets" @click="copy(infoModal.links[index])"></a-button>
|
<a-button :style="{ minWidth: '24px' }" size="small" icon="snippets" @click="copy(infoModal.links[index])"></a-button>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
|
<a-tooltip title='{{ i18n "download" }}'>
|
||||||
|
<a-button :style="{ minWidth: '24px' }" size="small" icon="download" @click="FileManager.downloadTextFile(infoModal.links[index], `peer-${index + 1}.conf`)"></a-button>
|
||||||
|
</a-tooltip>
|
||||||
</tr-info-title>
|
</tr-info-title>
|
||||||
<div v-html="infoModal.links[index].replaceAll(`\n`,`<br />`)" :style="{ borderRadius: '1rem', padding: '0.5rem' }" class="client-table-odd-row">
|
<div v-html="infoModal.links[index].replaceAll(`\n`,`<br />`)" :style="{ borderRadius: '1rem', padding: '0.5rem' }" class="client-table-odd-row">
|
||||||
</div>
|
</div>
|
||||||
|
@ -478,10 +481,19 @@
|
||||||
this.isExpired = this.inbound.clients ? this.inbound.isExpiry(index) : this.dbInbound.isExpiry;
|
this.isExpired = this.inbound.clients ? this.inbound.isExpiry(index) : this.dbInbound.isExpiry;
|
||||||
this.clientStats = this.inbound.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : [];
|
this.clientStats = this.inbound.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : [];
|
||||||
|
|
||||||
if (app.ipLimitEnable && this.clientSettings.limitIp) {
|
if (
|
||||||
refreshIPs(this.clientStats.email).then((ips) => {
|
[
|
||||||
this.clientIps = ips;
|
Protocols.VMESS,
|
||||||
})
|
Protocols.VLESS,
|
||||||
|
Protocols.TROJAN,
|
||||||
|
Protocols.SHADOWSOCKS
|
||||||
|
].includes(this.inbound.protocol)
|
||||||
|
) {
|
||||||
|
if (app.ipLimitEnable && this.clientSettings.limitIp) {
|
||||||
|
refreshIPs(this.clientStats.email).then((ips) => {
|
||||||
|
this.clientIps = ips;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.inbound.protocol == Protocols.WIREGUARD) {
|
if (this.inbound.protocol == Protocols.WIREGUARD) {
|
||||||
this.links = this.inbound.genInboundLinks(dbInbound.remark).split('\r\n')
|
this.links = this.inbound.genInboundLinks(dbInbound.remark).split('\r\n')
|
||||||
|
|
|
@ -6,6 +6,16 @@
|
||||||
<a-form-item label='{{ i18n "pages.xray.outbound.address" }}'>
|
<a-form-item label='{{ i18n "pages.xray.outbound.address" }}'>
|
||||||
<a-input v-model.trim="dnsModal.dnsServer.address"></a-input>
|
<a-input v-model.trim="dnsModal.dnsServer.address"></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.inbounds.port" }}'>
|
||||||
|
<a-input-number v-model.number="dnsModal.dnsServer.port" :min="1" :max="65531"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.dns.strategy" }}'>
|
||||||
|
<a-select v-model="dnsModal.dnsServer.queryStrategy" :style="{ width: '100%' }"
|
||||||
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
|
<a-select-option :value="l" :label="l" v-for="l in ['UseSystem', 'UseIP', 'UseIPv4', 'UseIPv6']"> [[ l ]] </a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-divider :style="{ margin: '5px 0' }"></a-divider>
|
||||||
<a-form-item label='{{ i18n "pages.xray.dns.domains" }}'>
|
<a-form-item label='{{ i18n "pages.xray.dns.domains" }}'>
|
||||||
<a-button icon="plus" size="small" type="primary" @click="dnsModal.dnsServer.domains.push('')"></a-button>
|
<a-button icon="plus" size="small" type="primary" @click="dnsModal.dnsServer.domains.push('')"></a-button>
|
||||||
<template v-for="(domain, index) in dnsModal.dnsServer.domains">
|
<template v-for="(domain, index) in dnsModal.dnsServer.domains">
|
||||||
|
@ -15,15 +25,6 @@
|
||||||
</a-input>
|
</a-input>
|
||||||
</template>
|
</template>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label='{{ i18n "pages.xray.dns.strategy" }}' v-if="isAdvanced">
|
|
||||||
<a-select v-model="dnsModal.dnsServer.queryStrategy" :style="{ width: '100%' }"
|
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme">
|
|
||||||
<a-select-option :value="l" :label="l" v-for="l in ['UseIP', 'UseIPv4', 'UseIPv6']"> [[ l ]] </a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label='Skip Fallback' v-if="isAdvanced">
|
|
||||||
<a-switch v-model="dnsModal.dnsServer.skipFallback"></a-switch>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label='{{ i18n "pages.xray.dns.expectIPs"}}'>
|
<a-form-item label='{{ i18n "pages.xray.dns.expectIPs"}}'>
|
||||||
<a-button icon="plus" size="small" type="primary" @click="dnsModal.dnsServer.expectIPs.push('')"></a-button>
|
<a-button icon="plus" size="small" type="primary" @click="dnsModal.dnsServer.expectIPs.push('')"></a-button>
|
||||||
<template v-for="(domain, index) in dnsModal.dnsServer.expectIPs">
|
<template v-for="(domain, index) in dnsModal.dnsServer.expectIPs">
|
||||||
|
@ -33,31 +34,50 @@
|
||||||
</a-input>
|
</a-input>
|
||||||
</template>
|
</template>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.dns.unexpectIPs"}}'>
|
||||||
|
<a-button icon="plus" size="small" type="primary" @click="dnsModal.dnsServer.unexpectedIPs.push('')"></a-button>
|
||||||
|
<template v-for="(domain, index) in dnsModal.dnsServer.unexpectedIPs">
|
||||||
|
<a-input v-model.trim="dnsModal.dnsServer.unexpectedIPs[index]">
|
||||||
|
<a-button icon="minus" size="small" slot="addonAfter"
|
||||||
|
@click="dnsModal.dnsServer.unexpectedIPs.splice(index,1)"></a-button>
|
||||||
|
</a-input>
|
||||||
|
</template>
|
||||||
|
</a-form-item>
|
||||||
|
<a-divider :style="{ margin: '5px 0' }"></a-divider>
|
||||||
|
<a-form-item label='Skip Fallback'>
|
||||||
|
<a-switch v-model="dnsModal.dnsServer.skipFallback"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='Disable Cache'>
|
||||||
|
<a-switch v-model="dnsModal.dnsServer.disableCache"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='Final Query'>
|
||||||
|
<a-switch v-model="dnsModal.dnsServer.finalQuery"></a-switch>
|
||||||
|
</a-form-item>
|
||||||
</a-form>
|
</a-form>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<script>
|
<script>
|
||||||
|
const defaultDnsObject = {
|
||||||
|
address: "localhost",
|
||||||
|
port: 53,
|
||||||
|
domains: [],
|
||||||
|
expectIPs: [],
|
||||||
|
unexpectedIPs: [],
|
||||||
|
queryStrategy: 'UseIP',
|
||||||
|
skipFallback: true,
|
||||||
|
disableCache: false,
|
||||||
|
finalQuery: false
|
||||||
|
}
|
||||||
|
|
||||||
const dnsModal = {
|
const dnsModal = {
|
||||||
title: '',
|
title: '',
|
||||||
visible: false,
|
visible: false,
|
||||||
okText: '{{ i18n "confirm" }}',
|
okText: '{{ i18n "confirm" }}',
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
confirm: null,
|
confirm: null,
|
||||||
dnsServer: {
|
dnsServer: { ...defaultDnsObject },
|
||||||
address: "localhost",
|
ok() {
|
||||||
domains: [],
|
ObjectUtil.execute(dnsModal.confirm, { ...dnsModal.dnsServer });
|
||||||
expectIPs: [],
|
|
||||||
queryStrategy: 'UseIP',
|
|
||||||
skipFallback: true,
|
|
||||||
},
|
},
|
||||||
ok() {
|
|
||||||
domains = dnsModal.dnsServer.domains.filter(d => d.length > 0);
|
|
||||||
expectIPs = dnsModal.dnsServer.expectIPs.filter(ip => ip.length > 0);
|
|
||||||
dnsModal.dnsServer.domains = domains;
|
|
||||||
dnsModal.dnsServer.expectIPs = expectIPs;
|
|
||||||
newDnsServer = (domains.length > 0 || expectIPs.length > 0) ? dnsModal.dnsServer : dnsModal.dnsServer.address;
|
|
||||||
ObjectUtil.execute(dnsModal.confirm, newDnsServer);
|
|
||||||
},
|
|
||||||
|
|
||||||
show({
|
show({
|
||||||
title = '',
|
title = '',
|
||||||
okText = '{{ i18n "confirm" }}',
|
okText = '{{ i18n "confirm" }}',
|
||||||
|
@ -69,28 +89,28 @@
|
||||||
this.okText = okText;
|
this.okText = okText;
|
||||||
this.confirm = confirm;
|
this.confirm = confirm;
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
|
this.isEdit = isEdit;
|
||||||
|
|
||||||
if (isEdit) {
|
if (isEdit) {
|
||||||
if (typeof dnsServer == 'object') {
|
switch (typeof dnsServer) {
|
||||||
this.dnsServer = dnsServer;
|
case 'string':
|
||||||
} else {
|
const dnsObj = { ...defaultDnsObject };
|
||||||
this.dnsServer = {
|
|
||||||
address: dnsServer ?? "",
|
dnsObj.address = dnsServer;
|
||||||
domains: [],
|
|
||||||
expectIPs: [],
|
this.dnsServer = dnsObj;
|
||||||
queryStrategy: 'UseIP',
|
break;
|
||||||
skipFallback: true,
|
case 'object':
|
||||||
}
|
this.dnsServer = dnsServer;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.dnsServer = {
|
this.dnsServer = { ...defaultDnsObject };
|
||||||
address: "localhost",
|
|
||||||
domains: [],
|
this.dnsServer.domains = [];
|
||||||
expectIPs: [],
|
this.dnsServer.expectIPs = [];
|
||||||
queryStrategy: 'UseIP',
|
this.dnsServer.unexpectedIPs = [];
|
||||||
skipFallback: true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.isEdit = isEdit;
|
|
||||||
},
|
},
|
||||||
close() {
|
close() {
|
||||||
dnsModal.visible = false;
|
dnsModal.visible = false;
|
||||||
|
@ -101,13 +121,6 @@
|
||||||
el: '#dns-modal',
|
el: '#dns-modal',
|
||||||
data: {
|
data: {
|
||||||
dnsModal: dnsModal,
|
dnsModal: dnsModal,
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isAdvanced: {
|
|
||||||
get: function () {
|
|
||||||
return dnsModal.dnsServer.domains.length > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
56
web/html/modals/xray_fakedns_modal.html
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{{define "modals/fakednsModal"}}
|
||||||
|
<a-modal id="fakedns-modal" v-model="fakednsModal.visible" :title="fakednsModal.title" @ok="fakednsModal.ok"
|
||||||
|
:closable="true" :mask-closable="false" :ok-text="fakednsModal.okText" cancel-text='{{ i18n "close" }}'
|
||||||
|
:class="themeSwitcher.currentTheme">
|
||||||
|
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.fakedns.ipPool" }}'>
|
||||||
|
<a-input v-model.trim="fakednsModal.fakeDns.ipPool"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label='{{ i18n "pages.xray.fakedns.poolSize" }}'>
|
||||||
|
<a-input-number v-model.number="fakednsModal.fakeDns.poolSize" :min="1"></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-modal>
|
||||||
|
<script>
|
||||||
|
const fakednsDefaultData = {
|
||||||
|
ipPool: "198.18.0.0/16",
|
||||||
|
poolSize: 65535,
|
||||||
|
}
|
||||||
|
|
||||||
|
const fakednsModal = {
|
||||||
|
title: '',
|
||||||
|
visible: false,
|
||||||
|
okText: '{{ i18n "confirm" }}',
|
||||||
|
isEdit: false,
|
||||||
|
confirm: null,
|
||||||
|
fakeDns: { ...fakednsDefaultData },
|
||||||
|
ok() {
|
||||||
|
ObjectUtil.execute(fakednsModal.confirm, fakednsModal.fakeDns);
|
||||||
|
},
|
||||||
|
show({ title = '', okText = '{{ i18n "confirm" }}', fakeDns, confirm = (fakeDns) => { }, isEdit = false }) {
|
||||||
|
this.title = title;
|
||||||
|
this.okText = okText;
|
||||||
|
this.confirm = confirm;
|
||||||
|
this.visible = true;
|
||||||
|
if (isEdit) {
|
||||||
|
this.fakeDns = fakeDns;
|
||||||
|
} else {
|
||||||
|
this.fakeDns = { ...fakednsDefaultData }
|
||||||
|
}
|
||||||
|
this.isEdit = isEdit;
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
fakednsModal.visible = false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
delimiters: ['[[', ']]'],
|
||||||
|
el: '#fakedns-modal',
|
||||||
|
data: {
|
||||||
|
fakednsModal: fakednsModal,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{{end}}
|
|
@ -1,6 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{ template "page/head_start" .}}
|
||||||
<html lang="en">
|
|
||||||
{{template "head" .}}
|
|
||||||
<style>
|
<style>
|
||||||
@media (min-width: 769px) {
|
@media (min-width: 769px) {
|
||||||
.ant-layout-content {
|
.ant-layout-content {
|
||||||
|
@ -60,68 +58,103 @@
|
||||||
margin-block-end: 12px;
|
margin-block-end: 12px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<body>
|
{{ template "page/head_end" .}}
|
||||||
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
|
||||||
<a-sidebar></a-sidebar>
|
{{ template "page/body_start" .}}
|
||||||
<a-layout id="content-layout">
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
||||||
<a-layout-content>
|
<a-sidebar></a-sidebar>
|
||||||
<a-spin :spinning="spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
<a-layout id="content-layout">
|
||||||
<transition name="list" appear>
|
<a-layout-content>
|
||||||
<a-alert type="error" v-if="confAlerts.length>0" :style="{ marginBottom: '10px' }"
|
<a-spin :spinning="loadingStates.spinning" :delay="500" tip='{{ i18n "loading"}}'>
|
||||||
message='{{ i18n "secAlertTitle" }}'
|
<transition name="list" appear>
|
||||||
color="red"
|
<a-alert type="error" v-if="confAlerts.length>0 && loadingStates.fetched" :style="{ marginBottom: '10px' }"
|
||||||
show-icon closable>
|
message='{{ i18n "secAlertTitle" }}'
|
||||||
<template slot="description">
|
color="red"
|
||||||
<b>{{ i18n "secAlertConf" }}</b>
|
show-icon closable>
|
||||||
<ul><li v-for="a in confAlerts">[[ a ]]</li></ul>
|
<template slot="description">
|
||||||
</template>
|
<b>{{ i18n "secAlertConf" }}</b>
|
||||||
</a-alert>
|
<ul><li v-for="a in confAlerts">[[ a ]]</li></ul>
|
||||||
</transition>
|
</template>
|
||||||
<a-space direction="vertical">
|
</a-alert>
|
||||||
<a-card hoverable :style="{ marginBottom: '.5rem', overflowX: 'hidden' }">
|
</transition>
|
||||||
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
<transition name="list" appear>
|
||||||
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
<template>
|
||||||
<a-space direction="horizontal">
|
<a-row v-if="!loadingStates.fetched">
|
||||||
<a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.settings.save" }}</a-button>
|
<a-card :style="{ textAlign: 'center', padding: '30px 0', marginTop: '10px', background: 'transparent', border: 'none' }">
|
||||||
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.settings.restartPanel" }}</a-button>
|
<a-spin tip='{{ i18n "loading" }}'></a-spin>
|
||||||
</a-space>
|
</a-card>
|
||||||
</a-col>
|
</a-row>
|
||||||
<a-col :xs="24" :sm="14">
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]" v-else>
|
||||||
<template>
|
<a-col>
|
||||||
<div>
|
<a-card hoverable>
|
||||||
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
<a-row :style="{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }">
|
||||||
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }"
|
<a-col :xs="24" :sm="10" :style="{ padding: '4px' }">
|
||||||
message='{{ i18n "pages.settings.infoDesc" }}'
|
<a-space direction="horizontal">
|
||||||
show-icon>
|
<a-button type="primary" :disabled="saveBtnDisable" @click="updateAllSetting">{{ i18n "pages.settings.save" }}</a-button>
|
||||||
</a-alert>
|
<a-button type="danger" :disabled="!saveBtnDisable" @click="restartPanel">{{ i18n "pages.settings.restartPanel" }}</a-button>
|
||||||
</div>
|
</a-space>
|
||||||
</template>
|
</a-col>
|
||||||
</a-col>
|
<a-col :xs="24" :sm="14">
|
||||||
</a-row>
|
<template>
|
||||||
</a-card>
|
<div>
|
||||||
<a-tabs default-active-key="1">
|
<a-back-top :target="() => document.getElementById('content-layout')" visibility-height="200"></a-back-top>
|
||||||
<a-tab-pane key="1" tab='{{ i18n "pages.settings.panelSettings" }}' :style="{ paddingTop: '20px' }">
|
<a-alert type="warning" :style="{ float: 'right', width: 'fit-content' }"
|
||||||
{{ template "settings/panel/general" . }}
|
message='{{ i18n "pages.settings.infoDesc" }}'
|
||||||
</a-tab-pane>
|
show-icon>
|
||||||
<a-tab-pane key="2" tab='{{ i18n "pages.settings.securitySettings" }}' :style="{ paddingTop: '20px' }">
|
</a-alert>
|
||||||
{{ template "settings/panel/security" . }}
|
</div>
|
||||||
</a-tab-pane>
|
</template>
|
||||||
<a-tab-pane key="3" tab='{{ i18n "pages.settings.TGBotSettings" }}' :style="{ paddingTop: '20px' }">
|
</a-col>
|
||||||
{{ template "settings/panel/telegram" . }}
|
</a-row>
|
||||||
</a-tab-pane>
|
</a-card>
|
||||||
<a-tab-pane key="4" tab='{{ i18n "pages.settings.subSettings" }}' :style="{ paddingTop: '20px' }">
|
</a-col>
|
||||||
{{ template "settings/panel/subscription/general" . }}
|
<a-col>
|
||||||
</a-tab-pane>
|
<a-tabs default-active-key="1">
|
||||||
<a-tab-pane key="5" tab='{{ i18n "pages.settings.subSettings" }} Json' v-if="allSetting.subEnable" :style="{ paddingTop: '20px' }">
|
<a-tab-pane key="1" :style="{ paddingTop: '20px' }">
|
||||||
{{ template "settings/panel/subscription/json" . }}
|
<template #tab>
|
||||||
</a-tab-pane>
|
<a-icon type="setting"></a-icon>
|
||||||
</a-tabs>
|
<span>{{ i18n "pages.settings.panelSettings" }}</span>
|
||||||
</a-space>
|
</template>
|
||||||
</a-spin>
|
{{ template "settings/panel/general" . }}
|
||||||
</a-layout-content>
|
</a-tab-pane>
|
||||||
</a-layout>
|
<a-tab-pane key="2" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="safety"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.securitySettings" }}</span>
|
||||||
|
</template>
|
||||||
|
{{ template "settings/panel/security" . }}
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="3" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="message"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.TGBotSettings" }}</span>
|
||||||
|
</template>
|
||||||
|
{{ template "settings/panel/telegram" . }}
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="4" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="cloud-server"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.subSettings" }}</span>
|
||||||
|
</template>
|
||||||
|
{{ template "settings/panel/subscription/general" . }}
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="5" v-if="allSetting.subEnable" :style="{ paddingTop: '20px' }">
|
||||||
|
<template #tab>
|
||||||
|
<a-icon type="code"></a-icon>
|
||||||
|
<span>{{ i18n "pages.settings.subSettings" }} (JSON)</span>
|
||||||
|
</template>
|
||||||
|
{{ template "settings/panel/subscription/json" . }}
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</template>
|
||||||
|
</transition>
|
||||||
|
</a-spin>
|
||||||
|
</a-layout-content>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
</a-layout>
|
||||||
|
{{template "page/body_scripts" .}}
|
||||||
<script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/qrcode/qrious2.min.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/otpauth/otpauth.umd.min.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/otpauth/otpauth.umd.min.js?{{ .cur_ver }}"></script>
|
||||||
<script src="{{ .base_path }}assets/js/model/setting.js?{{ .cur_ver }}"></script>
|
<script src="{{ .base_path }}assets/js/model/setting.js?{{ .cur_ver }}"></script>
|
||||||
|
@ -132,10 +165,14 @@
|
||||||
<script>
|
<script>
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
|
mixins: [MediaQueryMixin],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
data: {
|
data: {
|
||||||
themeSwitcher,
|
themeSwitcher,
|
||||||
spinning: false,
|
loadingStates: {
|
||||||
|
fetched: false,
|
||||||
|
spinning: false
|
||||||
|
},
|
||||||
oldAllSetting: new AllSetting(),
|
oldAllSetting: new AllSetting(),
|
||||||
allSetting: new AllSetting(),
|
allSetting: new AllSetting(),
|
||||||
saveBtnDisable: true,
|
saveBtnDisable: true,
|
||||||
|
@ -248,13 +285,16 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loading(spinning = true) {
|
loading(spinning = true) {
|
||||||
this.spinning = spinning;
|
this.loadingStates.spinning = spinning;
|
||||||
},
|
},
|
||||||
async getAllSetting() {
|
async getAllSetting() {
|
||||||
this.loading(true);
|
|
||||||
const msg = await HttpUtil.post("/panel/setting/all");
|
const msg = await HttpUtil.post("/panel/setting/all");
|
||||||
this.loading(false);
|
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
|
if (!this.loadingStates.fetched) {
|
||||||
|
this.loadingStates.fetched = true
|
||||||
|
}
|
||||||
|
|
||||||
this.oldAllSetting = new AllSetting(msg.obj);
|
this.oldAllSetting = new AllSetting(msg.obj);
|
||||||
this.allSetting = new AllSetting(msg.obj);
|
this.allSetting = new AllSetting(msg.obj);
|
||||||
app.changeRemarkSample();
|
app.changeRemarkSample();
|
||||||
|
@ -531,7 +571,7 @@
|
||||||
if (!this.allSetting) return [];
|
if (!this.allSetting) return [];
|
||||||
var alerts = []
|
var alerts = []
|
||||||
if (window.location.protocol !== "https:") alerts.push('{{ i18n "secAlertSSL" }}');
|
if (window.location.protocol !== "https:") alerts.push('{{ i18n "secAlertSSL" }}');
|
||||||
if (this.allSetting.webPort == 54321) alerts.push('{{ i18n "secAlertPanelPort" }}');
|
if (this.allSetting.webPort === 2053) alerts.push('{{ i18n "secAlertPanelPort" }}');
|
||||||
panelPath = window.location.pathname.split('/').length < 4
|
panelPath = window.location.pathname.split('/').length < 4
|
||||||
if (panelPath && this.allSetting.webBasePath == '/') alerts.push('{{ i18n "secAlertPanelURI" }}');
|
if (panelPath && this.allSetting.webBasePath == '/') alerts.push('{{ i18n "secAlertPanelURI" }}');
|
||||||
if (this.allSetting.subEnable) {
|
if (this.allSetting.subEnable) {
|
||||||
|
@ -554,5 +594,4 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
{{ template "page/body_end" .}}
|
||||||
</html>
|
|
|
@ -1,5 +1,5 @@
|
||||||
{{define "settings/xray/advanced"}}
|
{{define "settings/xray/advanced"}}
|
||||||
<a-space direction="vertical" size="small">
|
<a-space direction="vertical" size="small" :style="{ marginTop: '20px' }">
|
||||||
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}'
|
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}'
|
||||||
description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
|
||||||
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" :style="{ margin: '10px 0' }"
|
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" :style="{ margin: '10px 0' }"
|
||||||
|
|
|
@ -135,7 +135,7 @@
|
||||||
</template>
|
</template>
|
||||||
</a-setting-list-item>
|
</a-setting-list-item>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<a-collapse-panel key="4" header='{{ i18n "pages.xray.blockConfigs"}}'>
|
<a-collapse-panel key="4" header='{{ i18n "pages.xray.basicRouting"}}'>
|
||||||
<a-row :xs="24" :sm="24" :lg="12">
|
<a-row :xs="24" :sm="24" :lg="12">
|
||||||
<a-alert type="warning" :style="{ textAlign: 'center' }">
|
<a-alert type="warning" :style="{ textAlign: 'center' }">
|
||||||
<template slot="message">
|
<template slot="message">
|
||||||
|
@ -144,22 +144,12 @@
|
||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-setting-list-item paddings="small">
|
<a-setting-list-item paddings="small" :style="{ marginBottom: '20px' }">
|
||||||
<template #title>{{ i18n "pages.xray.Torrent"}}</template>
|
<template #title>{{ i18n "pages.xray.Torrent"}}</template>
|
||||||
<template #description>{{ i18n "pages.xray.TorrentDesc"}}</template>
|
|
||||||
<template #control>
|
<template #control>
|
||||||
<a-switch v-model="torrentSettings"></a-switch>
|
<a-switch v-model="torrentSettings"></a-switch>
|
||||||
</template>
|
</template>
|
||||||
</a-setting-list-item>
|
</a-setting-list-item>
|
||||||
<a-setting-list-item paddings="small">
|
|
||||||
<template #title>{{ i18n "pages.xray.Family"}}</template>
|
|
||||||
<template #description>{{ i18n "pages.xray.FamilyDesc"}}</template>
|
|
||||||
<template #control>
|
|
||||||
<a-switch v-model="familyProtectSettings"></a-switch>
|
|
||||||
</template>
|
|
||||||
</a-setting-list-item>
|
|
||||||
</a-collapse-panel>
|
|
||||||
<a-collapse-panel key="5" header='{{ i18n "pages.xray.basicRouting"}}'>
|
|
||||||
<a-row :xs="24" :sm="24" :lg="12">
|
<a-row :xs="24" :sm="24" :lg="12">
|
||||||
<a-alert type="warning" :style="{ textAlign: 'center' }">
|
<a-alert type="warning" :style="{ textAlign: 'center' }">
|
||||||
<template slot="message">
|
<template slot="message">
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<template #control>
|
<template #control>
|
||||||
<a-select v-model="dnsStrategy" :style="{ width: '100%' }"
|
<a-select v-model="dnsStrategy" :style="{ width: '100%' }"
|
||||||
:dropdown-class-name="themeSwitcher.currentTheme">
|
:dropdown-class-name="themeSwitcher.currentTheme">
|
||||||
<a-select-option :value="l" :label="l" v-for="l in ['UseIP', 'UseIPv4', 'UseIPv6']">
|
<a-select-option :value="l" :label="l" v-for="l in ['UseSystem', 'UseIP', 'UseIPv4', 'UseIPv6']">
|
||||||
<span>[[ l ]]</span>
|
<span>[[ l ]]</span>
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
@ -56,6 +56,14 @@
|
||||||
<a-switch v-model="dnsDisableFallbackIfMatch"></a-switch>
|
<a-switch v-model="dnsDisableFallbackIfMatch"></a-switch>
|
||||||
</template>
|
</template>
|
||||||
</a-setting-list-item>
|
</a-setting-list-item>
|
||||||
|
|
||||||
|
<a-setting-list-item paddings="small">
|
||||||
|
<template #title>{{ i18n "pages.xray.dns.useSystemHosts" }}</template>
|
||||||
|
<template #description>{{ i18n "pages.xray.dns.useSystemHostsDesc" }}</template>
|
||||||
|
<template #control>
|
||||||
|
<a-switch v-model="dnsUseSystemHosts"></a-switch>
|
||||||
|
</template>
|
||||||
|
</a-setting-list-item>
|
||||||
</template>
|
</template>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
<template v-if="enableDNS">
|
<template v-if="enableDNS">
|
||||||
|
@ -102,9 +110,12 @@
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<a-empty description='{{ i18n "emptyDnsDesc" }}' :style="{ margin: '10px' }">
|
<a-empty description='{{ i18n "emptyDnsDesc" }}' :style="{ margin: '10px' }">
|
||||||
<a-button type="primary" icon="plus" @click="addDNSServer()" :style="{ marginTop: '10px' }">
|
<a-button-group>
|
||||||
<span>{{ i18n "pages.xray.dns.add" }}</span>
|
<a-button type="primary" icon="plus" @click="addDNSServer()">
|
||||||
</a-button>
|
<span>{{ i18n "pages.xray.dns.add" }}</span>
|
||||||
|
</a-button>
|
||||||
|
<a-button type="primary" icon="menu" @click="openDNSPresets()"></a-button>
|
||||||
|
</a-button-group>
|
||||||
</a-empty>
|
</a-empty>
|
||||||
</template>
|
</template>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
|
|
2799
web/html/xray.html
|
@ -81,5 +81,9 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"stats": {}
|
"stats": {},
|
||||||
}
|
"metrics": {
|
||||||
|
"tag": "metrics_out",
|
||||||
|
"listen": "127.0.0.1:11111"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -295,7 +295,7 @@ func (s *ServerService) GetXrayVersions() ([]string, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if major > 25 || (major == 25 && minor > 3) || (major == 25 && minor == 3 && patch >= 3) {
|
if major > 25 || (major == 25 && minor > 6) || (major == 25 && minor == 6 && patch >= 8) {
|
||||||
versions = append(versions, release.TagName)
|
versions = append(versions, release.TagName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,19 @@ func (t *Tgbot) Start(i18nFS embed.FS) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// After bot initialization, set up bot commands with localized descriptions
|
||||||
|
err = bot.SetMyCommands(&telego.SetMyCommandsParams{
|
||||||
|
Commands: []telego.BotCommand{
|
||||||
|
{Command: "start", Description: t.I18nBot("tgbot.commands.startDesc")},
|
||||||
|
{Command: "help", Description: t.I18nBot("tgbot.commands.helpDesc")},
|
||||||
|
{Command: "status", Description: t.I18nBot("tgbot.commands.statusDesc")},
|
||||||
|
{Command: "id", Description: t.I18nBot("tgbot.commands.idDesc")},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
logger.Warning("Failed to set bot commands:", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Start receiving Telegram bot messages
|
// Start receiving Telegram bot messages
|
||||||
if !isRunning {
|
if !isRunning {
|
||||||
logger.Info("Telegram bot receiver started")
|
logger.Info("Telegram bot receiver started")
|
||||||
|
@ -935,7 +948,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
||||||
),
|
),
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_reset_exp_c "+strconv.Itoa(inputNumber))),
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_reset_exp_c "+strconv.Itoa(inputNumber))),
|
||||||
),
|
),
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 1")),
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 1")),
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
"totalData" = "إجمالي البيانات"
|
"totalData" = "إجمالي البيانات"
|
||||||
"sent" = "مرسل"
|
"sent" = "مرسل"
|
||||||
"received" = "مستقبل"
|
"received" = "مستقبل"
|
||||||
|
"documentation" = "التوثيق"
|
||||||
"xraySwitchVersionDialog" = "هل تريد حقًا تغيير إصدار Xray؟"
|
"xraySwitchVersionDialog" = "هل تريد حقًا تغيير إصدار Xray؟"
|
||||||
"xraySwitchVersionDialogDesc" = "سيؤدي هذا إلى تغيير إصدار Xray إلى #version#."
|
"xraySwitchVersionDialogDesc" = "سيؤدي هذا إلى تغيير إصدار Xray إلى #version#."
|
||||||
"xraySwitchVersionPopover" = "تم تحديث Xray بنجاح"
|
"xraySwitchVersionPopover" = "تم تحديث Xray بنجاح"
|
||||||
|
@ -399,7 +400,6 @@
|
||||||
"generalConfigsDesc" = "الخيارات دي هتحدد التعديلات العامة."
|
"generalConfigsDesc" = "الخيارات دي هتحدد التعديلات العامة."
|
||||||
"logConfigs" = "السجلات"
|
"logConfigs" = "السجلات"
|
||||||
"logConfigsDesc" = "السجلات ممكن تأثر على كفاءة السيرفر. ننصح بتفعيلها بحكمة لما تكون محتاجها."
|
"logConfigsDesc" = "السجلات ممكن تأثر على كفاءة السيرفر. ننصح بتفعيلها بحكمة لما تكون محتاجها."
|
||||||
"blockConfigs" = "درع الحماية"
|
|
||||||
"blockConfigsDesc" = "الخيارات دي هتحجب الترافيك بناءً على بروتوكولات ومواقع محددة."
|
"blockConfigsDesc" = "الخيارات دي هتحجب الترافيك بناءً على بروتوكولات ومواقع محددة."
|
||||||
"basicRouting" = "توجيه أساسي"
|
"basicRouting" = "توجيه أساسي"
|
||||||
"blockConnectionsConfigsDesc" = "الخيارات دي هتحجب الترافيك بناءً على الدولة المطلوبة."
|
"blockConnectionsConfigsDesc" = "الخيارات دي هتحجب الترافيك بناءً على الدولة المطلوبة."
|
||||||
|
@ -419,9 +419,6 @@
|
||||||
"RoutingStrategy" = "استراتيجية التوجيه العامة"
|
"RoutingStrategy" = "استراتيجية التوجيه العامة"
|
||||||
"RoutingStrategyDesc" = "حدد استراتيجية التوجيه الإجمالية لحل كل الطلبات."
|
"RoutingStrategyDesc" = "حدد استراتيجية التوجيه الإجمالية لحل كل الطلبات."
|
||||||
"Torrent" = "حظر بروتوكول التورنت"
|
"Torrent" = "حظر بروتوكول التورنت"
|
||||||
"TorrentDesc" = "بيحجب بروتوكول التورنت."
|
|
||||||
"Family" = "حماية العيلة"
|
|
||||||
"FamilyDesc" = "بيحجب المحتويات الكبار وعناوين المواقع الضارة."
|
|
||||||
"Inbounds" = "الإدخالات"
|
"Inbounds" = "الإدخالات"
|
||||||
"InboundsDesc" = "قبول العملاء المعينين."
|
"InboundsDesc" = "قبول العملاء المعينين."
|
||||||
"Outbounds" = "المخرجات"
|
"Outbounds" = "المخرجات"
|
||||||
|
@ -521,6 +518,12 @@
|
||||||
"edit" = "عدل السيرفر"
|
"edit" = "عدل السيرفر"
|
||||||
"domains" = "الدومينات"
|
"domains" = "الدومينات"
|
||||||
"expectIPs" = "العناوين المتوقعة"
|
"expectIPs" = "العناوين المتوقعة"
|
||||||
|
"unexpectIPs" = "عناوين IP غير متوقعة"
|
||||||
|
"useSystemHosts" = "استخدام ملف Hosts الخاص بالنظام"
|
||||||
|
"useSystemHostsDesc" = "استخدام ملف hosts من نظام مثبت"
|
||||||
|
"usePreset" = "استخدام النموذج"
|
||||||
|
"dnsPresetTitle" = "قوالب DNS"
|
||||||
|
"dnsPresetFamily" = "العائلي"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "أضف Fake DNS"
|
"add" = "أضف Fake DNS"
|
||||||
|
@ -590,6 +593,10 @@
|
||||||
"restartSuccess" = "✅ العملية نجحت!"
|
"restartSuccess" = "✅ العملية نجحت!"
|
||||||
"restartFailed" = "❗ حصل خطأ في العملية.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
"restartFailed" = "❗ حصل خطأ في العملية.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core مش شغال."
|
"xrayNotRunning" = "❗ Xray Core مش شغال."
|
||||||
|
"startDesc" = "عرض القائمة الرئيسية"
|
||||||
|
"helpDesc" = "مساعدة البوت"
|
||||||
|
"statusDesc" = "التحقق من حالة البوت"
|
||||||
|
"idDesc" = "عرض معرف Telegram الخاص بك"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 حمل المعالج {{ .Percent }}% عدى الحد المسموح ({{ .Threshold }}%)"
|
"cpuThreshold" = "🔴 حمل المعالج {{ .Percent }}% عدى الحد المسموح ({{ .Threshold }}%)"
|
||||||
|
|
|
@ -126,6 +126,7 @@
|
||||||
"totalData" = "Total Data"
|
"totalData" = "Total Data"
|
||||||
"sent" = "Sent"
|
"sent" = "Sent"
|
||||||
"received" = "Received"
|
"received" = "Received"
|
||||||
|
"documentation" = "Documentation"
|
||||||
"xraySwitchVersionDialog" = "Do you really want to change the Xray version?"
|
"xraySwitchVersionDialog" = "Do you really want to change the Xray version?"
|
||||||
"xraySwitchVersionDialogDesc" = "This will change the Xray version to #version#."
|
"xraySwitchVersionDialogDesc" = "This will change the Xray version to #version#."
|
||||||
"xraySwitchVersionPopover" = "Xray updated successfully"
|
"xraySwitchVersionPopover" = "Xray updated successfully"
|
||||||
|
@ -339,7 +340,7 @@
|
||||||
"subEnable" = "Enable Subscription Service"
|
"subEnable" = "Enable Subscription Service"
|
||||||
"subEnableDesc" = "Enables the subscription service."
|
"subEnableDesc" = "Enables the subscription service."
|
||||||
"subTitle" = "Subscription Title"
|
"subTitle" = "Subscription Title"
|
||||||
"subTitleDesc" = "Title shown in VPN client"
|
"subTitleDesc" = "Title shown in VPN client"
|
||||||
"subListen" = "Listen IP"
|
"subListen" = "Listen IP"
|
||||||
"subListenDesc" = "The IP address for the subscription service. (leave blank to listen on all IPs)"
|
"subListenDesc" = "The IP address for the subscription service. (leave blank to listen on all IPs)"
|
||||||
"subPort" = "Listen Port"
|
"subPort" = "Listen Port"
|
||||||
|
@ -398,7 +399,6 @@
|
||||||
"generalConfigsDesc" = "These options will determine general adjustments."
|
"generalConfigsDesc" = "These options will determine general adjustments."
|
||||||
"logConfigs" = "Log"
|
"logConfigs" = "Log"
|
||||||
"logConfigsDesc" = "Logs may affect your server's efficiency. It is recommended to enable it wisely only in case of your needs"
|
"logConfigsDesc" = "Logs may affect your server's efficiency. It is recommended to enable it wisely only in case of your needs"
|
||||||
"blockConfigs" = "Protection Shield"
|
|
||||||
"blockConfigsDesc" = "These options will block traffic based on specific requested protocols and websites."
|
"blockConfigsDesc" = "These options will block traffic based on specific requested protocols and websites."
|
||||||
"basicRouting" = "Basic Routing"
|
"basicRouting" = "Basic Routing"
|
||||||
"blockConnectionsConfigsDesc" = "These options will block traffic based on the specific requested country."
|
"blockConnectionsConfigsDesc" = "These options will block traffic based on the specific requested country."
|
||||||
|
@ -418,9 +418,6 @@
|
||||||
"RoutingStrategy" = "Overall Routing Strategy"
|
"RoutingStrategy" = "Overall Routing Strategy"
|
||||||
"RoutingStrategyDesc" = "Set the overall traffic routing strategy for resolving all requests."
|
"RoutingStrategyDesc" = "Set the overall traffic routing strategy for resolving all requests."
|
||||||
"Torrent" = "Block BitTorrent Protocol"
|
"Torrent" = "Block BitTorrent Protocol"
|
||||||
"TorrentDesc" = "Blocks BitTorrent protocol."
|
|
||||||
"Family" = "Family Protection"
|
|
||||||
"FamilyDesc" = "Blocks adult content, and malware websites."
|
|
||||||
"Inbounds" = "Inbounds"
|
"Inbounds" = "Inbounds"
|
||||||
"InboundsDesc" = "Accepting the specific clients."
|
"InboundsDesc" = "Accepting the specific clients."
|
||||||
"Outbounds" = "Outbounds"
|
"Outbounds" = "Outbounds"
|
||||||
|
@ -520,6 +517,12 @@
|
||||||
"edit" = "Edit Server"
|
"edit" = "Edit Server"
|
||||||
"domains" = "Domains"
|
"domains" = "Domains"
|
||||||
"expectIPs" = "Expect IPs"
|
"expectIPs" = "Expect IPs"
|
||||||
|
"unexpectIPs" = "Unexpect IPs"
|
||||||
|
"useSystemHosts" = "Use System Hosts"
|
||||||
|
"useSystemHostsDesc" = "Use the hosts file from an installed system"
|
||||||
|
"usePreset" = "Use Preset"
|
||||||
|
"dnsPresetTitle" = "DNS Presets"
|
||||||
|
"dnsPresetFamily" = "Family"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Add Fake DNS"
|
"add" = "Add Fake DNS"
|
||||||
|
@ -589,6 +592,10 @@
|
||||||
"restartSuccess" = "✅ Operation successful!"
|
"restartSuccess" = "✅ Operation successful!"
|
||||||
"restartFailed" = "❗ Error in operation.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
"restartFailed" = "❗ Error in operation.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core is not running."
|
"xrayNotRunning" = "❗ Xray Core is not running."
|
||||||
|
"startDesc" = "Show the main menu"
|
||||||
|
"helpDesc" = "Bot help"
|
||||||
|
"statusDesc" = "Check bot status"
|
||||||
|
"idDesc" = "Show your Telegram ID"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 CPU Load {{ .Percent }}% exceeds the threshold of {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 CPU Load {{ .Percent }}% exceeds the threshold of {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Datos totales"
|
"totalData" = "Datos totales"
|
||||||
"sent" = "Enviado"
|
"sent" = "Enviado"
|
||||||
"received" = "Recibido"
|
"received" = "Recibido"
|
||||||
|
"documentation" = "Documentación"
|
||||||
"xraySwitchVersionDialog" = "¿Realmente deseas cambiar la versión de Xray?"
|
"xraySwitchVersionDialog" = "¿Realmente deseas cambiar la versión de Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Esto cambiará la versión de Xray a #version#."
|
"xraySwitchVersionDialogDesc" = "Esto cambiará la versión de Xray a #version#."
|
||||||
"xraySwitchVersionPopover" = "Xray se actualizó correctamente"
|
"xraySwitchVersionPopover" = "Xray se actualizó correctamente"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "Estas opciones proporcionarán ajustes generales."
|
"generalConfigsDesc" = "Estas opciones proporcionarán ajustes generales."
|
||||||
"logConfigs" = "Registro"
|
"logConfigs" = "Registro"
|
||||||
"logConfigsDesc" = "Los registros pueden afectar la eficiencia de su servidor. Se recomienda habilitarlos sabiamente solo en caso de sus necesidades."
|
"logConfigsDesc" = "Los registros pueden afectar la eficiencia de su servidor. Se recomienda habilitarlos sabiamente solo en caso de sus necesidades."
|
||||||
"blockConfigs" = "Configuraciones de Bloqueo"
|
|
||||||
"blockConfigsDesc" = "Estas opciones evitarán que los usuarios se conecten a protocolos y sitios web específicos."
|
"blockConfigsDesc" = "Estas opciones evitarán que los usuarios se conecten a protocolos y sitios web específicos."
|
||||||
"basicRouting" = "Enrutamiento Básico"
|
"basicRouting" = "Enrutamiento Básico"
|
||||||
"blockConnectionsConfigsDesc" = "Estas opciones bloquearán el tráfico según el país solicitado específico."
|
"blockConnectionsConfigsDesc" = "Estas opciones bloquearán el tráfico según el país solicitado específico."
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "Configurar Estrategia de Enrutamiento de Dominios"
|
"RoutingStrategy" = "Configurar Estrategia de Enrutamiento de Dominios"
|
||||||
"RoutingStrategyDesc" = "Establece la estrategia general de enrutamiento para la resolución de DNS."
|
"RoutingStrategyDesc" = "Establece la estrategia general de enrutamiento para la resolución de DNS."
|
||||||
"Torrent" = "Prohibir Uso de BitTorrent"
|
"Torrent" = "Prohibir Uso de BitTorrent"
|
||||||
"TorrentDesc" = "Cambia la plantilla de configuración para evitar el uso de BitTorrent por parte de los usuarios."
|
|
||||||
"Family" = "Bloquee malware y contenido para adultos"
|
|
||||||
"FamilyDesc" = "Resolutores de DNS de Cloudflare para bloquear malware y contenido para adultos para protección familiar."
|
|
||||||
"Inbounds" = "Entrante"
|
"Inbounds" = "Entrante"
|
||||||
"InboundsDesc" = "Cambia la plantilla de configuración para aceptar clientes específicos."
|
"InboundsDesc" = "Cambia la plantilla de configuración para aceptar clientes específicos."
|
||||||
"Outbounds" = "Salidas"
|
"Outbounds" = "Salidas"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "Editar Servidor"
|
"edit" = "Editar Servidor"
|
||||||
"domains" = "Dominios"
|
"domains" = "Dominios"
|
||||||
"expectIPs" = "IPs esperadas"
|
"expectIPs" = "IPs esperadas"
|
||||||
|
"unexpectIPs" = "IPs inesperadas"
|
||||||
|
"useSystemHosts" = "Usar Hosts del sistema"
|
||||||
|
"useSystemHostsDesc" = "Usar el archivo hosts de un sistema instalado"
|
||||||
|
"usePreset" = "Usar plantilla"
|
||||||
|
"dnsPresetTitle" = "Plantillas DNS"
|
||||||
|
"dnsPresetFamily" = "Familiar"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Agregar DNS Falso"
|
"add" = "Agregar DNS Falso"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ ¡Operación exitosa!"
|
"restartSuccess" = "✅ ¡Operación exitosa!"
|
||||||
"restartFailed" = "❗ Error en la operación.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
"restartFailed" = "❗ Error en la operación.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core no está en ejecución."
|
"xrayNotRunning" = "❗ Xray Core no está en ejecución."
|
||||||
|
"startDesc" = "Mostrar el menú principal"
|
||||||
|
"helpDesc" = "Ayuda del bot"
|
||||||
|
"statusDesc" = "Comprobar el estado del bot"
|
||||||
|
"idDesc" = "Mostrar tu ID de Telegram"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 El uso de CPU {{ .Percent }}% es mayor que el umbral {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 El uso de CPU {{ .Percent }}% es mayor que el umbral {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "دادههای کل"
|
"totalData" = "دادههای کل"
|
||||||
"sent" = "ارسال شده"
|
"sent" = "ارسال شده"
|
||||||
"received" = "دریافت شده"
|
"received" = "دریافت شده"
|
||||||
|
"documentation" = "مستندات"
|
||||||
"xraySwitchVersionDialog" = "آیا واقعاً میخواهید نسخه Xray را تغییر دهید؟"
|
"xraySwitchVersionDialog" = "آیا واقعاً میخواهید نسخه Xray را تغییر دهید؟"
|
||||||
"xraySwitchVersionDialogDesc" = "این کار نسخه Xray را به #version# تغییر میدهد."
|
"xraySwitchVersionDialogDesc" = "این کار نسخه Xray را به #version# تغییر میدهد."
|
||||||
"xraySwitchVersionPopover" = "Xray با موفقیت بهروز شد"
|
"xraySwitchVersionPopover" = "Xray با موفقیت بهروز شد"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "این گزینهها استراتژی کلی ترافیک را تعیین میکنند"
|
"generalConfigsDesc" = "این گزینهها استراتژی کلی ترافیک را تعیین میکنند"
|
||||||
"logConfigs" = "گزارش"
|
"logConfigs" = "گزارش"
|
||||||
"logConfigsDesc" = "گزارشها ممکن است بر کارایی سرور شما تأثیر بگذارد. توصیه می شود فقط در صورت نیاز آن را عاقلانه فعال کنید"
|
"logConfigsDesc" = "گزارشها ممکن است بر کارایی سرور شما تأثیر بگذارد. توصیه می شود فقط در صورت نیاز آن را عاقلانه فعال کنید"
|
||||||
"blockConfigs" = "سپر محافظ"
|
|
||||||
"blockConfigsDesc" = "این گزینهها ترافیک را بر اساس پروتکلهای درخواستی خاص، و وب سایتها مسدود میکند"
|
"blockConfigsDesc" = "این گزینهها ترافیک را بر اساس پروتکلهای درخواستی خاص، و وب سایتها مسدود میکند"
|
||||||
"basicRouting" = "مسیریابی پایه"
|
"basicRouting" = "مسیریابی پایه"
|
||||||
"blockConnectionsConfigsDesc" = "این گزینهها ترافیک را بر اساس کشور درخواستشده خاص مسدود میکنند."
|
"blockConnectionsConfigsDesc" = "این گزینهها ترافیک را بر اساس کشور درخواستشده خاص مسدود میکنند."
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "استراتژی کلی مسیریابی"
|
"RoutingStrategy" = "استراتژی کلی مسیریابی"
|
||||||
"RoutingStrategyDesc" = "استراتژی کلی مسیریابی برای حل تمام درخواستها را تعیین میکند"
|
"RoutingStrategyDesc" = "استراتژی کلی مسیریابی برای حل تمام درخواستها را تعیین میکند"
|
||||||
"Torrent" = "مسدودسازی پروتکل بیتتورنت"
|
"Torrent" = "مسدودسازی پروتکل بیتتورنت"
|
||||||
"TorrentDesc" = "پروتکل بیت تورنت را مسدود میکند"
|
|
||||||
"Family" = "محافظت خانواده"
|
|
||||||
"FamilyDesc" = "محتوای مخصوص بزرگسالان، و وبسایتهای ناامن را مسدود میکند"
|
|
||||||
"Inbounds" = "ورودیها"
|
"Inbounds" = "ورودیها"
|
||||||
"InboundsDesc" = "پذیرش کلاینت خاص"
|
"InboundsDesc" = "پذیرش کلاینت خاص"
|
||||||
"Outbounds" = "خروجیها"
|
"Outbounds" = "خروجیها"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "ویرایش سرور"
|
"edit" = "ویرایش سرور"
|
||||||
"domains" = "دامنهها"
|
"domains" = "دامنهها"
|
||||||
"expectIPs" = "آیپیهای مورد انتظار"
|
"expectIPs" = "آیپیهای مورد انتظار"
|
||||||
|
"unexpectIPs" = "آیپیهای غیرمنتظره"
|
||||||
|
"useSystemHosts" = "استفاده از Hosts سیستم"
|
||||||
|
"useSystemHostsDesc" = "استفاده از فایل hosts یک سیستم نصبشده"
|
||||||
|
"usePreset" = "استفاده از پیشتنظیم"
|
||||||
|
"dnsPresetTitle" = "پیشتنظیمهای DNS"
|
||||||
|
"dnsPresetFamily" = "خانوادگی"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "افزودن دیاناس جعلی"
|
"add" = "افزودن دیاناس جعلی"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ عملیات با موفقیت انجام شد!"
|
"restartSuccess" = "✅ عملیات با موفقیت انجام شد!"
|
||||||
"restartFailed" = "❗ خطا در عملیات.\r\n\r\n<code>خطا: {{ .Error }}</code>."
|
"restartFailed" = "❗ خطا در عملیات.\r\n\r\n<code>خطا: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core در حال اجرا نیست."
|
"xrayNotRunning" = "❗ Xray Core در حال اجرا نیست."
|
||||||
|
"startDesc" = "نمایش منوی اصلی"
|
||||||
|
"helpDesc" = "راهنمای ربات"
|
||||||
|
"statusDesc" = "بررسی وضعیت ربات"
|
||||||
|
"idDesc" = "نمایش شناسه تلگرام شما"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 بار پردازنده {{ .Percent }}% بیشتر از آستانه است {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 بار پردازنده {{ .Percent }}% بیشتر از آستانه است {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Total data"
|
"totalData" = "Total data"
|
||||||
"sent" = "Dikirim"
|
"sent" = "Dikirim"
|
||||||
"received" = "Diterima"
|
"received" = "Diterima"
|
||||||
|
"documentation" = "Dokumentasi"
|
||||||
"xraySwitchVersionDialog" = "Apakah Anda yakin ingin mengubah versi Xray?"
|
"xraySwitchVersionDialog" = "Apakah Anda yakin ingin mengubah versi Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Ini akan mengubah versi Xray ke #version#."
|
"xraySwitchVersionDialogDesc" = "Ini akan mengubah versi Xray ke #version#."
|
||||||
"xraySwitchVersionPopover" = "Xray berhasil diperbarui"
|
"xraySwitchVersionPopover" = "Xray berhasil diperbarui"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "Opsi ini akan menentukan penyesuaian strategi umum."
|
"generalConfigsDesc" = "Opsi ini akan menentukan penyesuaian strategi umum."
|
||||||
"logConfigs" = "Catatan"
|
"logConfigs" = "Catatan"
|
||||||
"logConfigsDesc" = "Log dapat mempengaruhi efisiensi server Anda. Disarankan untuk mengaktifkannya dengan bijak hanya jika diperlukan"
|
"logConfigsDesc" = "Log dapat mempengaruhi efisiensi server Anda. Disarankan untuk mengaktifkannya dengan bijak hanya jika diperlukan"
|
||||||
"blockConfigs" = "Pelindung"
|
|
||||||
"blockConfigsDesc" = "Opsi ini akan memblokir lalu lintas berdasarkan protokol dan situs web yang diminta."
|
"blockConfigsDesc" = "Opsi ini akan memblokir lalu lintas berdasarkan protokol dan situs web yang diminta."
|
||||||
"basicRouting" = "Perutean Dasar"
|
"basicRouting" = "Perutean Dasar"
|
||||||
"blockConnectionsConfigsDesc" = "Opsi ini akan memblokir lalu lintas berdasarkan negara yang diminta."
|
"blockConnectionsConfigsDesc" = "Opsi ini akan memblokir lalu lintas berdasarkan negara yang diminta."
|
||||||
|
@ -422,8 +422,6 @@
|
||||||
"RoutingStrategyDesc" = "Atur strategi pengalihan lalu lintas keseluruhan untuk menyelesaikan semua permintaan."
|
"RoutingStrategyDesc" = "Atur strategi pengalihan lalu lintas keseluruhan untuk menyelesaikan semua permintaan."
|
||||||
"Torrent" = "Blokir Protokol BitTorrent"
|
"Torrent" = "Blokir Protokol BitTorrent"
|
||||||
"TorrentDesc" = "Memblokir protokol BitTorrent."
|
"TorrentDesc" = "Memblokir protokol BitTorrent."
|
||||||
"Family" = "Proteksi Keluarga"
|
|
||||||
"FamilyDesc" = "Memblokir konten dewasa dan situs web berbahaya."
|
|
||||||
"Inbounds" = "Masuk"
|
"Inbounds" = "Masuk"
|
||||||
"InboundsDesc" = "Menerima klien tertentu."
|
"InboundsDesc" = "Menerima klien tertentu."
|
||||||
"Outbounds" = "Keluar"
|
"Outbounds" = "Keluar"
|
||||||
|
@ -523,6 +521,12 @@
|
||||||
"edit" = "Sunting Server"
|
"edit" = "Sunting Server"
|
||||||
"domains" = "Domains"
|
"domains" = "Domains"
|
||||||
"expectIPs" = "IP yang Diharapkan"
|
"expectIPs" = "IP yang Diharapkan"
|
||||||
|
"unexpectIPs" = "IP tak terduga"
|
||||||
|
"useSystemHosts" = "Gunakan Hosts Sistem"
|
||||||
|
"useSystemHostsDesc" = "Gunakan file hosts dari sistem yang terinstal"
|
||||||
|
"usePreset" = "Gunakan templat"
|
||||||
|
"dnsPresetTitle" = "Templat DNS"
|
||||||
|
"dnsPresetFamily" = "Keluarga"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Tambahkan DNS Palsu"
|
"add" = "Tambahkan DNS Palsu"
|
||||||
|
@ -592,6 +596,10 @@
|
||||||
"restartSuccess" = "✅ Operasi berhasil!"
|
"restartSuccess" = "✅ Operasi berhasil!"
|
||||||
"restartFailed" = "❗ Kesalahan dalam operasi.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
"restartFailed" = "❗ Kesalahan dalam operasi.\r\n\r\n<code>Error: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core tidak berjalan."
|
"xrayNotRunning" = "❗ Xray Core tidak berjalan."
|
||||||
|
"startDesc" = "Tampilkan menu utama"
|
||||||
|
"helpDesc" = "Bantuan bot"
|
||||||
|
"statusDesc" = "Periksa status bot"
|
||||||
|
"idDesc" = "Tampilkan ID Telegram Anda"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 Beban CPU {{ .Percent }}% melebihi batas {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 Beban CPU {{ .Percent }}% melebihi batas {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "総データ量"
|
"totalData" = "総データ量"
|
||||||
"sent" = "送信"
|
"sent" = "送信"
|
||||||
"received" = "受信"
|
"received" = "受信"
|
||||||
|
"documentation" = "ドキュメント"
|
||||||
"xraySwitchVersionDialog" = "Xrayのバージョンを本当に変更しますか?"
|
"xraySwitchVersionDialog" = "Xrayのバージョンを本当に変更しますか?"
|
||||||
"xraySwitchVersionDialogDesc" = "Xrayのバージョンが#version#に変更されます。"
|
"xraySwitchVersionDialogDesc" = "Xrayのバージョンが#version#に変更されます。"
|
||||||
"xraySwitchVersionPopover" = "Xrayの更新が成功しました"
|
"xraySwitchVersionPopover" = "Xrayの更新が成功しました"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "これらのオプションは一般設定を決定します"
|
"generalConfigsDesc" = "これらのオプションは一般設定を決定します"
|
||||||
"logConfigs" = "ログ"
|
"logConfigs" = "ログ"
|
||||||
"logConfigsDesc" = "ログはサーバーのパフォーマンスに影響を与える可能性があるため、必要な場合にのみ有効にすることをお勧めします"
|
"logConfigsDesc" = "ログはサーバーのパフォーマンスに影響を与える可能性があるため、必要な場合にのみ有効にすることをお勧めします"
|
||||||
"blockConfigs" = "防御フィルター"
|
|
||||||
"blockConfigsDesc" = "これらのオプションは、特定のプロトコルやウェブサイトへのユーザー接続をブロックします"
|
"blockConfigsDesc" = "これらのオプションは、特定のプロトコルやウェブサイトへのユーザー接続をブロックします"
|
||||||
"basicRouting" = "基本ルーティング"
|
"basicRouting" = "基本ルーティング"
|
||||||
"blockConnectionsConfigsDesc" = "これらのオプションにより、特定のリクエスト元の国に基づいてトラフィックをブロックします。"
|
"blockConnectionsConfigsDesc" = "これらのオプションにより、特定のリクエスト元の国に基づいてトラフィックをブロックします。"
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "ルーティングドメイン戦略設定"
|
"RoutingStrategy" = "ルーティングドメイン戦略設定"
|
||||||
"RoutingStrategyDesc" = "DNS解決の全体的なルーティング戦略を設定する"
|
"RoutingStrategyDesc" = "DNS解決の全体的なルーティング戦略を設定する"
|
||||||
"Torrent" = "BitTorrent プロトコルをブロック"
|
"Torrent" = "BitTorrent プロトコルをブロック"
|
||||||
"TorrentDesc" = "BitTorrentの使用を禁止する"
|
|
||||||
"Family" = "ファミリー保護"
|
|
||||||
"FamilyDesc" = "アダルトコンテンツや悪意のあるサイトをブロックする"
|
|
||||||
"Inbounds" = "インバウンドルール"
|
"Inbounds" = "インバウンドルール"
|
||||||
"InboundsDesc" = "特定のクライアントからのトラフィックを受け入れる"
|
"InboundsDesc" = "特定のクライアントからのトラフィックを受け入れる"
|
||||||
"Outbounds" = "アウトバウンドルール"
|
"Outbounds" = "アウトバウンドルール"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "サーバー編集"
|
"edit" = "サーバー編集"
|
||||||
"domains" = "ドメイン"
|
"domains" = "ドメイン"
|
||||||
"expectIPs" = "期待されるIP"
|
"expectIPs" = "期待されるIP"
|
||||||
|
"unexpectIPs" = "予期しないIP"
|
||||||
|
"useSystemHosts" = "システムのHostsを使用"
|
||||||
|
"useSystemHostsDesc" = "インストール済みシステムのhostsファイルを使用する"
|
||||||
|
"usePreset" = "テンプレートを使用"
|
||||||
|
"dnsPresetTitle" = "DNSテンプレート"
|
||||||
|
"dnsPresetFamily" = "ファミリー"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "フェイクDNS追加"
|
"add" = "フェイクDNS追加"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ 操作成功!"
|
"restartSuccess" = "✅ 操作成功!"
|
||||||
"restartFailed" = "❗ 操作エラー。\r\n\r\n<code>エラー: {{ .Error }}</code>"
|
"restartFailed" = "❗ 操作エラー。\r\n\r\n<code>エラー: {{ .Error }}</code>"
|
||||||
"xrayNotRunning" = "❗ Xray Core は動作していません。"
|
"xrayNotRunning" = "❗ Xray Core は動作していません。"
|
||||||
|
"startDesc" = "メインメニューを表示"
|
||||||
|
"helpDesc" = "ボットのヘルプ"
|
||||||
|
"statusDesc" = "ボットの状態を確認"
|
||||||
|
"idDesc" = "Telegram IDを表示"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 CPU使用率は{{ .Percent }}%、しきい値{{ .Threshold }}%を超えました"
|
"cpuThreshold" = "🔴 CPU使用率は{{ .Percent }}%、しきい値{{ .Threshold }}%を超えました"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Dados totais"
|
"totalData" = "Dados totais"
|
||||||
"sent" = "Enviado"
|
"sent" = "Enviado"
|
||||||
"received" = "Recebido"
|
"received" = "Recebido"
|
||||||
|
"documentation" = "Documentação"
|
||||||
"xraySwitchVersionDialog" = "Você realmente deseja alterar a versão do Xray?"
|
"xraySwitchVersionDialog" = "Você realmente deseja alterar a versão do Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Isso mudará a versão do Xray para #version#."
|
"xraySwitchVersionDialogDesc" = "Isso mudará a versão do Xray para #version#."
|
||||||
"xraySwitchVersionPopover" = "Xray atualizado com sucesso"
|
"xraySwitchVersionPopover" = "Xray atualizado com sucesso"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "Essas opções determinam ajustes gerais."
|
"generalConfigsDesc" = "Essas opções determinam ajustes gerais."
|
||||||
"logConfigs" = "Log"
|
"logConfigs" = "Log"
|
||||||
"logConfigsDesc" = "Os logs podem afetar a eficiência do servidor. É recomendável habilitá-los com sabedoria apenas se necessário."
|
"logConfigsDesc" = "Os logs podem afetar a eficiência do servidor. É recomendável habilitá-los com sabedoria apenas se necessário."
|
||||||
"blockConfigs" = "Escudo de Proteção"
|
|
||||||
"blockConfigsDesc" = "Essas opções bloqueiam tráfego com base em protocolos e sites específicos solicitados."
|
"blockConfigsDesc" = "Essas opções bloqueiam tráfego com base em protocolos e sites específicos solicitados."
|
||||||
"basicRouting" = "Roteamento Básico"
|
"basicRouting" = "Roteamento Básico"
|
||||||
"blockConnectionsConfigsDesc" = "Essas opções bloquearão o tráfego com base no país solicitado."
|
"blockConnectionsConfigsDesc" = "Essas opções bloquearão o tráfego com base no país solicitado."
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "Estratégia Geral de Roteamento"
|
"RoutingStrategy" = "Estratégia Geral de Roteamento"
|
||||||
"RoutingStrategyDesc" = "Definir a estratégia geral de roteamento de tráfego para resolver todas as solicitações."
|
"RoutingStrategyDesc" = "Definir a estratégia geral de roteamento de tráfego para resolver todas as solicitações."
|
||||||
"Torrent" = "Bloquear Protocolo BitTorrent"
|
"Torrent" = "Bloquear Protocolo BitTorrent"
|
||||||
"TorrentDesc" = "Bloqueia o protocolo BitTorrent."
|
|
||||||
"Family" = "Proteção Familiar"
|
|
||||||
"FamilyDesc" = "Bloqueia conteúdo adulto e sites maliciosos."
|
|
||||||
"Inbounds" = "Inbounds"
|
"Inbounds" = "Inbounds"
|
||||||
"InboundsDesc" = "Aceitar clientes específicos."
|
"InboundsDesc" = "Aceitar clientes específicos."
|
||||||
"Outbounds" = "Outbounds"
|
"Outbounds" = "Outbounds"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "Editar Servidor"
|
"edit" = "Editar Servidor"
|
||||||
"domains" = "Domínios"
|
"domains" = "Domínios"
|
||||||
"expectIPs" = "IPs Esperadas"
|
"expectIPs" = "IPs Esperadas"
|
||||||
|
"unexpectIPs" = "IPs inesperados"
|
||||||
|
"useSystemHosts" = "Usar Hosts do sistema"
|
||||||
|
"useSystemHostsDesc" = "Usar o arquivo hosts de um sistema instalado"
|
||||||
|
"usePreset" = "Usar modelo"
|
||||||
|
"dnsPresetTitle" = "Modelos DNS"
|
||||||
|
"dnsPresetFamily" = "Familiar"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Adicionar Fake DNS"
|
"add" = "Adicionar Fake DNS"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ Operação bem-sucedida!"
|
"restartSuccess" = "✅ Operação bem-sucedida!"
|
||||||
"restartFailed" = "❗ Erro na operação.\r\n\r\n<code>Erro: {{ .Error }}</code>."
|
"restartFailed" = "❗ Erro na operação.\r\n\r\n<code>Erro: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core não está em execução."
|
"xrayNotRunning" = "❗ Xray Core não está em execução."
|
||||||
|
"startDesc" = "Mostrar menu principal"
|
||||||
|
"helpDesc" = "Ajuda do bot"
|
||||||
|
"statusDesc" = "Verificar status do bot"
|
||||||
|
"idDesc" = "Mostrar seu ID do Telegram"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 A carga da CPU {{ .Percent }}% excede o limite de {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 A carga da CPU {{ .Percent }}% excede o limite de {{ .Threshold }}%"
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
"sure" = "Да"
|
"sure" = "Да"
|
||||||
"encryption" = "Шифрование"
|
"encryption" = "Шифрование"
|
||||||
"useIPv4ForHost" = "Использовать IPv4 для хоста"
|
"useIPv4ForHost" = "Использовать IPv4 для хоста"
|
||||||
"transmission" = "Протокол"
|
"transmission" = "Транспорт"
|
||||||
"host" = "Хост"
|
"host" = "Хост"
|
||||||
"path" = "Путь"
|
"path" = "Путь"
|
||||||
"camouflage" = "Маскировка"
|
"camouflage" = "Маскировка"
|
||||||
|
@ -59,24 +59,24 @@
|
||||||
"security" = "Безопасность"
|
"security" = "Безопасность"
|
||||||
"secAlertTitle" = "Предупреждение системы безопасности"
|
"secAlertTitle" = "Предупреждение системы безопасности"
|
||||||
"secAlertSsl" = "Это соединение не защищено. Пожалуйста, не вводите конфиденциальную информацию, пока не установите SSL сертификат для защиты соединения"
|
"secAlertSsl" = "Это соединение не защищено. Пожалуйста, не вводите конфиденциальную информацию, пока не установите SSL сертификат для защиты соединения"
|
||||||
"secAlertConf" = "Некоторые настройки уязвимы для атак. Рекомендуем усилить протоколы безопасности, чтобы предотвратить проблемы в будущем."
|
"secAlertConf" = "Некоторые настройки уязвимы для атак. Чтобы в будущем не было проблем, нужно усилить защиту."
|
||||||
"secAlertSSL" = "Ваше подключение к панели небезопасно. Пожалуйста, установите SSL сертификат для защиты данных."
|
"secAlertSSL" = "Ваше подключение к панели не защищено. Установите SSL сертификат для защиты данных."
|
||||||
"secAlertPanelPort" = "Порт, на котором работает панель небезопасен. Пожалуйста, установите случайный или просто другой порт."
|
"secAlertPanelPort" = "Порт панели по умолчанию небезопасен. Установите случайный или просто другой порт."
|
||||||
"secAlertPanelURI" = "URI-адрес панели по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
"secAlertPanelURI" = "Адрес панели по умолчанию небезопасен. Сделайте адрес сложным."
|
||||||
"secAlertSubURI" = "URI-адрес подписки по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
"secAlertSubURI" = "URI-адрес подписки по умолчанию небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
||||||
"secAlertSubJsonURI" = "URI-адрес по умолчанию для JSON подписки небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
"secAlertSubJsonURI" = "URI-адрес по умолчанию для JSON подписки небезопасен. Пожалуйста, настройте сложный URI-адрес."
|
||||||
"emptyDnsDesc" = "Нет добавленных DNS-серверов."
|
"emptyDnsDesc" = "Нет добавленных DNS-серверов."
|
||||||
"emptyFakeDnsDesc" = "Нет добавленных Fake DNS-серверов."
|
"emptyFakeDnsDesc" = "Нет добавленных Fake DNS-серверов."
|
||||||
"emptyBalancersDesc" = "Нет добавленных балансировщиков."
|
"emptyBalancersDesc" = "Нет добавленных балансировщиков."
|
||||||
"emptyReverseDesc" = "Нет добавленных обратных прокси."
|
"emptyReverseDesc" = "Нет добавленных реверс-прокси."
|
||||||
"somethingWentWrong" = "Что-то пошло не так"
|
"somethingWentWrong" = "Что-то пошло не так"
|
||||||
|
|
||||||
[menu]
|
[menu]
|
||||||
"theme" = "Тема"
|
"theme" = "Тема"
|
||||||
"dark" = "Темная"
|
"dark" = "Темная"
|
||||||
"ultraDark" = "Очень темная"
|
"ultraDark" = "Очень темная"
|
||||||
"dashboard" = "Статус системы"
|
"dashboard" = "Дашборд"
|
||||||
"inbounds" = "Входящие подключения"
|
"inbounds" = "Инбаунды"
|
||||||
"settings" = "Настройки"
|
"settings" = "Настройки"
|
||||||
"xray" = "Настройки Xray"
|
"xray" = "Настройки Xray"
|
||||||
"logout" = "Выход"
|
"logout" = "Выход"
|
||||||
|
@ -91,15 +91,15 @@
|
||||||
"invalidFormData" = "Недопустимый формат данных"
|
"invalidFormData" = "Недопустимый формат данных"
|
||||||
"emptyUsername" = "Введите имя пользователя"
|
"emptyUsername" = "Введите имя пользователя"
|
||||||
"emptyPassword" = "Введите пароль"
|
"emptyPassword" = "Введите пароль"
|
||||||
"wrongUsernameOrPassword" = "Неверное имя пользователя, пароль или код двухфакторной аутентификации."
|
"wrongUsernameOrPassword" = "Неверные данные учетной записи."
|
||||||
"successLogin" = "Успешный вход"
|
"successLogin" = "Вы успешно вошли в аккаунт"
|
||||||
|
|
||||||
[pages.index]
|
[pages.index]
|
||||||
"title" = "Статус системы"
|
"title" = "Дашборд"
|
||||||
"cpu" = "ЦП"
|
"cpu" = "ЦП"
|
||||||
"logicalProcessors" = "Логические процессоры"
|
"logicalProcessors" = "Логические процессоры"
|
||||||
"frequency" = "Частота"
|
"frequency" = "Частота"
|
||||||
"swap" = "Swap"
|
"swap" = "Файл подкачки"
|
||||||
"storage" = "Диск"
|
"storage" = "Диск"
|
||||||
"memory" = "ОЗУ"
|
"memory" = "ОЗУ"
|
||||||
"threads" = "Потоки"
|
"threads" = "Потоки"
|
||||||
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Общий объем трафика"
|
"totalData" = "Общий объем трафика"
|
||||||
"sent" = "Отправлено"
|
"sent" = "Отправлено"
|
||||||
"received" = "Получено"
|
"received" = "Получено"
|
||||||
|
"documentation" = "Документация"
|
||||||
"xraySwitchVersionDialog" = "Переключить версию Xray"
|
"xraySwitchVersionDialog" = "Переключить версию Xray"
|
||||||
"xraySwitchVersionDialogDesc" = "Вы точно хотите сменить версию Xray?"
|
"xraySwitchVersionDialogDesc" = "Вы точно хотите сменить версию Xray?"
|
||||||
"xraySwitchVersionPopover" = "Xray успешно обновлён"
|
"xraySwitchVersionPopover" = "Xray успешно обновлён"
|
||||||
|
@ -135,7 +136,7 @@
|
||||||
"geofileUpdateDialogDesc" = "Это обновит файл #filename#."
|
"geofileUpdateDialogDesc" = "Это обновит файл #filename#."
|
||||||
"geofileUpdatePopover" = "Геофайл успешно обновлён"
|
"geofileUpdatePopover" = "Геофайл успешно обновлён"
|
||||||
"dontRefresh" = "Установка в процессе. Не обновляйте страницу"
|
"dontRefresh" = "Установка в процессе. Не обновляйте страницу"
|
||||||
"logs" = "Логи"
|
"logs" = "Журнал"
|
||||||
"config" = "Конфигурация"
|
"config" = "Конфигурация"
|
||||||
"backup" = "Резервная копия"
|
"backup" = "Резервная копия"
|
||||||
"backupTitle" = "Резервная копия базы данных"
|
"backupTitle" = "Резервная копия базы данных"
|
||||||
|
@ -150,10 +151,10 @@
|
||||||
"getConfigError" = "Произошла ошибка при получении конфигурационного файла"
|
"getConfigError" = "Произошла ошибка при получении конфигурационного файла"
|
||||||
|
|
||||||
[pages.inbounds]
|
[pages.inbounds]
|
||||||
"title" = "Входящие подключения"
|
"title" = "Инбаунды"
|
||||||
"totalDownUp" = "Объем отправленного/полученного трафика"
|
"totalDownUp" = "Объем отправленного/полученного трафика"
|
||||||
"totalUsage" = "Всего трафика"
|
"totalUsage" = "Всего трафика"
|
||||||
"inboundCount" = "Всего подключений"
|
"inboundCount" = "Всего инбаундов"
|
||||||
"operate" = "Меню"
|
"operate" = "Меню"
|
||||||
"enable" = "Включить"
|
"enable" = "Включить"
|
||||||
"remark" = "Примечание"
|
"remark" = "Примечание"
|
||||||
|
@ -164,18 +165,18 @@
|
||||||
"transportConfig" = "Транспорт"
|
"transportConfig" = "Транспорт"
|
||||||
"expireDate" = "Дата окончания"
|
"expireDate" = "Дата окончания"
|
||||||
"resetTraffic" = "Сброс трафика"
|
"resetTraffic" = "Сброс трафика"
|
||||||
"addInbound" = "Создать новое подключение"
|
"addInbound" = "Создать инбаунд"
|
||||||
"generalActions" = "Общие действия"
|
"generalActions" = "Общие действия"
|
||||||
"autoRefresh" = "Автообновление"
|
"autoRefresh" = "Автообновление"
|
||||||
"autoRefreshInterval" = "Интервал"
|
"autoRefreshInterval" = "Интервал"
|
||||||
"modifyInbound" = "Изменить входящее подключение"
|
"modifyInbound" = "Изменить инбаунд"
|
||||||
"deleteInbound" = "Удалить входящее подключение"
|
"deleteInbound" = "Удалить инбаунд"
|
||||||
"deleteInboundContent" = "Вы уверены, что хотите удалить входящее подключение?"
|
"deleteInboundContent" = "Вы уверены, что хотите удалить инбаунд?"
|
||||||
"deleteClient" = "Удалить клиента"
|
"deleteClient" = "Удалить клиента"
|
||||||
"deleteClientContent" = "Вы уверены, что хотите удалить клиента?"
|
"deleteClientContent" = "Вы уверены, что хотите удалить клиента?"
|
||||||
"resetTrafficContent" = "Вы уверены, что хотите сбросить трафик?"
|
"resetTrafficContent" = "Вы уверены, что хотите сбросить трафик?"
|
||||||
"inboundUpdateSuccess" = "Входящее подключение успешно обновлено."
|
"inboundUpdateSuccess" = "Инбаунд успешно обновлен."
|
||||||
"inboundCreateSuccess" = "Входящее подключение успешно создано."
|
"inboundCreateSuccess" = "Инбаунд успешно создан."
|
||||||
"copyLink" = "Копировать ссылку"
|
"copyLink" = "Копировать ссылку"
|
||||||
"address" = "Адрес"
|
"address" = "Адрес"
|
||||||
"network" = "Сеть"
|
"network" = "Сеть"
|
||||||
|
@ -195,11 +196,11 @@
|
||||||
"export" = "Экспорт ссылок"
|
"export" = "Экспорт ссылок"
|
||||||
"clone" = "Клонировать"
|
"clone" = "Клонировать"
|
||||||
"cloneInbound" = "Клонировать"
|
"cloneInbound" = "Клонировать"
|
||||||
"cloneInboundContent" = "Будут клонированы все настройки входящих подключений, кроме списка клиентов, порта и IP-адреса прослушивания"
|
"cloneInboundContent" = "Будут клонированы все настройки инбаундов, кроме списка клиентов, порта и IP-адреса прослушивания"
|
||||||
"cloneInboundOk" = "Клонировано"
|
"cloneInboundOk" = "Клонировано"
|
||||||
"resetAllTraffic" = "Сброс трафика всех подключений"
|
"resetAllTraffic" = "Сброс трафика всех инбаундов"
|
||||||
"resetAllTrafficTitle" = "Сброс трафика всех подключений"
|
"resetAllTrafficTitle" = "Сброс трафика всех инбаундов"
|
||||||
"resetAllTrafficContent" = "Вы уверены, что хотите сбросить трафик всех подключений?"
|
"resetAllTrafficContent" = "Вы уверены, что хотите сбросить трафик всех инбаундов?"
|
||||||
"resetInboundClientTraffics" = "Сброс трафика клиента"
|
"resetInboundClientTraffics" = "Сброс трафика клиента"
|
||||||
"resetInboundClientTrafficTitle" = "Сброс трафика клиентов"
|
"resetInboundClientTrafficTitle" = "Сброс трафика клиентов"
|
||||||
"resetInboundClientTrafficContent" = "Вы уверены, что хотите сбросить трафик для этих клиентов?"
|
"resetInboundClientTrafficContent" = "Вы уверены, что хотите сбросить трафик для этих клиентов?"
|
||||||
|
@ -221,10 +222,10 @@
|
||||||
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее'"
|
"subscriptionDesc" = "Вы можете найти свою ссылку подписки в разделе 'Подробнее'"
|
||||||
"info" = "Информация"
|
"info" = "Информация"
|
||||||
"same" = "Тот же"
|
"same" = "Тот же"
|
||||||
"inboundData" = "Данные подключений"
|
"inboundData" = "Данные инбаундов"
|
||||||
"exportInbound" = "Экспорт входящих подключений"
|
"exportInbound" = "Экспорт инбаундов"
|
||||||
"import" = "Импортировать"
|
"import" = "Импортировать"
|
||||||
"importInbound" = "Импорт входящих подключений"
|
"importInbound" = "Импорт инбаундов"
|
||||||
|
|
||||||
[pages.client]
|
[pages.client]
|
||||||
"add" = "Создать клиента"
|
"add" = "Создать клиента"
|
||||||
|
@ -248,13 +249,13 @@
|
||||||
"obtain" = "Получить"
|
"obtain" = "Получить"
|
||||||
"updateSuccess" = "Обновление прошло успешно"
|
"updateSuccess" = "Обновление прошло успешно"
|
||||||
"logCleanSuccess" = "Лог был очищен"
|
"logCleanSuccess" = "Лог был очищен"
|
||||||
"inboundsUpdateSuccess" = "Входящие подключения успешно обновлены"
|
"inboundsUpdateSuccess" = "Инбаунды успешно обновлены"
|
||||||
"inboundUpdateSuccess" = "Входящее подключение успешно обновлено"
|
"inboundUpdateSuccess" = "Инбаунд успешно обновлено"
|
||||||
"inboundCreateSuccess" = "Входящее подключение успешно создано"
|
"inboundCreateSuccess" = "Инбаунд успешно создано"
|
||||||
"inboundDeleteSuccess" = "Входящее подключение успешно удалено"
|
"inboundDeleteSuccess" = "Инбаунд успешно удалено"
|
||||||
"inboundClientAddSuccess" = "Клиент(ы) входящего подключения добавлен(ы)"
|
"inboundClientAddSuccess" = "Клиент(ы) инбаунда добавлен(ы)"
|
||||||
"inboundClientDeleteSuccess" = "Клиент входящего подключения удалён"
|
"inboundClientDeleteSuccess" = "Клиент инбаунда удалён"
|
||||||
"inboundClientUpdateSuccess" = "Клиент входящего подключения обновлён"
|
"inboundClientUpdateSuccess" = "Клиент инбаунда обновлён"
|
||||||
"delDepletedClientsSuccess" = "Все исчерпанные клиенты удалены"
|
"delDepletedClientsSuccess" = "Все исчерпанные клиенты удалены"
|
||||||
"resetAllClientTrafficSuccess" = "Весь трафик клиента сброшен"
|
"resetAllClientTrafficSuccess" = "Весь трафик клиента сброшен"
|
||||||
"resetAllTrafficSuccess" = "Весь трафик сброшен"
|
"resetAllTrafficSuccess" = "Весь трафик сброшен"
|
||||||
|
@ -280,15 +281,15 @@
|
||||||
[pages.settings]
|
[pages.settings]
|
||||||
"title" = "Настройки"
|
"title" = "Настройки"
|
||||||
"save" = "Сохранить"
|
"save" = "Сохранить"
|
||||||
"infoDesc" = "Каждое выполненное изменение необходимо сохранить. Пожалуйста, перезапустите панель, чтобы изменения вступили в силу"
|
"infoDesc" = "Каждое внесённое изменение должно быть сохранено. Пожалуйста, перезапустите панель, чтобы изменения вступили в силу."
|
||||||
"restartPanel" = "Перезапуск панели"
|
"restartPanel" = "Перезапуск панели"
|
||||||
"restartPanelDesc" = "Вы уверены, что хотите перезапустить панель? Подтвердите, и перезапуск произойдёт через 3 секунды. Если панель будет недоступна, проверьте лог сервера"
|
"restartPanelDesc" = "Вы уверены, что хотите перезапустить панель? Подтвердите, и перезапуск произойдёт через 3 секунды. Если панель будет недоступна, проверьте лог сервера"
|
||||||
"restartPanelSuccess" = "Панель успешно перезапущена"
|
"restartPanelSuccess" = "Панель успешно перезапущена"
|
||||||
"actions" = "Действия"
|
"actions" = "Действия"
|
||||||
"resetDefaultConfig" = "Восстановить настройки по умолчанию"
|
"resetDefaultConfig" = "Восстановить настройки по умолчанию"
|
||||||
"panelSettings" = "Настройки панели"
|
"panelSettings" = "Панель"
|
||||||
"securitySettings" = "Настройки безопасности"
|
"securitySettings" = "Учетная запись"
|
||||||
"TGBotSettings" = "Настройки Telegram бота"
|
"TGBotSettings" = "Telegram"
|
||||||
"panelListeningIP" = "IP-адрес для управления панелью"
|
"panelListeningIP" = "IP-адрес для управления панелью"
|
||||||
"panelListeningIPDesc" = "Оставьте пустым для подключения с любого IP"
|
"panelListeningIPDesc" = "Оставьте пустым для подключения с любого IP"
|
||||||
"panelListeningDomain" = "Домен панели"
|
"panelListeningDomain" = "Домен панели"
|
||||||
|
@ -302,7 +303,7 @@
|
||||||
"panelUrlPath" = "Корневой путь URL адреса панели"
|
"panelUrlPath" = "Корневой путь URL адреса панели"
|
||||||
"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться '/'"
|
"panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться '/'"
|
||||||
"pageSize" = "Размер нумерации страниц"
|
"pageSize" = "Размер нумерации страниц"
|
||||||
"pageSizeDesc" = "Определить размер страницы для таблицы входящих подключений. Установите 0, чтобы отключить"
|
"pageSizeDesc" = "Определить размер страницы для таблицы инбаундов. Установите 0, чтобы отключить"
|
||||||
"remarkModel" = "Модель примечания и символ разделения"
|
"remarkModel" = "Модель примечания и символ разделения"
|
||||||
"datepicker" = "Выбор даты"
|
"datepicker" = "Выбор даты"
|
||||||
"datepickerPlaceholder" = "Выберите дату"
|
"datepickerPlaceholder" = "Выберите дату"
|
||||||
|
@ -342,7 +343,7 @@
|
||||||
"subEnable" = "Включить подписку"
|
"subEnable" = "Включить подписку"
|
||||||
"subEnableDesc" = "Функция подписки с отдельной конфигурацией"
|
"subEnableDesc" = "Функция подписки с отдельной конфигурацией"
|
||||||
"subTitle" = "Заголовок подписки"
|
"subTitle" = "Заголовок подписки"
|
||||||
"subTitleDesc" = "Название подписки, которое видит клиент в VPN клиенте"
|
"subTitleDesc" = "Название подписки, которое видит клиент в VPN клиенте"
|
||||||
"subListen" = "Прослушивание IP"
|
"subListen" = "Прослушивание IP"
|
||||||
"subListenDesc" = "Оставьте пустым по умолчанию, чтобы отслеживать все IP-адреса"
|
"subListenDesc" = "Оставьте пустым по умолчанию, чтобы отслеживать все IP-адреса"
|
||||||
"subPort" = "Порт подписки"
|
"subPort" = "Порт подписки"
|
||||||
|
@ -390,19 +391,18 @@
|
||||||
[pages.xray]
|
[pages.xray]
|
||||||
"title" = "Настройки Xray"
|
"title" = "Настройки Xray"
|
||||||
"save" = "Сохранить"
|
"save" = "Сохранить"
|
||||||
"restart" = "Перезапустить Xray"
|
"restart" = "Перезапуск Xray"
|
||||||
"restartSuccess" = "Xray успешно перезапущен"
|
"restartSuccess" = "Xray успешно перезапущен"
|
||||||
"stopSuccess" = "Xray успешно остановлен"
|
"stopSuccess" = "Xray успешно остановлен"
|
||||||
"restartError" = "Произошла ошибка при перезапуске Xray."
|
"restartError" = "Произошла ошибка при перезапуске Xray."
|
||||||
"stopError" = "Произошла ошибка при остановке Xray."
|
"stopError" = "Произошла ошибка при остановке Xray."
|
||||||
"basicTemplate" = "Базовый шаблон"
|
"basicTemplate" = "Основное"
|
||||||
"advancedTemplate" = "Расширенный шаблон"
|
"advancedTemplate" = "Расширенный шаблон"
|
||||||
"generalConfigs" = "Основные настройки"
|
"generalConfigs" = "Основные настройки"
|
||||||
"generalConfigsDesc" = "Эти параметры описывают общие настройки"
|
"generalConfigsDesc" = "Эти параметры описывают общие настройки"
|
||||||
"logConfigs" = "Логи"
|
"logConfigs" = "Логи"
|
||||||
"logConfigsDesc" = "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!"
|
"logConfigsDesc" = "Логи могут замедлять работу сервера. Включайте только нужные вам виды логов при необходимости!"
|
||||||
"blockConfigs" = "Блокировка подключений"
|
"blockConfigsDesc" = "Настройте, чтобы клиенты не имели доступа к определенным протоколам"
|
||||||
"blockConfigsDesc" = "Настройте, чтобы клиенты не имели доступа к определенным протоколам и веб-сайтами"
|
|
||||||
"basicRouting" = "Базовые соединения"
|
"basicRouting" = "Базовые соединения"
|
||||||
"blockConnectionsConfigsDesc" = "Эти параметры будут блокировать трафик в зависимости от страны назначения."
|
"blockConnectionsConfigsDesc" = "Эти параметры будут блокировать трафик в зависимости от страны назначения."
|
||||||
"directConnectionsConfigsDesc" = "Прямое соединение означает, что определенный трафик не будет перенаправлен через другой сервер."
|
"directConnectionsConfigsDesc" = "Прямое соединение означает, что определенный трафик не будет перенаправлен через другой сервер."
|
||||||
|
@ -413,22 +413,19 @@
|
||||||
"ipv4Routing" = "Правила IPv4"
|
"ipv4Routing" = "Правила IPv4"
|
||||||
"ipv4RoutingDesc" = "Эти параметры позволят клиентам маршрутизироваться к целевым доменам только через IPv4"
|
"ipv4RoutingDesc" = "Эти параметры позволят клиентам маршрутизироваться к целевым доменам только через IPv4"
|
||||||
"warpRouting" = "Правила WARP"
|
"warpRouting" = "Правила WARP"
|
||||||
"warpRoutingDesc" = "Внимание: перед использованием этих параметров установите WARP в режиме прокси-сервера socks5 на свой сервер, следуя инструкциям на GitHub панели. WARP будет направлять трафик на веб-сайты через серверы Cloudflare"
|
"warpRoutingDesc" = " Эти опции будут направлять трафик в зависимости от конкретного пункта назначения через WARP."
|
||||||
"Template" = "Шаблон конфигурации Xray"
|
"Template" = "Шаблон конфигурации Xray"
|
||||||
"TemplateDesc" = "Создание файла конфигурации Xray на основе этого шаблона"
|
"TemplateDesc" = "На основе шаблона создаётся конфигурационный файл Xray."
|
||||||
"FreedomStrategy" = "Настройка стратегии протокола Freedom"
|
"FreedomStrategy" = "Настройка стратегии протокола Freedom"
|
||||||
"FreedomStrategyDesc" = "Установка стратегии вывода сети в протоколе Freedom"
|
"FreedomStrategyDesc" = "Установка стратегии вывода сети в протоколе Freedom"
|
||||||
"RoutingStrategy" = "Настройка маршрутизации доменов"
|
"RoutingStrategy" = "Настройка маршрутизации доменов"
|
||||||
"RoutingStrategyDesc" = "Установка общей стратегии маршрутизации разрешения DNS"
|
"RoutingStrategyDesc" = "Установка общей стратегии маршрутизации разрешения DNS"
|
||||||
"Torrent" = "Заблокировать BitTorrent"
|
"Torrent" = "Заблокировать BitTorrent"
|
||||||
"TorrentDesc" = "Запретить входящий/исходящий трафик, в котором фигурирует протокол BitTorrent"
|
"Inbounds" = "Инбаунды"
|
||||||
"Family" = "Семейный режим"
|
|
||||||
"FamilyDesc" = "Использовать DNS-сервера Cloudflare для блокировки вредоносного ПО и контента для взрослых в целях защиты семьи."
|
|
||||||
"Inbounds" = "Входящее соединение"
|
|
||||||
"InboundsDesc" = "Изменение шаблона конфигурации для подключения определенных клиентов"
|
"InboundsDesc" = "Изменение шаблона конфигурации для подключения определенных клиентов"
|
||||||
"Outbounds" = "Исходящее соединение"
|
"Outbounds" = "Аутбаунды"
|
||||||
"Balancers" = "Балансировщик"
|
"Balancers" = "Балансировщик"
|
||||||
"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить исходящие соединения для этого сервера"
|
"OutboundsDesc" = "Изменение шаблона конфигурации, чтобы определить аутбаунды для этого сервера"
|
||||||
"Routings" = "Маршрутизация"
|
"Routings" = "Маршрутизация"
|
||||||
"RoutingsDesc" = "Важен приоритет каждого правила!"
|
"RoutingsDesc" = "Важен приоритет каждого правила!"
|
||||||
"completeTemplate" = "Все"
|
"completeTemplate" = "Все"
|
||||||
|
@ -459,8 +456,8 @@
|
||||||
"down" = "Опустить вниз"
|
"down" = "Опустить вниз"
|
||||||
"source" = "Источник"
|
"source" = "Источник"
|
||||||
"dest" = "Пункт назначения"
|
"dest" = "Пункт назначения"
|
||||||
"inbound" = "Входящее соединение"
|
"inbound" = "Инбаунд"
|
||||||
"outbound" = "Исходящее соединение"
|
"outbound" = "Аутбаунд"
|
||||||
"balancer" = "Балансировщик"
|
"balancer" = "Балансировщик"
|
||||||
"info" = "Информация"
|
"info" = "Информация"
|
||||||
"add" = "Создать правило"
|
"add" = "Создать правило"
|
||||||
|
@ -468,14 +465,14 @@
|
||||||
"useComma" = "Элементы, разделённые запятыми"
|
"useComma" = "Элементы, разделённые запятыми"
|
||||||
|
|
||||||
[pages.xray.outbound]
|
[pages.xray.outbound]
|
||||||
"addOutbound" = "Создать исходящее соединение"
|
"addOutbound" = "Создать аутбаунд"
|
||||||
"addReverse" = "Создать обратный прокси"
|
"addReverse" = "Создать реверс-прокси"
|
||||||
"editOutbound" = "Изменить исходящее соединение"
|
"editOutbound" = "Изменить аутбаунд"
|
||||||
"editReverse" = "Редактировать обратное прокси"
|
"editReverse" = "Редактировать реверс-прокси"
|
||||||
"tag" = "Тег"
|
"tag" = "Тег"
|
||||||
"tagDesc" = "Уникальный тег"
|
"tagDesc" = "Уникальный тег"
|
||||||
"address" = "Адрес"
|
"address" = "Адрес"
|
||||||
"reverse" = "Обратный"
|
"reverse" = "Реверс-прокси"
|
||||||
"domain" = "Домен"
|
"domain" = "Домен"
|
||||||
"type" = "Тип"
|
"type" = "Тип"
|
||||||
"bridge" = "Мост"
|
"bridge" = "Мост"
|
||||||
|
@ -484,7 +481,7 @@
|
||||||
"intercon" = "Соединение"
|
"intercon" = "Соединение"
|
||||||
"settings" = "Настройки"
|
"settings" = "Настройки"
|
||||||
"accountInfo" = "Информация об учетной записи"
|
"accountInfo" = "Информация об учетной записи"
|
||||||
"outboundStatus" = "Исходящий статус"
|
"outboundStatus" = "Статус аутбаунда"
|
||||||
"sendThrough" = "Отправить через"
|
"sendThrough" = "Отправить через"
|
||||||
|
|
||||||
[pages.xray.balancer]
|
[pages.xray.balancer]
|
||||||
|
@ -497,7 +494,7 @@
|
||||||
"balancerDesc" = "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
|
"balancerDesc" = "Невозможно одновременно использовать balancerTag и outboundTag. При одновременном использовании будет работать только outboundTag."
|
||||||
|
|
||||||
[pages.xray.wireguard]
|
[pages.xray.wireguard]
|
||||||
"secretKey" = "Приватный ключ"
|
"secretKey" = "Секретный ключ"
|
||||||
"publicKey" = "Публичный ключ"
|
"publicKey" = "Публичный ключ"
|
||||||
"allowedIPs" = "Разрешенные IP-адреса"
|
"allowedIPs" = "Разрешенные IP-адреса"
|
||||||
"endpoint" = "Конечная точка"
|
"endpoint" = "Конечная точка"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "Редактировать DNS"
|
"edit" = "Редактировать DNS"
|
||||||
"domains" = "Домены"
|
"domains" = "Домены"
|
||||||
"expectIPs" = "Ожидаемые IP"
|
"expectIPs" = "Ожидаемые IP"
|
||||||
|
"unexpectIPs" = "Неожидаемые IP"
|
||||||
|
"useSystemHosts" = "Использовать системные Hosts"
|
||||||
|
"useSystemHostsDesc" = "Использовать файл hosts из установленной системы"
|
||||||
|
"usePreset" = "Использовать шаблон"
|
||||||
|
"dnsPresetTitle" = "Шаблоны DNS"
|
||||||
|
"dnsPresetFamily" = "Семейный"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Создать Fake DNS"
|
"add" = "Создать Fake DNS"
|
||||||
|
@ -532,9 +535,9 @@
|
||||||
|
|
||||||
[pages.settings.security]
|
[pages.settings.security]
|
||||||
"admin" = "Учетные данные администратора"
|
"admin" = "Учетные данные администратора"
|
||||||
"twoFactor" = "Двухфакторная аутентификация"
|
"twoFactor" = "Двухфакторная аутентификация"
|
||||||
"twoFactorEnable" = "Включить 2FA"
|
"twoFactorEnable" = "Включить 2FA"
|
||||||
"twoFactorEnableDesc" = "Добавляет дополнительный уровень аутентификации для повышения безопасности."
|
"twoFactorEnableDesc" = "Добавляет дополнительный уровень аутентификации для повышения безопасности."
|
||||||
"twoFactorModalSetTitle" = "Включить двухфакторную аутентификацию"
|
"twoFactorModalSetTitle" = "Включить двухфакторную аутентификацию"
|
||||||
"twoFactorModalDeleteTitle" = "Отключить двухфакторную аутентификацию"
|
"twoFactorModalDeleteTitle" = "Отключить двухфакторную аутентификацию"
|
||||||
"twoFactorModalSteps" = "Для настройки двухфакторной аутентификации выполните несколько шагов:"
|
"twoFactorModalSteps" = "Для настройки двухфакторной аутентификации выполните несколько шагов:"
|
||||||
|
@ -554,8 +557,8 @@
|
||||||
"modifyUser" = "Вы успешно изменили учетные данные администратора."
|
"modifyUser" = "Вы успешно изменили учетные данные администратора."
|
||||||
"originalUserPassIncorrect" = "Неверное имя пользователя или пароль"
|
"originalUserPassIncorrect" = "Неверное имя пользователя или пароль"
|
||||||
"userPassMustBeNotEmpty" = "Новое имя пользователя и новый пароль должны быть заполнены"
|
"userPassMustBeNotEmpty" = "Новое имя пользователя и новый пароль должны быть заполнены"
|
||||||
"getOutboundTrafficError" = "Ошибка получения исходящего трафика"
|
"getOutboundTrafficError" = "Ошибка получения трафика аутбаунда"
|
||||||
"resetOutboundTrafficError" = "Ошибка сброса исходящего трафика"
|
"resetOutboundTrafficError" = "Ошибка сброса трафика аутбаунда"
|
||||||
|
|
||||||
[tgbot]
|
[tgbot]
|
||||||
"keyboardClosed" = "❌ Клавиатура закрыта."
|
"keyboardClosed" = "❌ Клавиатура закрыта."
|
||||||
|
@ -563,7 +566,7 @@
|
||||||
"noQuery" = "❌ Запрос не найден. Пожалуйста, повторите команду."
|
"noQuery" = "❌ Запрос не найден. Пожалуйста, повторите команду."
|
||||||
"wentWrong" = "❌ Что-то пошло не так..."
|
"wentWrong" = "❌ Что-то пошло не так..."
|
||||||
"noIpRecord" = "❗ Нет записей об IP-адресе."
|
"noIpRecord" = "❗ Нет записей об IP-адресе."
|
||||||
"noInbounds" = "❗ У вас не настроено ни одного подключения."
|
"noInbounds" = "❗ У вас не настроено ни одного инбаунда."
|
||||||
"unlimited" = "♾ Безлимит"
|
"unlimited" = "♾ Безлимит"
|
||||||
"add" = "Добавить"
|
"add" = "Добавить"
|
||||||
"month" = "Месяц"
|
"month" = "Месяц"
|
||||||
|
@ -572,7 +575,7 @@
|
||||||
"days" = "Дней"
|
"days" = "Дней"
|
||||||
"hours" = "Часов"
|
"hours" = "Часов"
|
||||||
"unknown" = "Неизвестно"
|
"unknown" = "Неизвестно"
|
||||||
"inbounds" = "Подключения"
|
"inbounds" = "Инбаунды"
|
||||||
"clients" = "Клиенты"
|
"clients" = "Клиенты"
|
||||||
"offline" = "🔴 Офлайн"
|
"offline" = "🔴 Офлайн"
|
||||||
"online" = "🟢 Онлайн"
|
"online" = "🟢 Онлайн"
|
||||||
|
@ -586,12 +589,16 @@
|
||||||
"status" = "✅ Бот функционирует нормально."
|
"status" = "✅ Бот функционирует нормально."
|
||||||
"usage" = "❗ Пожалуйста, укажите email для поиска."
|
"usage" = "❗ Пожалуйста, укажите email для поиска."
|
||||||
"getID" = "🆔 Ваш User ID: <code>{{ .ID }}</code>"
|
"getID" = "🆔 Ваш User ID: <code>{{ .ID }}</code>"
|
||||||
"helpAdminCommands" = "🔃 Для перезапуска Xray Core:\r\n<code>/restart</code>\r\n\r\n🔎 Для поиска клиента по email:\r\n<code>/usage [Email]</code>\r\n\r\n📊 Для поиска подключений (со статистикой клиентов):\r\n<code>/inbound [имя подключения]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
"helpAdminCommands" = "🔃 Для перезапуска Xray Core:\r\n<code>/restart</code>\r\n\r\n🔎 Для поиска клиента по email:\r\n<code>/usage [Email]</code>\r\n\r\n📊 Для поиска инбаундов (со статистикой клиентов):\r\n<code>/inbound [имя подключения]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
||||||
"helpClientCommands" = "💲 Для просмотра информации о вашей подписке используйте команду:\r\n<code>/usage [Email]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
"helpClientCommands" = "💲 Для просмотра информации о вашей подписке используйте команду:\r\n<code>/usage [Email]</code>\r\n\r\n🆔 Ваш Telegram User ID:\r\n<code>/id</code>"
|
||||||
"restartUsage" = "\r\n\r\n<code>/restart</code>"
|
"restartUsage" = "\r\n\r\n<code>/restart</code>"
|
||||||
"restartSuccess" = "✅ Ядро Xray успешно перезапущено."
|
"restartSuccess" = "✅ Ядро Xray успешно перезапущено."
|
||||||
"restartFailed" = "❗ Ошибка при перезапуске Xray-core.\r\n\r\n<code>Ошибка: {{ .Error }}</code>."
|
"restartFailed" = "❗ Ошибка при перезапуске Xray-core.\r\n\r\n<code>Ошибка: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core не запущен."
|
"xrayNotRunning" = "❗ Xray Core не запущен."
|
||||||
|
"startDesc" = "Показать главное меню"
|
||||||
|
"helpDesc" = "Справка по боту"
|
||||||
|
"statusDesc" = "Проверить статус бота"
|
||||||
|
"idDesc" = "Показать ваш Telegram ID"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 Загрузка процессора составляет {{ .Percent }}%, что превышает пороговое значение {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 Загрузка процессора составляет {{ .Percent }}%, что превышает пороговое значение {{ .Threshold }}%"
|
||||||
|
@ -648,8 +655,8 @@
|
||||||
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
|
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
|
||||||
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
|
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
|
||||||
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
|
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
|
||||||
"inbound_client_data_id" = "🔄 Подключения: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в подключение!"
|
"inbound_client_data_id" = "🔄 Инбаунды: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в инбаунд!"
|
||||||
"inbound_client_data_pass" = "🔄 Подключения: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в подключение!"
|
"inbound_client_data_pass" = "🔄 Инбаунды: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата исчерпания: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента в инбаунд!"
|
||||||
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
|
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
|
||||||
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Используется значение по умолчанию👌"
|
"using_default_value" = "Используется значение по умолчанию👌"
|
||||||
|
@ -671,7 +678,7 @@
|
||||||
"confirmToggle" = "✅ Подтвердить вкл/выкл пользователя?"
|
"confirmToggle" = "✅ Подтвердить вкл/выкл пользователя?"
|
||||||
"dbBackup" = "📂 Бэкап БД"
|
"dbBackup" = "📂 Бэкап БД"
|
||||||
"serverUsage" = "💻 Состояние сервера"
|
"serverUsage" = "💻 Состояние сервера"
|
||||||
"getInbounds" = "🔌 Подключения"
|
"getInbounds" = "🔌 Инбаунды"
|
||||||
"depleteSoon" = "⚠️ Скоро конец"
|
"depleteSoon" = "⚠️ Скоро конец"
|
||||||
"clientUsage" = "Статистика клиента"
|
"clientUsage" = "Статистика клиента"
|
||||||
"onlines" = "🟢 Онлайн"
|
"onlines" = "🟢 Онлайн"
|
||||||
|
@ -709,7 +716,7 @@
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
"successfulOperation" = "✅ Успешно!"
|
"successfulOperation" = "✅ Успешно!"
|
||||||
"errorOperation" = "❗ Ошибка в операции."
|
"errorOperation" = "❗ Ошибка в операции."
|
||||||
"getInboundsFailed" = "❌ Не удалось получить подключения."
|
"getInboundsFailed" = "❌ Не удалось получить инбаунды."
|
||||||
"getClientsFailed" = "❌ Не удалось получить клиентов."
|
"getClientsFailed" = "❌ Не удалось получить клиентов."
|
||||||
"canceled" = "❌ {{ .Email }}: Операция отменена."
|
"canceled" = "❌ {{ .Email }}: Операция отменена."
|
||||||
"clientRefreshSuccess" = "✅ {{ .Email }}: Клиент успешно обновлен."
|
"clientRefreshSuccess" = "✅ {{ .Email }}: Клиент успешно обновлен."
|
||||||
|
@ -726,5 +733,5 @@
|
||||||
"enableSuccess" = "✅ {{ .Email }}: Включено успешно."
|
"enableSuccess" = "✅ {{ .Email }}: Включено успешно."
|
||||||
"disableSuccess" = "✅ {{ .Email }}: Отключено успешно."
|
"disableSuccess" = "✅ {{ .Email }}: Отключено успешно."
|
||||||
"askToAddUserId" = "❌ Ваша конфигурация не найдена!\r\n💭 Пожалуйста, попросите администратора использовать ваш Telegram User ID в конфигурации.\r\n\r\n🆔 Ваш User ID: <code>{{ .TgUserID }}</code>"
|
"askToAddUserId" = "❌ Ваша конфигурация не найдена!\r\n💭 Пожалуйста, попросите администратора использовать ваш Telegram User ID в конфигурации.\r\n\r\n🆔 Ваш User ID: <code>{{ .TgUserID }}</code>"
|
||||||
"chooseClient" = "Выберите клиента для подключения {{ .Inbound }}"
|
"chooseClient" = "Выберите клиента для инбаунда {{ .Inbound }}"
|
||||||
"chooseInbound" = "Выберите подключение"
|
"chooseInbound" = "Выберите инбаунд"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Toplam veri"
|
"totalData" = "Toplam veri"
|
||||||
"sent" = "Gönderilen"
|
"sent" = "Gönderilen"
|
||||||
"received" = "Alınan"
|
"received" = "Alınan"
|
||||||
|
"documentation" = "Dokümantasyon"
|
||||||
"xraySwitchVersionDialog" = "Xray sürümünü gerçekten değiştirmek istiyor musunuz?"
|
"xraySwitchVersionDialog" = "Xray sürümünü gerçekten değiştirmek istiyor musunuz?"
|
||||||
"xraySwitchVersionDialogDesc" = "Bu işlem Xray sürümünü #version# olarak değiştirecektir."
|
"xraySwitchVersionDialogDesc" = "Bu işlem Xray sürümünü #version# olarak değiştirecektir."
|
||||||
"xraySwitchVersionPopover" = "Xray başarıyla güncellendi"
|
"xraySwitchVersionPopover" = "Xray başarıyla güncellendi"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "Bu seçenekler genel ayarlamaları belirler."
|
"generalConfigsDesc" = "Bu seçenekler genel ayarlamaları belirler."
|
||||||
"logConfigs" = "Günlük"
|
"logConfigs" = "Günlük"
|
||||||
"logConfigsDesc" = "Günlükler sunucunuzun verimliliğini etkileyebilir. Yalnızca ihtiyaç durumunda akıllıca etkinleştirmeniz önerilir"
|
"logConfigsDesc" = "Günlükler sunucunuzun verimliliğini etkileyebilir. Yalnızca ihtiyaç durumunda akıllıca etkinleştirmeniz önerilir"
|
||||||
"blockConfigs" = "Koruma Kalkanı"
|
|
||||||
"blockConfigsDesc" = "Bu seçenekler belirli istek protokolleri ve web siteleri temelinde trafiği engeller."
|
"blockConfigsDesc" = "Bu seçenekler belirli istek protokolleri ve web siteleri temelinde trafiği engeller."
|
||||||
"basicRouting" = "Temel Yönlendirme"
|
"basicRouting" = "Temel Yönlendirme"
|
||||||
"blockConnectionsConfigsDesc" = "Bu seçenekler belirli bir istenen ülkeye göre trafiği engelleyecektir."
|
"blockConnectionsConfigsDesc" = "Bu seçenekler belirli bir istenen ülkeye göre trafiği engelleyecektir."
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "Genel Yönlendirme Stratejisi"
|
"RoutingStrategy" = "Genel Yönlendirme Stratejisi"
|
||||||
"RoutingStrategyDesc" = "Tüm istekleri çözmek için genel trafik yönlendirme stratejisini ayarlayın."
|
"RoutingStrategyDesc" = "Tüm istekleri çözmek için genel trafik yönlendirme stratejisini ayarlayın."
|
||||||
"Torrent" = "BitTorrent Protokolünü Engelle"
|
"Torrent" = "BitTorrent Protokolünü Engelle"
|
||||||
"TorrentDesc" = "BitTorrent protokolünü engeller."
|
|
||||||
"Family" = "Aile Koruması"
|
|
||||||
"FamilyDesc" = "Yetişkin içerikli ve kötü amaçlı yazılım web sitelerini engeller."
|
|
||||||
"Inbounds" = "Gelenler"
|
"Inbounds" = "Gelenler"
|
||||||
"InboundsDesc" = "Belirli müşterileri kabul eder."
|
"InboundsDesc" = "Belirli müşterileri kabul eder."
|
||||||
"Outbounds" = "Gidenler"
|
"Outbounds" = "Gidenler"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "Sunucuyu Düzenle"
|
"edit" = "Sunucuyu Düzenle"
|
||||||
"domains" = "Alan Adları"
|
"domains" = "Alan Adları"
|
||||||
"expectIPs" = "Beklenen IP'ler"
|
"expectIPs" = "Beklenen IP'ler"
|
||||||
|
"unexpectIPs" = "Beklenmeyen IP'ler"
|
||||||
|
"useSystemHosts" = "Sistem Hosts'larını Kullan"
|
||||||
|
"useSystemHostsDesc" = "Yüklü bir sistemden hosts dosyasını kullan"
|
||||||
|
"usePreset" = "Şablon kullan"
|
||||||
|
"dnsPresetTitle" = "DNS Şablonları"
|
||||||
|
"dnsPresetFamily" = "Aile"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Sahte DNS Ekle"
|
"add" = "Sahte DNS Ekle"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ İşlem başarılı!"
|
"restartSuccess" = "✅ İşlem başarılı!"
|
||||||
"restartFailed" = "❗ İşlem hatası.\r\n\r\n<code>Hata: {{ .Error }}</code>."
|
"restartFailed" = "❗ İşlem hatası.\r\n\r\n<code>Hata: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core çalışmıyor."
|
"xrayNotRunning" = "❗ Xray Core çalışmıyor."
|
||||||
|
"startDesc" = "Ana menüyü göster"
|
||||||
|
"helpDesc" = "Bot yardımı"
|
||||||
|
"statusDesc" = "Bot durumunu kontrol et"
|
||||||
|
"idDesc" = "Telegram ID'nizi göster"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 CPU Yükü {{ .Percent }}% eşiği {{ .Threshold }}%'yi aşıyor"
|
"cpuThreshold" = "🔴 CPU Yükü {{ .Percent }}% eşiği {{ .Threshold }}%'yi aşıyor"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Загальний обсяг даних"
|
"totalData" = "Загальний обсяг даних"
|
||||||
"sent" = "Відправлено"
|
"sent" = "Відправлено"
|
||||||
"received" = "Отримано"
|
"received" = "Отримано"
|
||||||
|
"documentation" = "Документація"
|
||||||
"xraySwitchVersionDialog" = "Ви дійсно хочете змінити версію Xray?"
|
"xraySwitchVersionDialog" = "Ви дійсно хочете змінити версію Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Це змінить версію Xray на #version#."
|
"xraySwitchVersionDialogDesc" = "Це змінить версію Xray на #version#."
|
||||||
"xraySwitchVersionPopover" = "Xray успішно оновлено"
|
"xraySwitchVersionPopover" = "Xray успішно оновлено"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "Ці параметри визначатимуть загальні налаштування."
|
"generalConfigsDesc" = "Ці параметри визначатимуть загальні налаштування."
|
||||||
"logConfigs" = "Журнал"
|
"logConfigs" = "Журнал"
|
||||||
"logConfigsDesc" = "Журнали можуть вплинути на ефективність вашого сервера. Рекомендується вмикати його з розумом лише у випадку ваших потреб"
|
"logConfigsDesc" = "Журнали можуть вплинути на ефективність вашого сервера. Рекомендується вмикати його з розумом лише у випадку ваших потреб"
|
||||||
"blockConfigs" = "Захисний екран"
|
|
||||||
"blockConfigsDesc" = "Ці параметри блокуватимуть трафік на основі конкретних запитуваних протоколів і веб-сайтів."
|
"blockConfigsDesc" = "Ці параметри блокуватимуть трафік на основі конкретних запитуваних протоколів і веб-сайтів."
|
||||||
"basicRouting" = "Основна Маршрутизація"
|
"basicRouting" = "Основна Маршрутизація"
|
||||||
"blockConnectionsConfigsDesc" = "Ці параметри блокуватимуть трафік на основі запитаних країн."
|
"blockConnectionsConfigsDesc" = "Ці параметри блокуватимуть трафік на основі запитаних країн."
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "Загальна стратегія маршрутизації"
|
"RoutingStrategy" = "Загальна стратегія маршрутизації"
|
||||||
"RoutingStrategyDesc" = "Установити загальну стратегію маршрутизації трафіку для вирішення всіх запитів."
|
"RoutingStrategyDesc" = "Установити загальну стратегію маршрутизації трафіку для вирішення всіх запитів."
|
||||||
"Torrent" = "Блокувати протокол BitTorrent"
|
"Torrent" = "Блокувати протокол BitTorrent"
|
||||||
"TorrentDesc" = "Блокує протокол BitTorrent."
|
|
||||||
"Family" = "Захист сім'ї"
|
|
||||||
"FamilyDesc" = "Блокує вміст для дорослих і веб-сайти з шкідливими програмами."
|
|
||||||
"Inbounds" = "Вхідні"
|
"Inbounds" = "Вхідні"
|
||||||
"InboundsDesc" = "Прийняття певних клієнтів."
|
"InboundsDesc" = "Прийняття певних клієнтів."
|
||||||
"Outbounds" = "Вихід"
|
"Outbounds" = "Вихід"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "Редагувати сервер"
|
"edit" = "Редагувати сервер"
|
||||||
"domains" = "Домени"
|
"domains" = "Домени"
|
||||||
"expectIPs" = "Очікувані IP"
|
"expectIPs" = "Очікувані IP"
|
||||||
|
"unexpectIPs" = "Неочікувані IP"
|
||||||
|
"useSystemHosts" = "Використовувати системні Hosts"
|
||||||
|
"useSystemHostsDesc" = "Використовувати файл hosts з встановленої системи"
|
||||||
|
"usePreset" = "Використати шаблон"
|
||||||
|
"dnsPresetTitle" = "Шаблони DNS"
|
||||||
|
"dnsPresetFamily" = "Сімейний"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Додати підроблений DNS"
|
"add" = "Додати підроблений DNS"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ Операція успішна!"
|
"restartSuccess" = "✅ Операція успішна!"
|
||||||
"restartFailed" = "❗ Помилка в операції.\r\n\r\n<code>Помилка: {{ .Error }}</code>."
|
"restartFailed" = "❗ Помилка в операції.\r\n\r\n<code>Помилка: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core не запущений."
|
"xrayNotRunning" = "❗ Xray Core не запущений."
|
||||||
|
"startDesc" = "Показати головне меню"
|
||||||
|
"helpDesc" = "Довідка по боту"
|
||||||
|
"statusDesc" = "Перевірити статус бота"
|
||||||
|
"idDesc" = "Показати ваш Telegram ID"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 Навантаження ЦП {{ .Percent }}% перевищує порогове значення {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 Навантаження ЦП {{ .Percent }}% перевищує порогове значення {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "Tổng dữ liệu"
|
"totalData" = "Tổng dữ liệu"
|
||||||
"sent" = "Đã gửi"
|
"sent" = "Đã gửi"
|
||||||
"received" = "Đã nhận"
|
"received" = "Đã nhận"
|
||||||
|
"documentation" = "Tài liệu"
|
||||||
"xraySwitchVersionDialog" = "Bạn có chắc chắn muốn thay đổi phiên bản Xray không?"
|
"xraySwitchVersionDialog" = "Bạn có chắc chắn muốn thay đổi phiên bản Xray không?"
|
||||||
"xraySwitchVersionDialogDesc" = "Hành động này sẽ thay đổi phiên bản Xray thành #version#."
|
"xraySwitchVersionDialogDesc" = "Hành động này sẽ thay đổi phiên bản Xray thành #version#."
|
||||||
"xraySwitchVersionPopover" = "Xray đã được cập nhật thành công"
|
"xraySwitchVersionPopover" = "Xray đã được cập nhật thành công"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "Những tùy chọn này sẽ cung cấp điều chỉnh tổng quát."
|
"generalConfigsDesc" = "Những tùy chọn này sẽ cung cấp điều chỉnh tổng quát."
|
||||||
"logConfigs" = "Nhật ký"
|
"logConfigs" = "Nhật ký"
|
||||||
"logConfigsDesc" = "Nhật ký có thể ảnh hưởng đến hiệu suất máy chủ của bạn. Bạn chỉ nên kích hoạt nó một cách khôn ngoan trong trường hợp bạn cần"
|
"logConfigsDesc" = "Nhật ký có thể ảnh hưởng đến hiệu suất máy chủ của bạn. Bạn chỉ nên kích hoạt nó một cách khôn ngoan trong trường hợp bạn cần"
|
||||||
"blockConfigs" = "Cấu hình Chặn"
|
|
||||||
"blockConfigsDesc" = "Những tùy chọn này sẽ ngăn người dùng kết nối đến các giao thức và trang web cụ thể."
|
"blockConfigsDesc" = "Những tùy chọn này sẽ ngăn người dùng kết nối đến các giao thức và trang web cụ thể."
|
||||||
"basicRouting" = "Định tuyến Cơ bản"
|
"basicRouting" = "Định tuyến Cơ bản"
|
||||||
"blockConnectionsConfigsDesc" = "Các tùy chọn này sẽ chặn lưu lượng truy cập dựa trên quốc gia được yêu cầu cụ thể."
|
"blockConnectionsConfigsDesc" = "Các tùy chọn này sẽ chặn lưu lượng truy cập dựa trên quốc gia được yêu cầu cụ thể."
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "Cấu hình Chiến lược Định tuyến Tên miền"
|
"RoutingStrategy" = "Cấu hình Chiến lược Định tuyến Tên miền"
|
||||||
"RoutingStrategyDesc" = "Đặt chiến lược định tuyến tổng thể cho việc giải quyết DNS."
|
"RoutingStrategyDesc" = "Đặt chiến lược định tuyến tổng thể cho việc giải quyết DNS."
|
||||||
"Torrent" = "Cấu hình sử dụng BitTorrent"
|
"Torrent" = "Cấu hình sử dụng BitTorrent"
|
||||||
"TorrentDesc" = "Thay đổi mẫu cấu hình để tránh việc người dùng sử dụng BitTorrent."
|
|
||||||
"Family" = "Chặn phần mềm độc hại và nội dung người lớn"
|
|
||||||
"FamilyDesc" = "Trình phân giải DNS của Cloudflare để chặn phần mềm độc hại và nội dung người lớn để bảo vệ gia đình."
|
|
||||||
"Inbounds" = "Đầu vào"
|
"Inbounds" = "Đầu vào"
|
||||||
"InboundsDesc" = "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể."
|
"InboundsDesc" = "Thay đổi mẫu cấu hình để chấp nhận các máy khách cụ thể."
|
||||||
"Outbounds" = "Đầu ra"
|
"Outbounds" = "Đầu ra"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "Chỉnh sửa máy chủ"
|
"edit" = "Chỉnh sửa máy chủ"
|
||||||
"domains" = "Tên miền"
|
"domains" = "Tên miền"
|
||||||
"expectIPs" = "Các IP Dự Kiến"
|
"expectIPs" = "Các IP Dự Kiến"
|
||||||
|
"unexpectIPs" = "IP không mong muốn"
|
||||||
|
"useSystemHosts" = "Sử dụng Hosts hệ thống"
|
||||||
|
"useSystemHostsDesc" = "Sử dụng file hosts từ hệ thống đã cài đặt"
|
||||||
|
"usePreset" = "Dùng mẫu"
|
||||||
|
"dnsPresetTitle" = "Mẫu DNS"
|
||||||
|
"dnsPresetFamily" = "Gia đình"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "Thêm DNS giả"
|
"add" = "Thêm DNS giả"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ Hoạt động thành công!"
|
"restartSuccess" = "✅ Hoạt động thành công!"
|
||||||
"restartFailed" = "❗ Lỗi trong quá trình hoạt động.\r\n\r\n<code>Lỗi: {{ .Error }}</code>."
|
"restartFailed" = "❗ Lỗi trong quá trình hoạt động.\r\n\r\n<code>Lỗi: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core không chạy."
|
"xrayNotRunning" = "❗ Xray Core không chạy."
|
||||||
|
"startDesc" = "Hiển thị menu chính"
|
||||||
|
"helpDesc" = "Trợ giúp bot"
|
||||||
|
"statusDesc" = "Kiểm tra trạng thái bot"
|
||||||
|
"idDesc" = "Hiển thị ID Telegram của bạn"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 Sử dụng CPU {{ .Percent }}% vượt quá ngưỡng {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 Sử dụng CPU {{ .Percent }}% vượt quá ngưỡng {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "总数据"
|
"totalData" = "总数据"
|
||||||
"sent" = "已发送"
|
"sent" = "已发送"
|
||||||
"received" = "已接收"
|
"received" = "已接收"
|
||||||
|
"documentation" = "文档"
|
||||||
"xraySwitchVersionDialog" = "您确定要更改Xray版本吗?"
|
"xraySwitchVersionDialog" = "您确定要更改Xray版本吗?"
|
||||||
"xraySwitchVersionDialogDesc" = "这将把Xray版本更改为#version#。"
|
"xraySwitchVersionDialogDesc" = "这将把Xray版本更改为#version#。"
|
||||||
"xraySwitchVersionPopover" = "Xray 更新成功"
|
"xraySwitchVersionPopover" = "Xray 更新成功"
|
||||||
|
@ -401,7 +402,6 @@
|
||||||
"generalConfigsDesc" = "这些选项将决定常规配置"
|
"generalConfigsDesc" = "这些选项将决定常规配置"
|
||||||
"logConfigs" = "日志"
|
"logConfigs" = "日志"
|
||||||
"logConfigsDesc" = "日志可能会影响服务器的性能,建议仅在需要时启用"
|
"logConfigsDesc" = "日志可能会影响服务器的性能,建议仅在需要时启用"
|
||||||
"blockConfigs" = "防护屏蔽"
|
|
||||||
"blockConfigsDesc" = "这些选项将阻止用户连接到特定协议和网站"
|
"blockConfigsDesc" = "这些选项将阻止用户连接到特定协议和网站"
|
||||||
"basicRouting" = "基本路由"
|
"basicRouting" = "基本路由"
|
||||||
"blockConnectionsConfigsDesc" = "这些选项将根据特定的请求国家阻止流量。"
|
"blockConnectionsConfigsDesc" = "这些选项将根据特定的请求国家阻止流量。"
|
||||||
|
@ -421,9 +421,6 @@
|
||||||
"RoutingStrategy" = "配置路由域策略"
|
"RoutingStrategy" = "配置路由域策略"
|
||||||
"RoutingStrategyDesc" = "设置 DNS 解析的整体路由策略"
|
"RoutingStrategyDesc" = "设置 DNS 解析的整体路由策略"
|
||||||
"Torrent" = "屏蔽 BitTorrent 协议"
|
"Torrent" = "屏蔽 BitTorrent 协议"
|
||||||
"TorrentDesc" = "禁止使用 BitTorrent"
|
|
||||||
"Family" = "家庭保护"
|
|
||||||
"FamilyDesc" = "屏蔽成人内容和恶意网站"
|
|
||||||
"Inbounds" = "入站规则"
|
"Inbounds" = "入站规则"
|
||||||
"InboundsDesc" = "接受来自特定客户端的流量"
|
"InboundsDesc" = "接受来自特定客户端的流量"
|
||||||
"Outbounds" = "出站规则"
|
"Outbounds" = "出站规则"
|
||||||
|
@ -523,6 +520,12 @@
|
||||||
"edit" = "编辑服务器"
|
"edit" = "编辑服务器"
|
||||||
"domains" = "域"
|
"domains" = "域"
|
||||||
"expectIPs" = "预期 IP"
|
"expectIPs" = "预期 IP"
|
||||||
|
"unexpectIPs" = "意外IP"
|
||||||
|
"useSystemHosts" = "使用系统Hosts"
|
||||||
|
"useSystemHostsDesc" = "使用已安装系统的hosts文件"
|
||||||
|
"usePreset" = "使用模板"
|
||||||
|
"dnsPresetTitle" = "DNS模板"
|
||||||
|
"dnsPresetFamily" = "家庭"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "添加假 DNS"
|
"add" = "添加假 DNS"
|
||||||
|
@ -592,6 +595,10 @@
|
||||||
"restartSuccess" = "✅ 操作成功!"
|
"restartSuccess" = "✅ 操作成功!"
|
||||||
"restartFailed" = "❗ 操作错误。\r\n\r\n<code>错误: {{ .Error }}</code>."
|
"restartFailed" = "❗ 操作错误。\r\n\r\n<code>错误: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core 未运行。"
|
"xrayNotRunning" = "❗ Xray Core 未运行。"
|
||||||
|
"startDesc" = "显示主菜单"
|
||||||
|
"helpDesc" = "机器人帮助"
|
||||||
|
"statusDesc" = "检查机器人状态"
|
||||||
|
"idDesc" = "显示您的 Telegram ID"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 CPU 使用率为 {{ .Percent }}%,超过阈值 {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 CPU 使用率为 {{ .Percent }}%,超过阈值 {{ .Threshold }}%"
|
||||||
|
|
|
@ -128,6 +128,7 @@
|
||||||
"totalData" = "總數據"
|
"totalData" = "總數據"
|
||||||
"sent" = "已發送"
|
"sent" = "已發送"
|
||||||
"received" = "已接收"
|
"received" = "已接收"
|
||||||
|
"documentation" = "文件"
|
||||||
"xraySwitchVersionDialog" = "您確定要變更Xray版本嗎?"
|
"xraySwitchVersionDialog" = "您確定要變更Xray版本嗎?"
|
||||||
"xraySwitchVersionDialogDesc" = "這將會把Xray版本變更為#version#。"
|
"xraySwitchVersionDialogDesc" = "這將會把Xray版本變更為#version#。"
|
||||||
"xraySwitchVersionPopover" = "Xray 更新成功"
|
"xraySwitchVersionPopover" = "Xray 更新成功"
|
||||||
|
@ -403,7 +404,6 @@
|
||||||
"generalConfigsDesc" = "這些選項將決定常規配置"
|
"generalConfigsDesc" = "這些選項將決定常規配置"
|
||||||
"logConfigs" = "日誌"
|
"logConfigs" = "日誌"
|
||||||
"logConfigsDesc" = "日誌可能會影響伺服器的效能,建議僅在需要時啟用"
|
"logConfigsDesc" = "日誌可能會影響伺服器的效能,建議僅在需要時啟用"
|
||||||
"blockConfigs" = "防護遮蔽"
|
|
||||||
"blockConfigsDesc" = "這些選項將阻止使用者連線到特定協議和網站"
|
"blockConfigsDesc" = "這些選項將阻止使用者連線到特定協議和網站"
|
||||||
"basicRouting" = "基本路由"
|
"basicRouting" = "基本路由"
|
||||||
"blockConnectionsConfigsDesc" = "這些選項將根據特定的請求國家阻止流量。"
|
"blockConnectionsConfigsDesc" = "這些選項將根據特定的請求國家阻止流量。"
|
||||||
|
@ -423,9 +423,6 @@
|
||||||
"RoutingStrategy" = "配置路由域策略"
|
"RoutingStrategy" = "配置路由域策略"
|
||||||
"RoutingStrategyDesc" = "設定 DNS 解析的整體路由策略"
|
"RoutingStrategyDesc" = "設定 DNS 解析的整體路由策略"
|
||||||
"Torrent" = "遮蔽 BitTorrent 協議"
|
"Torrent" = "遮蔽 BitTorrent 協議"
|
||||||
"TorrentDesc" = "禁止使用 BitTorrent"
|
|
||||||
"Family" = "家庭保護"
|
|
||||||
"FamilyDesc" = "遮蔽成人內容和惡意網站"
|
|
||||||
"Inbounds" = "入站規則"
|
"Inbounds" = "入站規則"
|
||||||
"InboundsDesc" = "接受來自特定客戶端的流量"
|
"InboundsDesc" = "接受來自特定客戶端的流量"
|
||||||
"Outbounds" = "出站規則"
|
"Outbounds" = "出站規則"
|
||||||
|
@ -525,6 +522,12 @@
|
||||||
"edit" = "編輯伺服器"
|
"edit" = "編輯伺服器"
|
||||||
"domains" = "域"
|
"domains" = "域"
|
||||||
"expectIPs" = "預期 IP"
|
"expectIPs" = "預期 IP"
|
||||||
|
"unexpectIPs" = "意外IP"
|
||||||
|
"useSystemHosts" = "使用系統Hosts"
|
||||||
|
"useSystemHostsDesc" = "使用已安裝系統的hosts檔案"
|
||||||
|
"usePreset" = "使用範本"
|
||||||
|
"dnsPresetTitle" = "DNS範本"
|
||||||
|
"dnsPresetFamily" = "家庭"
|
||||||
|
|
||||||
[pages.xray.fakedns]
|
[pages.xray.fakedns]
|
||||||
"add" = "新增假 DNS"
|
"add" = "新增假 DNS"
|
||||||
|
@ -594,6 +597,10 @@
|
||||||
"restartSuccess" = "✅ 操作成功!"
|
"restartSuccess" = "✅ 操作成功!"
|
||||||
"restartFailed" = "❗ 操作錯誤。\r\n\r\n<code>錯誤: {{ .Error }}</code>."
|
"restartFailed" = "❗ 操作錯誤。\r\n\r\n<code>錯誤: {{ .Error }}</code>."
|
||||||
"xrayNotRunning" = "❗ Xray Core 未運行。"
|
"xrayNotRunning" = "❗ Xray Core 未運行。"
|
||||||
|
"startDesc" = "顯示主選單"
|
||||||
|
"helpDesc" = "機器人幫助"
|
||||||
|
"statusDesc" = "檢查機器人狀態"
|
||||||
|
"idDesc" = "顯示您的 Telegram ID"
|
||||||
|
|
||||||
[tgbot.messages]
|
[tgbot.messages]
|
||||||
"cpuThreshold" = "🔴 CPU 使用率為 {{ .Percent }}%,超過閾值 {{ .Threshold }}%"
|
"cpuThreshold" = "🔴 CPU 使用率為 {{ .Percent }}%,超過閾值 {{ .Threshold }}%"
|
||||||
|
|
8
x-ui.sh
|
@ -483,7 +483,7 @@ enable_bbr() {
|
||||||
ubuntu | debian | armbian)
|
ubuntu | debian | armbian)
|
||||||
apt-get update && apt-get install -yqq --no-install-recommends ca-certificates
|
apt-get update && apt-get install -yqq --no-install-recommends ca-certificates
|
||||||
;;
|
;;
|
||||||
centos | almalinux | rocky | ol)
|
centos | rhel | almalinux | rocky | ol)
|
||||||
yum -y update && yum -y install ca-certificates
|
yum -y update && yum -y install ca-certificates
|
||||||
;;
|
;;
|
||||||
fedora | amzn | virtuozzo)
|
fedora | amzn | virtuozzo)
|
||||||
|
@ -1004,7 +1004,7 @@ ssl_cert_issue() {
|
||||||
ubuntu | debian | armbian)
|
ubuntu | debian | armbian)
|
||||||
apt update && apt install socat -y
|
apt update && apt install socat -y
|
||||||
;;
|
;;
|
||||||
centos | almalinux | rocky | ol)
|
centos | rhel | almalinux | rocky | ol)
|
||||||
yum -y update && yum -y install socat
|
yum -y update && yum -y install socat
|
||||||
;;
|
;;
|
||||||
fedora | amzn | virtuozzo)
|
fedora | amzn | virtuozzo)
|
||||||
|
@ -1520,7 +1520,7 @@ install_iplimit() {
|
||||||
debian | armbian)
|
debian | armbian)
|
||||||
apt update && apt install fail2ban -y
|
apt update && apt install fail2ban -y
|
||||||
;;
|
;;
|
||||||
centos | almalinux | rocky | ol)
|
centos | rhel | almalinux | rocky | ol)
|
||||||
yum update -y && yum install epel-release -y
|
yum update -y && yum install epel-release -y
|
||||||
yum -y install fail2ban
|
yum -y install fail2ban
|
||||||
;;
|
;;
|
||||||
|
@ -1600,7 +1600,7 @@ remove_iplimit() {
|
||||||
apt-get purge -y fail2ban -y
|
apt-get purge -y fail2ban -y
|
||||||
apt-get autoremove -y
|
apt-get autoremove -y
|
||||||
;;
|
;;
|
||||||
centos | almalinux | rocky | ol)
|
centos | rhel | almalinux | rocky | ol)
|
||||||
yum remove fail2ban -y
|
yum remove fail2ban -y
|
||||||
yum autoremove -y
|
yum autoremove -y
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
"math"
|
||||||
|
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/util/common"
|
"x-ui/util/common"
|
||||||
|
@ -32,7 +33,7 @@ type XrayAPI struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XrayAPI) Init(apiPort int) error {
|
func (x *XrayAPI) Init(apiPort int) error {
|
||||||
if apiPort <= 0 {
|
if apiPort <= 0 || apiPort > math.MaxUint16 {
|
||||||
return fmt.Errorf("invalid Xray API port: %d", apiPort)
|
return fmt.Errorf("invalid Xray API port: %d", apiPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ type Config struct {
|
||||||
FakeDNS json_util.RawMessage `json:"fakedns"`
|
FakeDNS json_util.RawMessage `json:"fakedns"`
|
||||||
Observatory json_util.RawMessage `json:"observatory"`
|
Observatory json_util.RawMessage `json:"observatory"`
|
||||||
BurstObservatory json_util.RawMessage `json:"burstObservatory"`
|
BurstObservatory json_util.RawMessage `json:"burstObservatory"`
|
||||||
|
Metrics json_util.RawMessage `json:"metrics"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Equals(other *Config) bool {
|
func (c *Config) Equals(other *Config) bool {
|
||||||
|
@ -61,5 +62,8 @@ func (c *Config) Equals(other *Config) bool {
|
||||||
if !bytes.Equal(c.FakeDNS, other.FakeDNS) {
|
if !bytes.Equal(c.FakeDNS, other.FakeDNS) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if !bytes.Equal(c.Metrics, other.Metrics) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|