mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-09-10 12:16:18 +00:00
Merge branch 'MHSanaei:main' into main
This commit is contained in:
commit
1842219b19
31 changed files with 419 additions and 144 deletions
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -83,7 +83,7 @@ jobs:
|
|||
cd x-ui/bin
|
||||
|
||||
# Download dependencies
|
||||
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v1.8.23/"
|
||||
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v1.8.24/"
|
||||
if [ "${{ matrix.platform }}" == "amd64" ]; then
|
||||
wget ${Xray_URL}Xray-linux-64.zip
|
||||
unzip Xray-linux-64.zip
|
||||
|
|
|
@ -27,7 +27,7 @@ case $1 in
|
|||
esac
|
||||
mkdir -p build/bin
|
||||
cd build/bin
|
||||
wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.23/Xray-linux-${ARCH}.zip"
|
||||
wget "https://github.com/XTLS/Xray-core/releases/download/v1.8.24/Xray-linux-${ARCH}.zip"
|
||||
unzip "Xray-linux-${ARCH}.zip"
|
||||
rm -f "Xray-linux-${ARCH}.zip" geoip.dat geosite.dat
|
||||
mv xray "xray-linux-${FNAME}"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[English](/README.md) | [汉语](/README.zh_Hans.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
|
||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||
|
||||
|
@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
|
|||
|
||||
## Instalar una Versión Personalizada
|
||||
|
||||
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.13`:
|
||||
Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.14`:
|
||||
|
||||
```
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.13
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.14
|
||||
```
|
||||
|
||||
## Certificado SSL
|
||||
|
@ -177,6 +177,41 @@ eliminar 3x-ui de docker
|
|||
|
||||
</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
|
||||
|
||||
|
|
47
README.md
47
README.md
|
@ -1,4 +1,4 @@
|
|||
[English](/README.md) | [汉语](/README.zh_Hans.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
|
||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||
|
||||
|
@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
|
|||
|
||||
## Install Custom Version
|
||||
|
||||
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.3.13`:
|
||||
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.3.14`:
|
||||
|
||||
```
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.13
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.14
|
||||
```
|
||||
|
||||
## SSL Certificate
|
||||
|
@ -202,6 +202,41 @@ systemctl restart x-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
|
||||
|
||||
|
@ -415,13 +450,13 @@ The web panel supports daily traffic, panel login, database backup, system statu
|
|||
- 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 )
|
||||
- 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
|
||||
- Multi-language bot
|
||||
|
||||
### Setting up Telegram bot
|
||||
|
||||
|
|
191
README.ru_RU.md
191
README.ru_RU.md
|
@ -1,4 +1,4 @@
|
|||
[English](/README.md) | [汉语](/README.zh_Hans.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
|
||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
> **Отказ от ответственности:** Этот проект предназначен только для личного обучения и общения. Пожалуйста, не используйте его в незаконных целях и не применяйте в производственной среде.
|
||||
|
||||
**Если этот проект оказался полезным для вас, вы можете оценить его:** :star2:
|
||||
**Если этот проект оказался полезным для вас, вы можете оценить его, постативив звёздочку** :star2:
|
||||
|
||||
<p align="left">
|
||||
<a href="https://buymeacoffee.com/mhsanaei" target="_blank">
|
||||
|
@ -30,30 +30,30 @@
|
|||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
||||
```
|
||||
|
||||
## Установка пользовательской версии
|
||||
## Установка определённой версии
|
||||
|
||||
Чтобы установить нужную вам версию, добавьте номер версии в конец команды установки, например, версия `v2.3.13`:
|
||||
Чтобы установить нужную вам версию, добавьте номер версии в конец команды установки. Например, `v2.3.14`:
|
||||
|
||||
```
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.13
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.14
|
||||
```
|
||||
|
||||
## SSL Сертификат
|
||||
|
||||
<details>
|
||||
<summary>Нажмите для получения информации о SSL сертификате</summary>
|
||||
<summary>Нажмите для получения информации об SSL сертификате</summary>
|
||||
|
||||
### ACME
|
||||
|
||||
Для управления SSL сертификатами с помощью ACME:
|
||||
|
||||
1. Убедитесь, что ваш домен правильно настроен и указывает на сервер.
|
||||
2. Выполните команду `x-ui` в терминале, затем выберите «Управление SSL сертификатами».
|
||||
2. Выполните команду `x-ui` в терминале, затем выберите `SSL Certificate Management`.
|
||||
3. Вам будут предложены следующие опции:
|
||||
|
||||
- **Получить SSL:** Получить SSL сертификаты.
|
||||
- **Отозвать:** Отозвать существующие SSL сертификаты.
|
||||
- **Принудительное обновление:** Принудительно обновить SSL сертификаты.
|
||||
- **Get SSL:** Получить SSL сертификаты.
|
||||
- **Revoke:** Отозвать существующие SSL сертификаты.
|
||||
- **Force Renew:** Принудительно превыпустить SSL сертификаты.
|
||||
|
||||
### Certbot
|
||||
|
||||
|
@ -61,7 +61,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
|
|||
|
||||
```sh
|
||||
apt-get install certbot -y
|
||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d yourdomain.com
|
||||
certbot certonly --standalone --agree-tos --register-unsafely-without-email -d вашдомен.com
|
||||
certbot renew --dry-run
|
||||
```
|
||||
|
||||
|
@ -69,20 +69,20 @@ certbot renew --dry-run
|
|||
|
||||
Скрипт управления включает встроенное приложение для получения SSL сертификата через Cloudflare. Чтобы использовать этот скрипт для запроса сертификата, вам потребуется следующее:
|
||||
|
||||
- Электронная почта, зарегистрированная в Cloudflare
|
||||
- Email, зарегистрированный в Cloudflare
|
||||
- Глобальный API-ключ Cloudflare
|
||||
- Доменное имя должно быть разрешено на текущий сервер через Cloudflare
|
||||
- Доменное имя должно указывать на текущий сервер через Cloudflare
|
||||
|
||||
**Как получить глобальный API-ключ Cloudflare:**
|
||||
|
||||
1. Выполните команду `x-ui` в терминале, затем выберите «Cloudflare SSL Certificate».
|
||||
1. Выполните команду `x-ui` в терминале, затем выберите `Cloudflare SSL Certificate`.
|
||||
2. Посетите ссылку: [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens).
|
||||
3. Нажмите на "View Global API Key" (см. скриншот ниже):
|
||||

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

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

|
||||
|
||||
</details>
|
||||
|
@ -94,7 +94,7 @@ certbot renew --dry-run
|
|||
|
||||
#### Использование
|
||||
|
||||
1. Чтобы скачать последнюю версию сжатого пакета напрямую на ваш сервер, выполните следующую команду:
|
||||
1. Чтобы скачать последнюю версию архива напрямую на ваш сервер, выполните следующую команду:
|
||||
|
||||
```sh
|
||||
ARCH=$(uname -m)
|
||||
|
@ -113,7 +113,7 @@ esac
|
|||
wget https://github.com/MHSanaei/3x-ui/releases/latest/download/x-ui-linux-${XUI_ARCH}.tar.gz
|
||||
```
|
||||
|
||||
2. После загрузки сжатого пакета выполните следующие команды для установки или обновления x-ui:
|
||||
2. После загрузки архива выполните следующие команды для установки или обновления x-ui:
|
||||
|
||||
```sh
|
||||
ARCH=$(uname -m)
|
||||
|
@ -155,7 +155,7 @@ systemctl restart x-ui
|
|||
bash <(curl -sSL https://get.docker.com)
|
||||
```
|
||||
|
||||
2. **Клонируйте репозиторий проекта:**
|
||||
2. **Склонируйте репозиторий проекта:**
|
||||
|
||||
```sh
|
||||
git clone https://github.com/MHSanaei/3x-ui.git
|
||||
|
@ -168,7 +168,7 @@ systemctl restart x-ui
|
|||
docker compose up -d
|
||||
```
|
||||
|
||||
**OR**
|
||||
**ИЛИ**
|
||||
|
||||
```sh
|
||||
docker run -itd \
|
||||
|
@ -181,7 +181,7 @@ systemctl restart x-ui
|
|||
ghcr.io/mhsanaei/3x-ui:latest
|
||||
```
|
||||
|
||||
4. **Обновите до последней версии:**
|
||||
4. **Обновление до последней версии:**
|
||||
|
||||
```sh
|
||||
cd 3x-ui
|
||||
|
@ -190,7 +190,7 @@ systemctl restart x-ui
|
|||
docker compose up -d
|
||||
```
|
||||
|
||||
5. **Удалите 3x-ui из Docker:**
|
||||
5. **Удаление 3x-ui из Docker:**
|
||||
|
||||
```sh
|
||||
docker stop 3x-ui
|
||||
|
@ -201,8 +201,43 @@ systemctl restart x-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 20.04+
|
||||
- Debian 11+
|
||||
|
@ -232,9 +267,9 @@ systemctl restart x-ui
|
|||
|
||||
- **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, полагаются на эту архитектуру.
|
||||
- **armv6 / arm / arm32**: Ориентирована на очень старые встроенные устройства, эта архитектура, хотя и менее распространенная, всё ещё используется. Например, такие устройства, как Raspberry Pi 1, Raspberry Pi Zero/Zero W, полагаются на эту архитектуру.
|
||||
|
||||
- **armv5 / arm / arm32**: Более старая архитектура, ассоциируемая с ранними встроенными системами, сегодня менее распространена, но все еще может быть найдена в устаревших устройствах, таких как ранние версии Raspberry Pi и некоторые старые смартфоны.
|
||||
- **armv5 / arm / arm32**: Более старая архитектура, ассоциируемая с ранними встроенными системами, сегодня менее распространена, но всё ещё может быть найдена в устаревших устройствах, таких как ранние версии Raspberry Pi и некоторые старые смартфоны.
|
||||
|
||||
- **s390x**: Эта архитектура обычно используется в мейнфреймах IBM и обеспечивает высокую производительность и надежность для корпоративных рабочих нагрузок.
|
||||
</details>
|
||||
|
@ -251,20 +286,20 @@ systemctl restart x-ui
|
|||
- Украинский
|
||||
- Турецкий
|
||||
|
||||
## Функции
|
||||
## Возможности
|
||||
|
||||
- Мониторинг состояния системы
|
||||
- Поиск по всем входящим подключениям и клиентам
|
||||
- Темная/светлая тема
|
||||
- Тёмная/светлая тема
|
||||
- Поддержка нескольких пользователей и протоколов
|
||||
- Поддержка протоколов, включая VMESS, VLESS, Trojan, Shadowsocks, Dokodemo-door, Socks, HTTP, WireGuard
|
||||
- Поддержка протоколов XTLS, включая RPRX-Direct, Vision, REALITY
|
||||
- Статистика трафика, ограничение трафика, ограничение по времени истечения
|
||||
- Настраиваемые шаблоны конфигурации Xray
|
||||
- Поддержка панели доступа через HTTPS (самостоятельно предоставленное доменное имя + SSL сертификат)
|
||||
- Поддержка установки SSL-сертификата в один клик и автоматического обновления
|
||||
- Для получения более продвинутых настроек обратитесь к панели
|
||||
- Исправлены маршруты API (настройка пользователя будет создана с API)
|
||||
- Поддержка HTTPS доступа к панели (ваше доменное имя + SSL сертификат)
|
||||
- Поддержка установки SSL-сертификата в один клик и автоматического перевыпуска
|
||||
- Для получения более продвинутых настроек обращайтесь к панели
|
||||
- Исправляет маршруты API (настройка пользователя будет создана через API)
|
||||
- Поддержка изменения конфигураций по различным элементам, предоставленным в панели
|
||||
- Поддержка экспорта/импорта базы данных из панели
|
||||
|
||||
|
@ -286,12 +321,12 @@ systemctl restart x-ui
|
|||
- **Путь к базе данных:**
|
||||
- `/etc/x-ui/x-ui.db`
|
||||
|
||||
### Веб-базовый путь
|
||||
### Webbasepath
|
||||
|
||||
1. **Сбросить веб-базовый путь:**
|
||||
1. **Сбросить webbasepath:**
|
||||
- Откройте терминал.
|
||||
- Выполните команду `x-ui`.
|
||||
- Выберите опцию `Сбросить веб-базовый путь`.
|
||||
- Выберите опцию `Reset Web Base Path`.
|
||||
|
||||
2. **Генерация или настройка пути:**
|
||||
- Путь будет случайным образом сгенерирован, или вы можете ввести пользовательский путь.
|
||||
|
@ -303,8 +338,8 @@ systemctl restart x-ui
|
|||
- Для повышения безопасности используйте длинное случайное слово в структуре вашего URL.
|
||||
|
||||
**Примеры:**
|
||||
- `http://ip:port/*webbasepath*/panel`
|
||||
- `http://domain:port/*webbasepath*/panel`
|
||||
- `http://ip_адрес:порт/*webbasepath*/panel`
|
||||
- `http://домен:порт/*webbasepath*/panel`
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -321,12 +356,12 @@ WARP встроен, и дополнительная установка не т
|
|||
|
||||
**Для версий до `v2.1.0`:**
|
||||
|
||||
1. Выполните команду `x-ui` в терминале, затем выберите «Управление WARP».
|
||||
1. Выполните команду `x-ui` в терминале, затем выберите `WARP Management`.
|
||||
2. Вам будут предложены следующие опции:
|
||||
|
||||
- **Тип учетной записи (free, plus, team):** Выберите соответствующий тип учетной записи.
|
||||
- **Включить/Выключить WireProxy:** Включите или отключите WireProxy.
|
||||
- **Удалить WARP:** Удалите приложение WARP.
|
||||
- **Account Type (free, plus, team):** Выбрать соответствующий тип учетной записи.
|
||||
- **Enable/Disable WireProxy:** Включить или отключить WireProxy.
|
||||
- **Uninstall WARP:** Удалить приложение WARP.
|
||||
|
||||
3. Настройте параметры по мере необходимости в панели.
|
||||
|
||||
|
@ -348,15 +383,15 @@ WARP встроен, и дополнительная установка не т
|
|||
|
||||
Чтобы включить функциональность ограничения IP, вам нужно установить `fail2ban` и его необходимые файлы, выполнив следующие шаги:
|
||||
|
||||
1. Выполните команду `x-ui` в терминале, затем выберите «Управление ограничением IP».
|
||||
1. Выполните команду `x-ui` в терминале, затем выберите `IP Limit Management`.
|
||||
2. Вам будут предложены следующие опции:
|
||||
|
||||
- **Изменить длительность блокировки:** Отрегулируйте длительность блокировок.
|
||||
- **Разблокировать всех:** Снять все текущие блокировки.
|
||||
- **Проверить логи:** Просмотреть логи.
|
||||
- **Статус Fail2ban:** Проверьте статус `fail2ban`.
|
||||
- **Перезапустить Fail2ban:** Перезапустите службу `fail2ban`.
|
||||
- **Удалить Fail2ban:** Удалите Fail2ban с конфигурацией.
|
||||
- **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.
|
||||
|
||||
|
@ -379,11 +414,11 @@ WARP встроен, и дополнительная установка не т
|
|||
## Телеграм-бот
|
||||
|
||||
<details>
|
||||
<summary>Нажмите для получения информации о Телеграм-боте</summary>
|
||||
<summary>Нажмите для получения информации о телеграм-боте</summary>
|
||||
|
||||
#### Использование
|
||||
|
||||
Веб-панель поддерживает уведомления и функции, такие как ежедневный трафик, вход в панель, резервное копирование базы данных, состояние системы, информация о клиентах и другие, через Телеграм-бота. Чтобы использовать бота, вам нужно настроить параметры, связанные с ботом, в панели, включая:
|
||||
Веб-панель поддерживает уведомления и функции, такие как ежедневный трафик, вход в панель, резервное копирование базы данных, состояние системы, информация о клиентах и другие, через телеграм-бота. Чтобы использовать бота, вам нужно настроить параметры, связанные с ботом, в панели, включая:
|
||||
|
||||
- Токен Telegram
|
||||
- ID чата админа(-ов)
|
||||
|
@ -391,85 +426,85 @@ WARP встроен, и дополнительная установка не т
|
|||
- Уведомления о дате истечения
|
||||
- Уведомления о лимите трафика
|
||||
- Резервное копирование базы данных
|
||||
- Уведомления о загрузке ЦП
|
||||
- Уведомления о загрузке CPU
|
||||
|
||||
**Синтаксис примеров:**
|
||||
**Примеры синтаксиса:**
|
||||
|
||||
- `30 * * * * *` - Уведомление на 30-й секунде каждого часа
|
||||
- `0 */10 * * * *` - Уведомление на первой секунде каждых 10 минут
|
||||
- `30 * * * * *` - Уведомлять на 30-й секунде каждого часа
|
||||
- `0 */10 * * * *` - Уведомлять на первой секунде каждых 10 минут
|
||||
- `@hourly` - Ежечасное уведомление
|
||||
- `@daily` - Ежедневное уведомление (00:00 утра)
|
||||
- `@daily` - Ежедневное уведомление (в 00:00)
|
||||
- `@weekly` - Еженедельное уведомление
|
||||
- `@every 8h` - Уведомление каждые 8 часов
|
||||
- `@every 8h` - Уведомлять каждые 8 часов
|
||||
|
||||
### Возможности Телеграм-бота
|
||||
### Возможности телеграм-бота
|
||||
|
||||
- Периодические отчеты
|
||||
- Уведомления о входе
|
||||
- Уведомления о пороге ЦП
|
||||
- Уведомления о пороге CPU
|
||||
- Уведомления о времени истечения и трафике заранее
|
||||
- Поддержка меню отчета о клиентах, если имя пользователя клиента добавлено в конфигурацию пользователя
|
||||
- Поддерживает меню отчетов клиента, если имя пользователя телеграм клиента добавлено в конфигурации пользователя
|
||||
- Поддержка отчета о трафике через Telegram, поиск по UUID (VMESS/VLESS) или паролю (TROJAN) - анонимно
|
||||
- Меню-бот
|
||||
- Поиск клиента по электронной почте (только администратор)
|
||||
- Бот, основанный на меню
|
||||
- Поиск клиента по email (только администратор)
|
||||
- Проверка всех входящих соединений
|
||||
- Проверка состояния сервера
|
||||
- Проверка истекших пользователей
|
||||
- Получение резервных копий по запросу и в периодических отчетах
|
||||
- Получение резервных копий по запросу и в периодических отчётах
|
||||
- Многоязычный бот
|
||||
|
||||
### Настройка Телеграм-бота
|
||||
### Настройка телеграм-бота
|
||||
|
||||
- Начните [Botfather](https://t.me/BotFather) в вашем аккаунте Telegram:
|
||||
- Запустить [Botfather](https://t.me/BotFather) в вашем аккаунте Telegram:
|
||||

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

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

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

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

|
||||
|
||||
</details>
|
||||
|
||||
## API маршруты
|
||||
## Маршруты API
|
||||
|
||||
<details>
|
||||
<summary>Нажмите для получения информации о маршрутах API</summary>
|
||||
|
||||
#### Использование
|
||||
|
||||
- `/login` с `POST` данными пользователя: `{username: '', password: ''}` для входа
|
||||
- `/panel/api/inbounds` базовый маршрут для следующих действий:
|
||||
- `/login` с `POST`-данными: `{username: '', password: ''}` для входа
|
||||
- `/panel/api/inbounds` это базовый путь для следующих действий:
|
||||
|
||||
| Метод | Путь | Действие
|
||||
| :---: | -----------------------------------| -------------------------------------------
|
||||
| :----: | -----------------------------------| -------------------------------------------
|
||||
| `GET` | `"/list"` | Получить все входящие соединения
|
||||
| `GET` | `"/get/:id"` | Получить входящее соединение с inbound.id
|
||||
| `GET` | `"/getClientTraffics/:email"` | Получить трафик клиента по электронной почте
|
||||
| `GET` | `"/getClientTraffics/:email"` | Получить трафик клиента по email
|
||||
| `GET` | `"/getClientTrafficsById/:id"` | Получить трафик клиента по ID
|
||||
| `GET` | `"/createbackup"` | Бот Telegram отправляет резервную копию администраторам
|
||||
| `GET` | `"/createbackup"` | Telegram-бот отправит резервную копию администраторам
|
||||
| `POST` | `"/add"` | Добавить входящее соединение
|
||||
| `POST` | `"/del/:id"` | Удалить входящее соединение
|
||||
| `POST` | `"/update/:id"` | Обновить входящее соединение
|
||||
| `POST` | `"/clientIps/:email"` | IP-адрес клиента
|
||||
| `POST` | `"/clearClientIps/: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"` | Получить онлайн пользователей (список электронных почт)
|
||||
| `POST` | `"/delDepletedClients/:id"` | Удалить истекших клиентов в входящем соединении (-1: всех)
|
||||
| `POST` | `"/onlines"` | Получить пользователей, которые онлайн (список email'ов)
|
||||
|
||||
\*- Поле `clientId` должно быть заполнено следующим образом:
|
||||
|
||||
|
@ -484,7 +519,7 @@ WARP встроен, и дополнительная установка не т
|
|||
- [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://app.getpostman.com/run-collection/16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D16802678-1a4c9270-ac77-40ed-959a-7aa56dc4a415%26entityType%3Dcollection%26workspaceId%3D2cd38c01-c851-4a15-a972-f181c23359d9)
|
||||
</details>
|
||||
|
||||
## Переменные Среды
|
||||
## Переменные среды
|
||||
|
||||
<details>
|
||||
<summary>Нажмите для получения информации о переменных среды</summary>
|
||||
|
@ -521,11 +556,11 @@ XUI_BIN_FOLDER="bin" XUI_DB_FOLDER="/etc/x-ui" go build main.go
|
|||
|
||||
- [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._
|
||||
- [Vietnam Adblock rules](https://github.com/vuong2023/vn-v2ray-rules) (License: **GPL-3.0**): _A hosted domain hosted in Vietnam and blocklist with the most efficiency for Vietnamese._
|
||||
|
||||
## Звездочеты со временем
|
||||
## Число звёзд со временем
|
||||
|
||||
[](https://starchart.cc/MHSanaei/3x-ui)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[English](/README.md) | [汉语](/README.zh_Hans.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
[English](/README.md) | [中文](/README.zh_CN.md) | [Español](/README.es_ES.md) | [Русский](/README.ru_RU.md)
|
||||
|
||||
<p align="center"><a href="#"><img src="./media/3X-UI.png" alt="Image"></a></p>
|
||||
|
||||
|
@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
|
|||
|
||||
## 安装指定版本
|
||||
|
||||
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.13`:
|
||||
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.14`:
|
||||
|
||||
```
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.13
|
||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.14
|
||||
```
|
||||
|
||||
## SSL 认证
|
||||
|
@ -178,6 +178,42 @@ systemctl restart x-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 20.04+
|
|
@ -1 +1 @@
|
|||
2.3.13
|
||||
2.3.14
|
8
go.mod
8
go.mod
|
@ -14,10 +14,10 @@ require (
|
|||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/shirou/gopsutil/v4 v4.24.7
|
||||
github.com/valyala/fasthttp v1.55.0
|
||||
github.com/xtls/xray-core v1.8.23
|
||||
github.com/xtls/xray-core v1.8.24
|
||||
go.uber.org/atomic v1.11.0
|
||||
golang.org/x/text v0.17.0
|
||||
google.golang.org/grpc v1.65.0
|
||||
google.golang.org/grpc v1.66.0
|
||||
gorm.io/driver/sqlite v1.5.6
|
||||
gorm.io/gorm v1.25.11
|
||||
)
|
||||
|
@ -40,7 +40,7 @@ require (
|
|||
github.com/go-playground/validator/v10 v10.22.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
|
||||
github.com/google/pprof v0.0.0-20240829160300-da1f7e9f2b25 // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/gorilla/sessions v1.4.0 // indirect
|
||||
|
@ -57,7 +57,7 @@ require (
|
|||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.20.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 // indirect
|
||||
github.com/pires/go-proxyproto v0.7.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
|
|
20
go.sum
20
go.sum
|
@ -98,8 +98,8 @@ 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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 h1:FKHo8hFI3A+7w0aUQuYXQ+6EN5stWmeY/AZqtM8xk9k=
|
||||
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/pprof v0.0.0-20240829160300-da1f7e9f2b25 h1:sEDPKUw6iPjczdu33njxFjO6tYa9bfc0z/QyB/zSsBw=
|
||||
github.com/google/pprof v0.0.0-20240829160300-da1f7e9f2b25/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
|
@ -150,8 +150,8 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
|
|||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -164,8 +164,8 @@ github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJE
|
|||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
|
||||
github.com/onsi/ginkgo/v2 v2.20.1 h1:YlVIbqct+ZmnEph770q9Q7NVAz4wwIiVNahee6JyUzo=
|
||||
github.com/onsi/ginkgo/v2 v2.20.1/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||
|
@ -275,8 +275,8 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y
|
|||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
|
||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
||||
github.com/xtls/xray-core v1.8.23 h1:A8Wr50ildMYLpaNu3EiK+Stg/tps6i0h7z5Hr4f9H2k=
|
||||
github.com/xtls/xray-core v1.8.23/go.mod h1:0CwyMPNA5Cs+ukPXHbYQGgne/ug0PuXOSVqBu7zyXOc=
|
||||
github.com/xtls/xray-core v1.8.24 h1:Y2NumdlnJ9C9gvh1Ivs2+73ui5XQgB70wZXYCiI9DyY=
|
||||
github.com/xtls/xray-core v1.8.24/go.mod h1:cWIOI6iBBOsB0HHU9PGhaiBhaMPfiktUjwA0IWolWJc=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
|
@ -374,8 +374,8 @@ google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE
|
|||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -92,6 +92,11 @@ func (s *Server) initRouter() (*gin.Engine, error) {
|
|||
SubJsonFragment = ""
|
||||
}
|
||||
|
||||
SubJsonNoise, err := s.settingService.GetSubJsonNoise()
|
||||
if err != nil {
|
||||
SubJsonNoise = ""
|
||||
}
|
||||
|
||||
SubJsonMux, err := s.settingService.GetSubJsonMux()
|
||||
if err != nil {
|
||||
SubJsonMux = ""
|
||||
|
@ -106,7 +111,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
|
|||
|
||||
s.sub = NewSUBController(
|
||||
g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates,
|
||||
SubJsonFragment, SubJsonMux, SubJsonRules)
|
||||
SubJsonFragment, SubJsonNoise, SubJsonMux, SubJsonRules)
|
||||
|
||||
return engine, nil
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ func NewSUBController(
|
|||
rModel string,
|
||||
update string,
|
||||
jsonFragment string,
|
||||
jsonNoise string,
|
||||
jsonMux string,
|
||||
jsonRules string,
|
||||
) *SUBController {
|
||||
|
@ -38,7 +39,7 @@ func NewSUBController(
|
|||
updateInterval: update,
|
||||
|
||||
subService: sub,
|
||||
subJsonService: NewSubJsonService(jsonFragment, jsonMux, jsonRules, sub),
|
||||
subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub),
|
||||
}
|
||||
a.initRouter(g)
|
||||
return a
|
||||
|
|
|
@ -21,13 +21,14 @@ type SubJsonService struct {
|
|||
configJson map[string]interface{}
|
||||
defaultOutbounds []json_util.RawMessage
|
||||
fragment string
|
||||
noise string
|
||||
mux string
|
||||
|
||||
inboundService service.InboundService
|
||||
SubService *SubService
|
||||
}
|
||||
|
||||
func NewSubJsonService(fragment string, mux string, rules string, subService *SubService) *SubJsonService {
|
||||
func NewSubJsonService(fragment string, noise string, mux string, rules string, subService *SubService) *SubJsonService {
|
||||
var configJson map[string]interface{}
|
||||
var defaultOutbounds []json_util.RawMessage
|
||||
json.Unmarshal([]byte(defaultJson), &configJson)
|
||||
|
@ -52,10 +53,15 @@ func NewSubJsonService(fragment string, mux string, rules string, subService *Su
|
|||
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment))
|
||||
}
|
||||
|
||||
if noise != "" {
|
||||
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noise))
|
||||
}
|
||||
|
||||
return &SubJsonService{
|
||||
configJson: configJson,
|
||||
defaultOutbounds: defaultOutbounds,
|
||||
fragment: fragment,
|
||||
noise: noise,
|
||||
mux: mux,
|
||||
SubService: subService,
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ const supportLangs = [
|
|||
icon: '🇮🇷',
|
||||
},
|
||||
{
|
||||
name: '汉语',
|
||||
value: 'zh-Hans',
|
||||
name: '中文',
|
||||
value: 'zh-CN',
|
||||
icon: '🇨🇳',
|
||||
},
|
||||
{
|
||||
|
|
|
@ -861,23 +861,34 @@ Outbound.Settings = class extends CommonClass {
|
|||
}
|
||||
};
|
||||
Outbound.FreedomSettings = class extends CommonClass {
|
||||
constructor(domainStrategy = '', fragment = {}) {
|
||||
constructor(
|
||||
domainStrategy = '',
|
||||
timeout = '',
|
||||
fragment = {},
|
||||
noise = {}
|
||||
) {
|
||||
super();
|
||||
this.domainStrategy = domainStrategy;
|
||||
this.timeout = timeout;
|
||||
this.fragment = fragment;
|
||||
this.noise = noise;
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
return new Outbound.FreedomSettings(
|
||||
json.domainStrategy,
|
||||
json.timeout,
|
||||
json.fragment ? Outbound.FreedomSettings.Fragment.fromJson(json.fragment) : undefined,
|
||||
json.noise ? Outbound.FreedomSettings.Noise.fromJson(json.noise) : undefined,
|
||||
);
|
||||
}
|
||||
|
||||
toJson() {
|
||||
return {
|
||||
domainStrategy: ObjectUtil.isEmpty(this.domainStrategy) ? undefined : this.domainStrategy,
|
||||
timeout: this.timeout,
|
||||
fragment: Object.keys(this.fragment).length === 0 ? undefined : this.fragment,
|
||||
noise: Object.keys(this.noise).length === 0 ? undefined : this.noise,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -897,6 +908,21 @@ Outbound.FreedomSettings.Fragment = class extends CommonClass {
|
|||
);
|
||||
}
|
||||
};
|
||||
Outbound.FreedomSettings.Noise = class extends CommonClass {
|
||||
constructor(packet = '', delay = '') {
|
||||
super();
|
||||
this.packet = packet;
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
static fromJson(json = {}) {
|
||||
return new Outbound.FreedomSettings.Noise(
|
||||
json.packet,
|
||||
json.delay,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
Outbound.BlackholeSettings = class extends CommonClass {
|
||||
constructor(type) {
|
||||
super();
|
||||
|
|
|
@ -38,6 +38,7 @@ class AllSetting {
|
|||
this.subURI = "";
|
||||
this.subJsonURI = "";
|
||||
this.subJsonFragment = "";
|
||||
this.subJsonNoise = "";
|
||||
this.subJsonMux = "";
|
||||
this.subJsonRules = "";
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ type AllSetting struct {
|
|||
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
|
||||
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
|
||||
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
|
||||
SubJsonNoise string `json:"subJsonNoise" form:"subJsonNoise"`
|
||||
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
|
||||
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
|
||||
Datepicker string `json:"datepicker" form:"datepicker"`
|
||||
|
|
|
@ -416,19 +416,19 @@
|
|||
<a-col span="24">
|
||||
<a-form>
|
||||
<a-form-item>
|
||||
<a-input autocomplete="username" v-model.trim="user.username" placeholder='{{ i18n "username" }}'
|
||||
<a-input autocomplete="username" name="username" v-model.trim="user.username" placeholder='{{ i18n "username" }}'
|
||||
@keydown.enter.native="login" autofocus>
|
||||
<a-icon slot="prefix" type="user" style="font-size: 16px;"></a-icon>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<password-input autocomplete="current-password" icon="lock" v-model.trim="user.password"
|
||||
<password-input autocomplete="password" name="password" icon="lock" v-model.trim="user.password"
|
||||
placeholder='{{ i18n "password" }}'
|
||||
@keydown.enter.native="login">
|
||||
</password-input>
|
||||
</a-form-item>
|
||||
<a-form-item v-if="secretEnable">
|
||||
<password-input autocomplete="secret" icon="key" v-model.trim="user.loginSecret"
|
||||
<password-input autocomplete="secret" name="secret" icon="key" v-model.trim="user.loginSecret"
|
||||
placeholder='{{ i18n "secretToken" }}'
|
||||
@keydown.enter.native="login">
|
||||
</password-input>
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
<template>
|
||||
<a-input :value="value" :type="showPassword ? 'text' : 'password'"
|
||||
:placeholder="placeholder"
|
||||
:autocomplete="autocomplete"
|
||||
:name="name"
|
||||
@input="$emit('input', $event.target.value)">
|
||||
<template v-if="icon" #prefix>
|
||||
<a-icon :type="icon" style="font-size: 16px;" />
|
||||
|
@ -18,7 +20,7 @@
|
|||
{{define "component/password"}}
|
||||
<script>
|
||||
Vue.component('password-input', {
|
||||
props: ["title", "value", "placeholder", "icon"],
|
||||
props: ["title", "value", "placeholder", "icon", "autocomplete", "name"],
|
||||
template: `{{template "component/passwordInput"}}`,
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
<a-select-option v-for="s in OutboundDomainStrategies" :value="s">[[ s ]]</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label='Timeout'>
|
||||
<a-input-number v-model.number="outbound.settings.timeout" min="0" ></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Fragment'>
|
||||
<a-switch :checked="Object.keys(outbound.settings.fragment).length >0" @change="checked => outbound.settings.fragment = checked ? new Outbound.FreedomSettings.Fragment() : {}"></a-switch>
|
||||
</a-form-item>
|
||||
|
@ -38,6 +41,17 @@
|
|||
<a-input v-model.trim="outbound.settings.fragment.interval"></a-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
<a-form-item label='Noise'>
|
||||
<a-switch :checked="Object.keys(outbound.settings.noise).length >0" @change="checked => outbound.settings.noise = checked ? new Outbound.FreedomSettings.Noise() : {}"></a-switch>
|
||||
</a-form-item>
|
||||
<template v-if="Object.keys(outbound.settings.noise).length >0">
|
||||
<a-form-item label='Packet'>
|
||||
<a-input v-model.trim="outbound.settings.noise.packet"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='Delay'>
|
||||
<a-input v-model.trim="outbound.settings.noise.delay"></a-input>
|
||||
</a-form-item>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- blackhole settings -->
|
||||
|
@ -95,10 +109,10 @@
|
|||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label='MTU'>
|
||||
<a-input-number v-model.number="outbound.settings.mtu"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.settings.mtu" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Workers'>
|
||||
<a-input-number min="0" v-model.number="outbound.settings.workers"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.settings.workers" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Kernel Mode'>
|
||||
<a-switch v-model="outbound.settings.kernelMode"></a-switch>
|
||||
|
@ -257,25 +271,25 @@
|
|||
<a-input v-model="outbound.stream.kcp.seed"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label='MTU'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.mtu"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.mtu" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='TTI (ms)'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.tti"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.tti" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Uplink (MB/s)'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.upCap"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.upCap" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Downlink (MB/s)'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.downCap"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.downCap" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Congestion'>
|
||||
<a-switch v-model="outbound.stream.kcp.congestion"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label='Read Buffer (MB)'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.readBuffer"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.readBuffer" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
<a-form-item label='Write Buffer (MB)'>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.writeBuffer"></a-input-number>
|
||||
<a-input-number v-model.number="outbound.stream.kcp.writeBuffer" min="0"></a-input-number>
|
||||
</a-form-item>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -60,10 +60,10 @@
|
|||
<a-switch v-model="inbound.stream.tls.rejectUnknownSni"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label="Disable System Root">
|
||||
<a-switch v-model="inbound.stream.tls.settings.disableSystemRoot"></a-switch>
|
||||
<a-switch v-model="inbound.stream.tls.disableSystemRoot"></a-switch>
|
||||
</a-form-item>
|
||||
<a-form-item label="Session Resumption">
|
||||
<a-switch v-model="inbound.stream.tls.settings.enableSessionResumption"></a-switch>
|
||||
<a-switch v-model="inbound.stream.tls.enableSessionResumption"></a-switch>
|
||||
</a-form-item>
|
||||
<template v-for="cert,index in inbound.stream.tls.certs">
|
||||
<a-form-item label='{{ i18n "certificate" }}'>
|
||||
|
|
|
@ -313,6 +313,24 @@
|
|||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-list-item>
|
||||
<a-list-item style="padding: 20px">
|
||||
<a-row>
|
||||
<a-col :lg="24" :xl="12">
|
||||
<a-list-item-meta title='Noise'>
|
||||
<template slot="description">{{ i18n "pages.settings.noiseDesc"}}</template>
|
||||
</a-list-item-meta>
|
||||
</a-col>
|
||||
<a-col :lg="24" :xl="12">
|
||||
<a-switch v-model="noise"></a-switch>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-collapse v-if="noise" style="margin-top: 14px;">
|
||||
<a-collapse-panel header='{{ i18n "pages.settings.noiseSett"}}' v-if="noise">
|
||||
<setting-list-item style="padding: 10px 20px" type="text" title='Packet (ms)' v-model="noisePacket" placeholder="rand:5-10"></setting-list-item>
|
||||
<setting-list-item style="padding: 10px 20px" type="text" title='Delay (ms)' v-model="noiseDelay" placeholder="10-20"></setting-list-item>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</a-list-item>
|
||||
<a-list-item style="padding: 20px">
|
||||
<a-row>
|
||||
<a-col :lg="24" :xl="12">
|
||||
|
@ -412,6 +430,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
defaultNoise: {
|
||||
tag: "noise",
|
||||
protocol: "freedom",
|
||||
settings: {
|
||||
domainStrategy: "AsIs",
|
||||
noise: {
|
||||
packet: "rand:5-10",
|
||||
delay: "10-20",
|
||||
}
|
||||
},
|
||||
},
|
||||
defaultMux: {
|
||||
enabled: true,
|
||||
concurrency: 8,
|
||||
|
@ -611,6 +640,32 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
noise: {
|
||||
get: function () { return this.allSetting?.subJsonNoise != ""; },
|
||||
set: function (v) {
|
||||
this.allSetting.subJsonNoise = v ? JSON.stringify(this.defaultNoise) : "";
|
||||
}
|
||||
},
|
||||
noisePacket: {
|
||||
get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.packet : ""; },
|
||||
set: function (v) {
|
||||
if (v != "") {
|
||||
newNoise = JSON.parse(this.allSetting.subJsonNoise);
|
||||
newNoise.settings.noise.packet = v;
|
||||
this.allSetting.subJsonNoise = JSON.stringify(newNoise);
|
||||
}
|
||||
}
|
||||
},
|
||||
noiseDelay: {
|
||||
get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.delay : ""; },
|
||||
set: function (v) {
|
||||
if (v != "") {
|
||||
newNoise = JSON.parse(this.allSetting.subJsonNoise);
|
||||
newNoise.settings.noise.delay = v;
|
||||
this.allSetting.subJsonNoise = JSON.stringify(newNoise);
|
||||
}
|
||||
}
|
||||
},
|
||||
enableMux: {
|
||||
get: function () { return this.allSetting?.subJsonMux != ""; },
|
||||
set: function (v) {
|
||||
|
|
|
@ -62,6 +62,7 @@ var defaultValueMap = map[string]string{
|
|||
"subJsonPath": "/json/",
|
||||
"subJsonURI": "",
|
||||
"subJsonFragment": "",
|
||||
"subJsonNoise": "",
|
||||
"subJsonMux": "",
|
||||
"subJsonRules": "",
|
||||
"datepicker": "gregorian",
|
||||
|
@ -458,6 +459,10 @@ func (s *SettingService) GetSubJsonFragment() (string, error) {
|
|||
return s.getString("subJsonFragment")
|
||||
}
|
||||
|
||||
func (s *SettingService) GetSubJsonNoise() (string, error) {
|
||||
return s.getString("subJsonNoise")
|
||||
}
|
||||
|
||||
func (s *SettingService) GetSubJsonMux() (string, error) {
|
||||
return s.getString("subJsonMux")
|
||||
}
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Fragmentation"
|
||||
"fragmentDesc" = "Enable fragmentation for TLS hello packet."
|
||||
"fragmentSett" = "Fragmentation Settings"
|
||||
"noiseDesc" = "Enable Noise."
|
||||
"noiseSett" = "Noise Settings"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Transmit multiple independent data streams within an established data stream."
|
||||
"muxSett" = "Mux Settings"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Fragmentación"
|
||||
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"
|
||||
"fragmentSett" = "Configuración de Fragmentación"
|
||||
"noiseDesc" = "Activar Noise."
|
||||
"noiseSett" = "Configuración de Noise"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido."
|
||||
"muxSett" = "Configuración Mux"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "فرگمنت"
|
||||
"fragmentDesc" = "فعال کردن فرگمنت برای بستهی نخست تیالاس"
|
||||
"fragmentSett" = "تنظیمات فرگمنت"
|
||||
"noiseDesc" = "فعال کردن Noise."
|
||||
"noiseSett" = "تنظیمات Noise"
|
||||
"mux" = "ماکس"
|
||||
"muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند"
|
||||
"muxSett" = "تنظیمات ماکس"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Fragmentasi"
|
||||
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
|
||||
"fragmentSett" = "Pengaturan Fragmentasi"
|
||||
"noiseDesc" = "Aktifkan Noise."
|
||||
"noiseSett" = "Pengaturan Noise"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada."
|
||||
"muxSett" = "Pengaturan Mux"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Фрагментация"
|
||||
"fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS"
|
||||
"fragmentSett" = "Настройки фрагментации"
|
||||
"noiseDesc" = "Включить Noise."
|
||||
"noiseSett" = "Настройки Noise"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Передача нескольких независимых потоков данных в рамках установленного потока данных."
|
||||
"muxSett" = "Mux Настройки"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Parçalama"
|
||||
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
|
||||
"fragmentSett" = "Parçalama Ayarları"
|
||||
"noiseDesc" = "Noise'i Etkinleştir."
|
||||
"noiseSett" = "Noise Ayarları"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir."
|
||||
"muxSett" = "Mux Ayarları"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Фрагментація"
|
||||
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
|
||||
"fragmentSett" = "Параметри фрагментації"
|
||||
"noiseDesc" = "Увімкнути Noise."
|
||||
"noiseSett" = "Налаштування Noise"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних."
|
||||
"muxSett" = "Налаштування Mux"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "Sự phân mảnh"
|
||||
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
|
||||
"fragmentSett" = "Cài đặt phân mảnh"
|
||||
"noiseDesc" = "Bật Noise."
|
||||
"noiseSett" = "Cài đặt Noise"
|
||||
"mux" = "Mux"
|
||||
"muxDesc" = "Truyền nhiều luồng dữ liệu độc lập trong luồng dữ liệu đã thiết lập."
|
||||
"muxSett" = "Mux Cài đặt"
|
||||
|
|
|
@ -312,6 +312,8 @@
|
|||
"fragment" = "分片"
|
||||
"fragmentDesc" = "启用 TLS hello 数据包分片"
|
||||
"fragmentSett" = "设置"
|
||||
"noiseDesc" = "启用 Noise."
|
||||
"noiseSett" = "Noise 设置"
|
||||
"mux" = "多路复用器"
|
||||
"muxDesc" = "在已建立的数据流内传输多个独立的数据流"
|
||||
"muxSett" = "复用器设置"
|
Loading…
Reference in a new issue