Compare commits

..

1 Commits

Author SHA1 Message Date
mhsanaei
f26567d85d v2.3.15 2024-09-05 10:23:01 +02:00
58 changed files with 1313 additions and 1255 deletions

View File

@@ -83,7 +83,7 @@ jobs:
cd x-ui/bin cd x-ui/bin
# Download dependencies # Download dependencies
Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v24.9.30/" Xray_URL="https://github.com/XTLS/Xray-core/releases/download/v1.8.24/"
if [ "${{ matrix.platform }}" == "amd64" ]; then if [ "${{ matrix.platform }}" == "amd64" ]; then
wget ${Xray_URL}Xray-linux-64.zip wget ${Xray_URL}Xray-linux-64.zip
unzip Xray-linux-64.zip unzip Xray-linux-64.zip

View File

@@ -27,7 +27,7 @@ case $1 in
esac esac
mkdir -p build/bin mkdir -p build/bin
cd build/bin cd build/bin
wget "https://github.com/XTLS/Xray-core/releases/download/v24.9.30/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" 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}"

View File

@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Instalar una Versión Personalizada ## 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.4.3`: Para instalar la versión deseada, agrega la versión al final del comando de instalación. Por ejemplo, ver `v2.3.15`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.15
``` ```
## Certificado SSL ## Certificado SSL
@@ -220,14 +220,11 @@ location /sub {
- CentOS 8+ - CentOS 8+
- Fedora 36+ - Fedora 36+
- Arch Linux - Arch Linux
- Parch Linux
- Manjaro - Manjaro
- Armbian - Armbian
- AlmaLinux 8.0+ - AlmaLinux 9+
- Rocky Linux 8+ - Rockylinux 9+
- Oracle Linux 8+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## Arquitecturas y Dispositivos Compatibles ## Arquitecturas y Dispositivos Compatibles
@@ -279,100 +276,88 @@ Nuestra plataforma ofrece compatibilidad con una amplia gama de arquitecturas y
- Soporta exportar/importar base de datos desde el panel - Soporta exportar/importar base de datos desde el panel
## Configuración Predeterminada del Panel ## Configuraciones por Defecto
<details> <details>
<summary>Haz clic para ver los detalles de la configuración predeterminada</summary> <summary>Haz clic para detalles de las configuraciones por defecto</summary>
### Nombre de Usuario & Contraseña & Ruta Base Web: ### Información
Estos se generarán aleatoriamente si no los modificas.
- **Puerto:** el puerto predeterminado para el panel es `2053`
### Gestión de la Base de Datos:
Puedes realizar copias de seguridad y restauraciones de la base de datos directamente desde el panel.
- **Puerto:** 2053
- **Usuario y Contraseña:** Se generarán aleatoriamente si omites la modificación.
- **Ruta de la Base de Datos:** - **Ruta de la Base de Datos:**
- `/etc/x-ui/x-ui.db` - /etc/x-ui/x-ui.db
- **Ruta de Configuración de Xray:**
### Ruta Base Web - /usr/local/x-ui/bin/config.json
- **Ruta del Panel Web sin Implementar SSL:**
1. **Restablecer la Ruta Base Web:** - http://ip:2053/panel
- Abre tu terminal. - http://domain:2053/panel
- Ejecuta el comando `x-ui`. - **Ruta del Panel Web con Implementación de SSL:**
- Selecciona la opción `Restablecer la Ruta Base Web`. - https://domain:2053/panel
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> </details>
## Configuración de WARP ## Configuración WARP
<details> <details>
<summary>Haz clic para ver los detalles de la configuración de WARP</summary> <summary>Haz clic para detalles de la configuración WARP</summary>
#### Uso #### Uso
**Para versiones `v2.1.0` y posteriores:** Si deseas usar enrutamiento a WARP antes de la versión v2.1.0, sigue los pasos a continuación:
WARP está integrado, no se requiere instalación adicional. Simplemente habilita la configuración necesaria en el panel. **1.** Instala WARP en **Modo de Proxy SOCKS**:
```sh
bash <(curl -sSL https://raw.githubusercontent.com/hamid-gh98/x-ui-scripts/main/install_warp_proxy.sh)
```
**2.** Si ya instalaste warp, puedes desinstalarlo usando el siguiente comando:
```sh
warp u
```
**3.** Activa la configuración que necesites en el panel
Características de Configuración:
- Bloquear Anuncios
- Enrutar Google + Netflix + Spotify + OpenAI (ChatGPT) a WARP
- Corregir error 403 de Google
</details> </details>
## Límite de IP ## Límite de IP
<details> <details>
<summary>Haz clic para ver los detalles del límite de IP</summary> <summary>Haz clic para s detalles del límite de IP</summary>
#### Uso #### Uso
**Nota:** El Límite de IP no funcionará correctamente cuando uses Túnel IP. **Nota:** El Límite de IP no funcionará correctamente cuando se use IP Tunnel
- Para versiones hasta `v1.6.1`:
- **Para versiones hasta `v1.6.1`:**
- El límite de IP está integrado en el panel. - El límite de IP está integrado en el panel.
**Para versiones `v1.7.0` y posteriores:** - 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: - Para que el Límite de IP funcione correctamente, necesitas instalar fail2ban y sus archivos requeridos siguiendo estos pasos:
1. Ejecuta el comando `x-ui` en el terminal, luego elige `Gestión de Límite de IP`. 1. Usa el comando `x-ui` dentro de la terminal.
2. Verás las siguientes opciones: 2. Selecciona `Gestión de Límite de IP`.
3. Elige las opciones apropiadas según tus necesidades.
- **Cambiar la Duración del Bloqueo:** Ajustar la duración de los bloqueos. - asegúrate de tener ./access.log en tu Configuración de Xray después de la v2.1.3 tenemos una opción para ello
- **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. ```sh
- **Para versiones anteriores a `v2.1.3`:**
- Necesitas configurar manualmente la ruta del registro de acceso en tu configuración de Xray:
```sh
"log": { "log": {
"access": "./access.log", "access": "./access.log",
"dnsLog": false, "dnsLog": false,
"loglevel": "warning" "loglevel": "warning"
}, },
``` ```
- **Para versiones `v2.1.3` y posteriores:**
- Hay una opción para configurar `access.log` directamente desde el panel.
</details> </details>

View File

@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Install Custom Version ## Install Custom Version
To install your desired version, add the version to the end of the installation command. e.g., ver `v2.4.3`: To install your desired version, add the version to the end of the installation command. e.g., ver `v2.3.15`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.15
``` ```
## SSL Certificate ## SSL Certificate
@@ -169,8 +169,6 @@ systemctl restart x-ui
docker compose up -d 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** **OR**
```sh ```sh
@@ -250,11 +248,10 @@ location /sub {
- Parch Linux - Parch Linux
- Manjaro - Manjaro
- Armbian - Armbian
- AlmaLinux 8.0+ - AlmaLinux 9+
- Rocky Linux 8+ - Rocky Linux 9+
- Oracle Linux 8+ - Oracle Linux 8+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## Supported Architectures and Devices ## Supported Architectures and Devices
@@ -289,7 +286,6 @@ Our platform offers compatibility with a diverse range of architectures and devi
- Indonesian - Indonesian
- Ukrainian - Ukrainian
- Turkish - Turkish
- Português (Brazil)
## Features ## Features
@@ -362,6 +358,17 @@ Our platform offers compatibility with a diverse range of architectures and devi
WARP is built-in, and no additional installation is required. Simply turn on the necessary configuration in the panel. WARP is built-in, and no additional installation is required. Simply turn on the necessary configuration in the panel.
**For versions before `v2.1.0`:**
1. Run the `x-ui` command in the terminal, then choose `WARP Management`.
2. You will see the following options:
- **Account Type (free, plus, team):** Choose the appropriate account type.
- **Enable/Disable WireProxy:** Toggle WireProxy on or off.
- **Uninstall WARP:** Remove the WARP application.
3. Configure the settings as needed in the panel.
</details> </details>
## IP Limit ## IP Limit

View File

@@ -12,7 +12,7 @@
> **Отказ от ответственности:** Этот проект предназначен только для личного обучения и общения. Пожалуйста, не используйте его в незаконных целях и не применяйте в производственной среде. > **Отказ от ответственности:** Этот проект предназначен только для личного обучения и общения. Пожалуйста, не используйте его в незаконных целях и не применяйте в производственной среде.
**Если этот проект оказался полезным для вас, вы можете оценить его, поставив звёздочку** :star2: **Если этот проект оказался полезным для вас, вы можете оценить его, постативив звёздочку** :star2:
<p align="left"> <p align="left">
<a href="https://buymeacoffee.com/mhsanaei" target="_blank"> <a href="https://buymeacoffee.com/mhsanaei" target="_blank">
@@ -32,10 +32,10 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## Установка определённой версии ## Установка определённой версии
Чтобы установить нужную вам версию, добавьте номер версии в конец команды установки. Например, `v2.4.3`: Чтобы установить нужную вам версию, добавьте номер версии в конец команды установки. Например, `v2.3.15`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.15
``` ```
## SSL Сертификат ## SSL Сертификат
@@ -53,7 +53,7 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
- **Get SSL:** Получить SSL сертификаты. - **Get SSL:** Получить SSL сертификаты.
- **Revoke:** Отозвать существующие SSL сертификаты. - **Revoke:** Отозвать существующие SSL сертификаты.
- **Force Renew:** Принудительно перевыпустить SSL сертификаты. - **Force Renew:** Принудительно превыпустить SSL сертификаты.
### Certbot ### Certbot
@@ -76,7 +76,7 @@ certbot renew --dry-run
**Как получить глобальный API-ключ 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). 2. Посетите ссылку: [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens).
3. Нажмите на "View Global API Key" (см. скриншот ниже): 3. Нажмите на "View Global API Key" (см. скриншот ниже):
![](media/APIKey1.PNG) ![](media/APIKey1.PNG)
4. Возможно, вам потребуется повторно пройти аутентификацию. После этого ключ API будет отображён (см. скриншот ниже): 4. Возможно, вам потребуется повторно пройти аутентификацию. После этого ключ API будет отображён (см. скриншот ниже):
@@ -168,8 +168,6 @@ systemctl restart x-ui
docker compose up -d docker compose up -d
``` ```
Добавьте параметр ```--pull always``` для автоматического обновления контейнера, когда публикуется новый образ. Подробности: https://docs.docker.com/reference/cli/docker/container/run/#pull
**ИЛИ** **ИЛИ**
```sh ```sh
@@ -249,11 +247,10 @@ location /sub {
- Parch Linux - Parch Linux
- Manjaro - Manjaro
- Armbian - Armbian
- AlmaLinux 8.0+ - AlmaLinux 9+
- Rocky Linux 8+ - Rocky Linux 9+
- Oracle Linux 8+ - Oracle Linux 8+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## Поддерживаемые архитектуры и устройства ## Поддерживаемые архитектуры и устройства
@@ -288,7 +285,6 @@ location /sub {
- Индонезийский - Индонезийский
- Украинский - Украинский
- Турецкий - Турецкий
- Португальский (Бразилия)
## Возможности ## Возможности
@@ -333,7 +329,7 @@ location /sub {
- Выберите опцию `Reset Web Base Path`. - Выберите опцию `Reset Web Base Path`.
2. **Генерация или настройка пути:** 2. **Генерация или настройка пути:**
- Путь будет сгенерирован случайным образом, или вы можете ввести собственный путь. - Путь будет случайным образом сгенерирован, или вы можете ввести пользовательский путь.
3. **Просмотр текущих настроек:** 3. **Просмотр текущих настроек:**
- Чтобы просмотреть текущие настройки, используйте команду `x-ui settings` в терминале или опцию `View Current Settings` в `x-ui`. - Чтобы просмотреть текущие настройки, используйте команду `x-ui settings` в терминале или опцию `View Current Settings` в `x-ui`.
@@ -358,6 +354,17 @@ location /sub {
WARP встроен, и дополнительная установка не требуется. Просто включите необходимую конфигурацию в панели. WARP встроен, и дополнительная установка не требуется. Просто включите необходимую конфигурацию в панели.
**Для версий до `v2.1.0`:**
1. Выполните команду `x-ui` в терминале, затем выберите `WARP Management`.
2. Вам будут предложены следующие опции:
- **Account Type (free, plus, team):** Выбрать соответствующий тип учетной записи.
- **Enable/Disable WireProxy:** Включить или отключить WireProxy.
- **Uninstall WARP:** Удалить приложение WARP.
3. Настройте параметры по мере необходимости в панели.
</details> </details>
## Ограничение IP ## Ограничение IP
@@ -434,7 +441,7 @@ WARP встроен, и дополнительная установка не т
- Периодические отчеты - Периодические отчеты
- Уведомления о входе - Уведомления о входе
- Уведомления о пороге загруженности процессора - Уведомления о пороге CPU
- Уведомления о времени истечения и трафике заранее - Уведомления о времени истечения и трафике заранее
- Поддерживает меню отчетов клиента, если имя пользователя телеграм клиента добавлено в конфигурации пользователя - Поддерживает меню отчетов клиента, если имя пользователя телеграм клиента добавлено в конфигурации пользователя
- Поддержка отчета о трафике через Telegram, поиск по UUID (VMESS/VLESS) или паролю (TROJAN) - анонимно - Поддержка отчета о трафике через Telegram, поиск по UUID (VMESS/VLESS) или паролю (TROJAN) - анонимно
@@ -448,7 +455,7 @@ WARP встроен, и дополнительная установка не т
### Настройка телеграм-бота ### Настройка телеграм-бота
- Запустите [Botfather](https://t.me/BotFather) в вашем аккаунте Telegram: - Запустить [Botfather](https://t.me/BotFather) в вашем аккаунте Telegram:
![Botfather](./media/botfather.png) ![Botfather](./media/botfather.png)
- Создайте нового бота с помощью команды /newbot: у вас спросят 2 вопроса: отображаемое имя и имя пользователя для вашего бота. Обратите внимание, что имя пользователя должно заканчиваться на слово "bot". - Создайте нового бота с помощью команды /newbot: у вас спросят 2 вопроса: отображаемое имя и имя пользователя для вашего бота. Обратите внимание, что имя пользователя должно заканчиваться на слово "bot".
@@ -463,7 +470,7 @@ WARP встроен, и дополнительная установка не т
Введите токен вашего бота в поле ввода номер 3. Введите токен вашего бота в поле ввода номер 3.
Введите ID пользователя в поле ввода номер 4. Telegram-аккаунты с этим ID будут администраторами бота. (Вы можете ввести несколько ID, разделяя их запятой) Введите ID пользователя в поле ввода номер 4. Telegram-аккаунты с этим ID будут администраторами бота. (Вы можете ввести несколько ID, разделяя их запятой)
- Как получить ID пользователя Telegram? Используйте этот [бот](https://t.me/useridinfobot). Запустите бота, и он отобразит ваш ID пользователя Telegram. - Как получить ID пользователя Telegram? Используйте этого [бота](https://t.me/useridinfobot). Запустите бота, и он предоставит вам ваше ID пользователя Telegram.
![ID пользователя](./media/user-id.png) ![ID пользователя](./media/user-id.png)
</details> </details>
@@ -497,7 +504,7 @@ WARP встроен, и дополнительная установка не т
| `POST` | `"/resetAllTraffics"` | Сбросить трафик всех входящих соединений | `POST` | `"/resetAllTraffics"` | Сбросить трафик всех входящих соединений
| `POST` | `"/resetAllClientTraffics/:id"` | Сбросить трафик всех клиентов в входящем соединении | `POST` | `"/resetAllClientTraffics/:id"` | Сбросить трафик всех клиентов в входящем соединении
| `POST` | `"/delDepletedClients/:id"` | Удалить истекших клиентов в входящем соединении (-1: всех) | `POST` | `"/delDepletedClients/:id"` | Удалить истекших клиентов в входящем соединении (-1: всех)
| `POST` | `"/onlines"` | Получить пользователей, которые находятся онлайн (список email'ов) | `POST` | `"/onlines"` | Получить пользователей, которые онлайн (список email'ов)
\*- Поле `clientId` должно быть заполнено следующим образом: \*- Поле `clientId` должно быть заполнено следующим образом:

View File

@@ -32,58 +32,36 @@ bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.
## 安装指定版本 ## 安装指定版本
要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.4.3`: 要安装所需的版本,请将该版本添加到安装命令的末尾。 e.g., ver `v2.3.15`:
``` ```
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.4.3 bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh) v2.3.15
``` ```
### SSL证 ## SSL
<details> <details>
<summary>点击查看SSL证书详情</summary> <summary>点击查看 SSL证</summary>
### ACME ### Cloudflare
使用ACME管理SSL证书 管理脚本具有用于 Cloudflare 的内置 SSL 证书应用程序。若要使用此脚本申请证书,需要满足以下条件
1. 确保您的域名正确解析到服务器。 - Cloudflare 邮箱地址
2. 在终端中运行 `x-ui` 命令,然后选择 `SSL证书管理` - Cloudflare Global API Key
3. 您将看到以下选项: - 域名已通过 cloudflare 解析到当前服务器
**1:** 在终端中运行`x-ui` 选择 `Cloudflare SSL Certificate`.
- **获取SSL证书:** 获取SSL证书。
- **吊销:** 吊销现有的SSL证书。
- **强制更新:** 强制更新SSL证书。
### Certbot ### Certbot
```
安装并使用Certbot
```sh
apt-get install certbot -y 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 yourdomain.com
certbot renew --dry-run certbot renew --dry-run
``` ```
### Cloudflare ***Tip:*** *管理脚本具有 Certbot 。使用 `x-ui` 命令, 选择 `SSL Certificate Management`.*
管理脚本内置了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密钥”参见下图
![](media/APIKey1.PNG)
4. 您可能需要重新验证您的账户。之后将显示API密钥参见下图
![](media/APIKey2.png)
使用时,只需输入您的 `域名``电子邮件``API密钥`。如下图所示:
![](media/DetailEnter.png)
</details> </details>
@@ -243,14 +221,11 @@ location /sub {
- CentOS 8+ - CentOS 8+
- Fedora 36+ - Fedora 36+
- Arch Linux - Arch Linux
- Parch Linux
- Manjaro - Manjaro
- Armbian - Armbian
- AlmaLinux 8.0+ - AlmaLinux 9+
- Rocky Linux 8+ - Rockylinux 9+
- Oracle Linux 8+
- OpenSUSE Tubleweed - OpenSUSE Tubleweed
- Amazon Linux 2023
## 支持的架构和设备 ## 支持的架构和设备
<details> <details>
@@ -301,100 +276,88 @@ location /sub {
- 支持从面板导出/导入数据库 - 支持从面板导出/导入数据库
## 默认面板设置 ## 默认设置
<details> <details>
<summary>点击查看默认设置详情</summary> <summary>点击查看 默认设置</summary>
### 用户名 & 密码 & Web基础路径 ### 信息
如果不修改这些,它们将会随机生成。 - **端口:** 2053
- **用户名 & 密码:** 当您跳过设置时,此项会随机生成。
- **端口号:** 面板的默认端口号是 `2053` - **数据库路径:**
- /etc/x-ui/x-ui.db
### 数据库管理: - **Xray 配置路径:**
- /usr/local/x-ui/bin/config.json
您可以直接在面板中方便地进行数据库备份和还原。 - **面板链接无SSL**
- http://ip:2053/panel
- **数据库路径:** - http://domain:2053/panel
- `/etc/x-ui/x-ui.db` - **面板链接有SSL**
- https://domain:2053/panel
### 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> </details>
## WARP 配置 ## WARP 配置
<details> <details>
<summary>点击查看 WARP 配置详情</summary> <summary>点击查看 WARP 配置</summary>
#### 使用方法 #### 使用
**对于 `v2.1.0` 及之后的版本:** 如果要在 v2.1.0 之前使用 WARP 路由,请按照以下步骤操作:
WARP 已内置,无需额外安装。只需在面板中开启相关配置即可。 **1.** 在 **SOCKS Proxy Mode** 模式中安装Wrap
```sh
bash <(curl -sSL https://raw.githubusercontent.com/hamid-gh98/x-ui-scripts/main/install_warp_proxy.sh)
```
**2.** 如果您已经安装了 warp您可以使用以下命令卸载
```sh
warp u
```
**3.** 在面板中打开您需要的配置
配置:
- Block Ads
- Route Google + Netflix + Spotify + OpenAI (ChatGPT) to WARP
- Fix Google 403 error
</details> </details>
## IP 限制 ## IP 限制
<details> <details>
<summary>点击查看 IP 限制详情</summary> <summary>点击查看 IP 限制</summary>
#### 使用方法 #### 使用
**注意:** 使用 IP 隧道时IP 限制无法正常工作。 **注意** 使用 IP 隧道时IP 限制无法正常工作。
- **对于 `v1.6.1` 及之前的版本:** - 适用于最高 `v1.6.1`
- IP 限制功能已内置于面板中。
**对于 `v1.7.0` 及更新的版本:** - IP 限制 已被集成在面板中。
要启用 IP 限制功能,您需要安装 `fail2ban` 及其所需的文件,步骤如下 - 适用于 `v1.7.0` 以及更新的版本
1. 在终端中运行 `x-ui` 命令,然后选择 `IP 限制管理`。 - 要使 IP 限制正常工作,您需要按照以下步骤安装 fail2ban 及其所需的文件:
2. 您将看到以下选项:
- **更改封禁时长:** 调整封禁时长。 1. 使用面板内置的 `x-ui` 指令
- **解除所有封禁:** 解除当前的所有封禁。 2. 选择 `IP Limit Management`.
- **查看日志:** 查看日志 3. 根据您的需要选择合适的选项
- **Fail2ban 状态:** 检查 `fail2ban` 的状态。
- **重启 Fail2ban:** 重启 `fail2ban` 服务。
- **卸载 Fail2ban:** 卸载带有配置的 Fail2ban。
3. 在面板中通过设置 `Xray 配置/log/访问日志` 为 `./access.log` 添加访问日志路径,然后保存并重启 Xray - 确保您的 Xray 配置上有 ./access.log 。在 v2.1.3 之后,我们有一个选项
- **对于 `v2.1.3` 之前的版本:** ```sh
- 您需要在 Xray 配置中手动设置访问日志路径:
```sh
"log": { "log": {
"access": "./access.log", "access": "./access.log",
"dnsLog": false, "dnsLog": false,
"loglevel": "warning" "loglevel": "warning"
}, },
``` ```
- **对于 `v2.1.3` 及之后的版本:**
- 面板中直接提供了配置 `access.log` 的选项。
</details> </details>

View File

@@ -1 +1 @@
2.4.3 2.3.15

View File

@@ -46,7 +46,6 @@ type Inbound struct {
StreamSettings string `json:"streamSettings" form:"streamSettings"` StreamSettings string `json:"streamSettings" form:"streamSettings"`
Tag string `json:"tag" form:"tag" gorm:"unique"` Tag string `json:"tag" form:"tag" gorm:"unique"`
Sniffing string `json:"sniffing" form:"sniffing"` Sniffing string `json:"sniffing" form:"sniffing"`
Allocate string `json:"allocate" form:"allocate"`
} }
type OutboundTraffics struct { type OutboundTraffics struct {
@@ -76,7 +75,6 @@ func (i *Inbound) GenXrayInboundConfig() *xray.InboundConfig {
StreamSettings: json_util.RawMessage(i.StreamSettings), StreamSettings: json_util.RawMessage(i.StreamSettings),
Tag: i.Tag, Tag: i.Tag,
Sniffing: json_util.RawMessage(i.Sniffing), Sniffing: json_util.RawMessage(i.Sniffing),
Allocate: json_util.RawMessage(i.Allocate),
} }
} }

42
go.mod
View File

@@ -1,36 +1,35 @@
module x-ui module x-ui
go 1.23.1 go 1.23.0
require ( require (
github.com/gin-contrib/gzip v1.0.1 github.com/gin-contrib/gzip v1.0.1
github.com/gin-contrib/sessions v1.0.1 github.com/gin-contrib/sessions v1.0.1
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/goccy/go-json v0.10.3 github.com/goccy/go-json v0.10.3
github.com/mymmrac/telego v0.31.3 github.com/mymmrac/telego v0.31.2
github.com/nicksnyder/go-i18n/v2 v2.4.0 github.com/nicksnyder/go-i18n/v2 v2.4.0
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.3 github.com/pelletier/go-toml/v2 v2.2.3
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v4 v4.24.9 github.com/shirou/gopsutil/v4 v4.24.8
github.com/valyala/fasthttp v1.56.0 github.com/valyala/fasthttp v1.55.0
github.com/xtls/xray-core v1.8.24 github.com/xtls/xray-core v1.8.24
go.uber.org/atomic v1.11.0 go.uber.org/atomic v1.11.0
golang.org/x/text v0.18.0 golang.org/x/text v0.18.0
google.golang.org/grpc v1.67.1 google.golang.org/grpc v1.66.0
gorm.io/driver/sqlite v1.5.6 gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.12 gorm.io/gorm v1.25.11
) )
require ( require (
github.com/andybalholm/brotli v1.1.0 // indirect github.com/andybalholm/brotli v1.1.0 // indirect
github.com/bytedance/sonic v1.12.3 // indirect github.com/bytedance/sonic v1.12.2 // indirect
github.com/bytedance/sonic/loader v0.2.0 // indirect github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/cloudflare/circl v1.4.0 // indirect github.com/cloudflare/circl v1.4.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/ebitengine/purego v0.8.0 // indirect
github.com/fasthttp/router v1.5.2 // indirect github.com/fasthttp/router v1.5.2 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gabriel-vasile/mimetype v1.4.5 // indirect github.com/gabriel-vasile/mimetype v1.4.5 // indirect
@@ -38,10 +37,10 @@ require (
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.22.1 // indirect github.com/go-playground/validator/v10 v10.22.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-20241001023024-f4c0cfd0cf1d // indirect github.com/google/pprof v0.0.0-20240903155634-a8630aee4ab9 // 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
@@ -50,10 +49,10 @@ 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/klauspost/compress v1.17.10 // indirect github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // 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-20240909124753-873cd0166683 // indirect github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.23 // indirect github.com/mattn/go-sqlite3 v1.14.23 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@@ -61,15 +60,16 @@ require (
github.com/onsi/ginkgo/v2 v2.20.2 // indirect github.com/onsi/ginkgo/v2 v2.20.2 // indirect
github.com/pires/go-proxyproto v0.7.0 // indirect github.com/pires/go-proxyproto v0.7.0 // 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.0 // indirect
github.com/quic-go/quic-go v0.47.0 // indirect github.com/quic-go/quic-go v0.46.0 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect github.com/refraction-networking/utls v1.6.7 // 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.13.1 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/sagernet/sing v0.4.3 // indirect github.com/sagernet/sing v0.4.2 // indirect
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect github.com/tklauser/numcpus v0.8.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@@ -79,19 +79,19 @@ require (
github.com/valyala/fastjson v1.6.4 // indirect github.com/valyala/fastjson v1.6.4 // indirect
github.com/vishvananda/netlink v1.3.0 // indirect github.com/vishvananda/netlink v1.3.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect github.com/vishvananda/netns v0.0.4 // indirect
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 // indirect github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.uber.org/mock v0.4.0 // indirect go.uber.org/mock v0.4.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/arch v0.10.0 // indirect golang.org/x/arch v0.10.0 // indirect
golang.org/x/crypto v0.27.0 // indirect golang.org/x/crypto v0.26.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
golang.org/x/mod v0.21.0 // indirect golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.29.0 // indirect golang.org/x/net v0.28.0 // indirect
golang.org/x/sync v0.8.0 // indirect golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect golang.org/x/sys v0.25.0 // indirect
golang.org/x/time v0.6.0 // indirect golang.org/x/time v0.6.0 // indirect
golang.org/x/tools v0.25.0 // indirect golang.org/x/tools v0.24.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-20240826202546-f6391c0de4c7 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect

82
go.sum
View File

@@ -18,8 +18,8 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYU
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= github.com/bytedance/sonic v1.12.2 h1:oaMFuRTpMHYLpCntGca65YWt5ny+wAceDERTkT2L9lg=
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= github.com/bytedance/sonic v1.12.2/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
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.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
@@ -38,8 +38,6 @@ github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fp
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0= github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE=
github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/fasthttp/router v1.5.2 h1:ckJCCdV7hWkkrMeId3WfEhz+4Gyyf6QPwxi/RHIMZ6I= github.com/fasthttp/router v1.5.2 h1:ckJCCdV7hWkkrMeId3WfEhz+4Gyyf6QPwxi/RHIMZ6I=
github.com/fasthttp/router v1.5.2/go.mod h1:C8EY53ozOwpONyevc/V7Gr8pqnEjwnkFFqPo1alAGs0= github.com/fasthttp/router v1.5.2/go.mod h1:C8EY53ozOwpONyevc/V7Gr8pqnEjwnkFFqPo1alAGs0=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
@@ -72,8 +70,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.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
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.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
@@ -100,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/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/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-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d h1:Jaz2JzpQaQXyET0AjLBXShrthbpqMkhGiEfkcQAiAUs= github.com/google/pprof v0.0.0-20240903155634-a8630aee4ab9 h1:q5g0N9eal4bmJwXHC5z0QCKs8qhS35hFfq0BAYsIwZI=
github.com/google/pprof v0.0.0-20241001023024-f4c0cfd0cf1d/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/pprof v0.0.0-20240903155634-a8630aee4ab9/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 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/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -127,8 +125,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
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/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
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.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
@@ -142,8 +140,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 h1:5RK988zAqB3/AN3opGfRpoQgAVqr6/A5+qRTi67VUZY=
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -160,8 +158,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mymmrac/telego v0.31.3 h1:yZlD+dm+1W6p3OmCG8K+MbS02Y6paUgwPnqfZN3RWQQ= github.com/mymmrac/telego v0.31.2 h1:srvQOQtb5ZswmqIr03VuAkIF076bi25n7fyQ51Ifstw=
github.com/mymmrac/telego v0.31.3/go.mod h1:coOoqXVmjFnwBlzusjfEezbQ7RH9wQnDowJdMm+bnEo= github.com/mymmrac/telego v0.31.2/go.mod h1:dyuyrOIagRstnm2ZNWuVilPdsslQyEgwYww9zkDqdJU=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 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 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
@@ -188,21 +186,21 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.0 h1:jldbr38Ef/swDfxtvNvvUIYNg5LNm3Oa9W+IZvCm4q0=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/qpack v0.5.0/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.47.0 h1:yXs3v7r2bm1wmPTYNLKAAJTHMYkPEsfYJmTazXrCZ7Y= github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
github.com/quic-go/quic-go v0.47.0/go.mod h1:3bCapYsJvXGZcipOHuu7plYtaV6tnF+z7wIFsU0WK9E= github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
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=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8= github.com/sagernet/sing v0.4.2 h1:jzGNJdZVRI0xlAfFugsIQUPvyB9SuWvbJK7zQCXc4QM=
github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= github.com/sagernet/sing v0.4.2/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 h1:D0vL7YNisV2yqE55+q0lFuGse6U8lxlg7fYTctlT5Gc= github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 h1:D0vL7YNisV2yqE55+q0lFuGse6U8lxlg7fYTctlT5Gc=
@@ -210,8 +208,12 @@ github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38/go.mod h1:sM7Mt7uEo
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/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= github.com/shirou/gopsutil/v4 v4.24.8 h1:pVQjIenQkIhqO81mwTaXjTzOMT7d3TZkf43PlVFHENI=
github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q= github.com/shirou/gopsutil/v4 v4.24.8/go.mod h1:wE0OrJtj4dG+hYkxqDH3QiBICdKSf04/npcvLLc/oRg=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
@@ -261,8 +263,8 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
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.56.0 h1:bEZdJev/6LCBlpdORfrLu/WOZXXxvrUQSiyniuaoW8U= github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
github.com/valyala/fasthttp v1.56.0/go.mod h1:sReBt3XZVnudxuLOx4J/fMrJVorWRiWY2koQKgABiVI= github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
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/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
@@ -271,8 +273,8 @@ github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQ
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463 h1:g1Cj7d+my6k/HHxLAyxPwyX8i7FGRr6ulBDMkBzg2BM= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
github.com/xtls/reality v0.0.0-20240909153216-e26ae2305463/go.mod h1:BjIOLmkEEtAgloAiVUcYj0Mt+YU00JARZw8AEU0IwAg= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/xtls/xray-core v1.8.24 h1:Y2NumdlnJ9C9gvh1Ivs2+73ui5XQgB70wZXYCiI9DyY= 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/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 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
@@ -291,11 +293,11 @@ golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -309,8 +311,8 @@ golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -348,8 +350,8 @@ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE= golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
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=
@@ -372,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.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.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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= 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 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 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= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -390,8 +392,8 @@ 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.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE= gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=
gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/driver/sqlite v1.5.6/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk=

View File

@@ -39,12 +39,12 @@ arch() {
echo "arch: $(arch)" echo "arch: $(arch)"
os_version="" os_version=""
os_version=$(grep "^VERSION_ID" /etc/os-release | cut -d '=' -f2 | tr -d '"' | tr -d '.') os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1)
if [[ "${release}" == "arch" ]]; then if [[ "${release}" == "arch" ]]; then
echo "Your OS is Arch Linux" echo "Your OS is Arch Linux"
elif [[ "${release}" == "parch" ]]; then elif [[ "${release}" == "parch" ]]; then
echo "Your OS is Parch Linux" echo "Your OS is Parch linux"
elif [[ "${release}" == "manjaro" ]]; then elif [[ "${release}" == "manjaro" ]]; then
echo "Your OS is Manjaro" echo "Your OS is Manjaro"
elif [[ "${release}" == "armbian" ]]; then elif [[ "${release}" == "armbian" ]]; then
@@ -56,28 +56,24 @@ elif [[ "${release}" == "centos" ]]; then
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1 echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "ubuntu" ]]; then elif [[ "${release}" == "ubuntu" ]]; then
if [[ ${os_version} -lt 2004 ]]; then if [[ ${os_version} -lt 20 ]]; then
echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1 echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "fedora" ]]; then elif [[ "${release}" == "fedora" ]]; then
if [[ ${os_version} -lt 36 ]]; then if [[ ${os_version} -lt 36 ]]; then
echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1 echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "amzn" ]]; then
if [[ ${os_version} != "2023" ]]; then
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
fi
elif [[ "${release}" == "debian" ]]; then elif [[ "${release}" == "debian" ]]; then
if [[ ${os_version} -lt 11 ]]; then if [[ ${os_version} -lt 11 ]]; then
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1 echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "almalinux" ]]; then elif [[ "${release}" == "almalinux" ]]; then
if [[ ${os_version} -lt 80 ]]; then if [[ ${os_version} -lt 9 ]]; then
echo -e "${red} Please use AlmaLinux 8.0 or higher ${plain}\n" && exit 1 echo -e "${red} Please use AlmaLinux 9 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "rocky" ]]; then elif [[ "${release}" == "rocky" ]]; then
if [[ ${os_version} -lt 8 ]]; then if [[ ${os_version} -lt 9 ]]; then
echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1 echo -e "${red} Please use Rocky Linux 9 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "oracle" ]]; then elif [[ "${release}" == "oracle" ]]; then
if [[ ${os_version} -lt 8 ]]; then if [[ ${os_version} -lt 8 ]]; then
@@ -94,12 +90,12 @@ else
echo "- Parch Linux" echo "- Parch Linux"
echo "- Manjaro" echo "- Manjaro"
echo "- Armbian" echo "- Armbian"
echo "- AlmaLinux 8.0+" echo "- AlmaLinux 9+"
echo "- Rocky Linux 8+" echo "- Rocky Linux 9+"
echo "- Oracle Linux 8+" echo "- Oracle Linux 8+"
echo "- OpenSUSE Tumbleweed" echo "- OpenSUSE Tumbleweed"
echo "- Amazon Linux 2023"
exit 1 exit 1
fi fi
install_base() { install_base() {
@@ -110,7 +106,7 @@ install_base() {
centos | almalinux | rocky | oracle) centos | almalinux | rocky | oracle)
yum -y update && yum install -y -q wget curl tar tzdata yum -y update && yum install -y -q wget curl tar tzdata
;; ;;
fedora | amzn) fedora)
dnf -y update && dnf install -y -q wget curl tar tzdata dnf -y update && dnf install -y -q wget curl tar tzdata
;; ;;
arch | manjaro | parch) arch | manjaro | parch)

View File

@@ -23,7 +23,6 @@
"destOverride": [ "destOverride": [
"http", "http",
"tls", "tls",
"quic",
"fakedns" "fakedns"
], ],
"enabled": true "enabled": true

View File

@@ -92,9 +92,9 @@ func (s *Server) initRouter() (*gin.Engine, error) {
SubJsonFragment = "" SubJsonFragment = ""
} }
SubJsonNoises, err := s.settingService.GetSubJsonNoises() SubJsonNoise, err := s.settingService.GetSubJsonNoise()
if err != nil { if err != nil {
SubJsonNoises = "" SubJsonNoise = ""
} }
SubJsonMux, err := s.settingService.GetSubJsonMux() SubJsonMux, err := s.settingService.GetSubJsonMux()
@@ -111,7 +111,7 @@ func (s *Server) initRouter() (*gin.Engine, error) {
s.sub = NewSUBController( s.sub = NewSUBController(
g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates, g, LinksPath, JsonPath, Encrypt, ShowInfo, RemarkModel, SubUpdates,
SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules) SubJsonFragment, SubJsonNoise, SubJsonMux, SubJsonRules)
return engine, nil return engine, nil
} }

View File

@@ -21,14 +21,14 @@ type SubJsonService struct {
configJson map[string]interface{} configJson map[string]interface{}
defaultOutbounds []json_util.RawMessage defaultOutbounds []json_util.RawMessage
fragment string fragment string
noises string noise string
mux string mux string
inboundService service.InboundService inboundService service.InboundService
SubService *SubService SubService *SubService
} }
func NewSubJsonService(fragment string, noises 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 configJson map[string]interface{}
var defaultOutbounds []json_util.RawMessage var defaultOutbounds []json_util.RawMessage
json.Unmarshal([]byte(defaultJson), &configJson) json.Unmarshal([]byte(defaultJson), &configJson)
@@ -53,15 +53,15 @@ func NewSubJsonService(fragment string, noises string, mux string, rules string,
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment)) defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(fragment))
} }
if noises != "" { if noise != "" {
defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noises)) defaultOutbounds = append(defaultOutbounds, json_util.RawMessage(noise))
} }
return &SubJsonService{ return &SubJsonService{
configJson: configJson, configJson: configJson,
defaultOutbounds: defaultOutbounds, defaultOutbounds: defaultOutbounds,
fragment: fragment, fragment: fragment,
noises: noises, noise: noise,
mux: mux, mux: mux,
SubService: subService, SubService: subService,
} }
@@ -268,13 +268,13 @@ func (s *SubJsonService) realityData(rData map[string]interface{}) map[string]in
rltyData["spiderX"] = "/" + random.Seq(15) rltyData["spiderX"] = "/" + random.Seq(15)
shortIds, ok := rData["shortIds"].([]interface{}) shortIds, ok := rData["shortIds"].([]interface{})
if ok && len(shortIds) > 0 { if ok && len(shortIds) > 0 {
rltyData["shortId"] = shortIds[random.Num(len(shortIds))].(string) rltyData["shortId"] = shortIds
} else { } else {
rltyData["shortId"] = "" rltyData["shortId"] = ""
} }
serverNames, ok := rData["serverNames"].([]interface{}) serverNames, ok := rData["serverNames"].([]interface{})
if ok && len(serverNames) > 0 { if ok && len(serverNames) > 0 {
rltyData["serverName"] = serverNames[random.Num(len(serverNames))].(string) rltyData["serverName"] = serverNames
} else { } else {
rltyData["serverName"] = "" rltyData["serverName"] = ""
} }

View File

@@ -213,6 +213,12 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
http, _ := stream["httpSettings"].(map[string]interface{}) http, _ := stream["httpSettings"].(map[string]interface{})
obj["path"], _ = http["path"].(string) obj["path"], _ = http["path"].(string)
obj["host"] = searchHost(http) obj["host"] = searchHost(http)
case "quic":
quic, _ := stream["quicSettings"].(map[string]interface{})
header := quic["header"].(map[string]interface{})
obj["type"], _ = header["type"].(string)
obj["host"], _ = quic["security"].(string)
obj["path"], _ = quic["key"].(string)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
obj["path"] = grpc["serviceName"].(string) obj["path"] = grpc["serviceName"].(string)
@@ -364,6 +370,12 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
http, _ := stream["httpSettings"].(map[string]interface{}) http, _ := stream["httpSettings"].(map[string]interface{})
params["path"] = http["path"].(string) params["path"] = http["path"].(string)
params["host"] = searchHost(http) params["host"] = searchHost(http)
case "quic":
quic, _ := stream["quicSettings"].(map[string]interface{})
params["quicSecurity"] = quic["security"].(string)
params["key"] = quic["key"].(string)
header := quic["header"].(map[string]interface{})
params["headerType"] = header["type"].(string)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string) params["serviceName"] = grpc["serviceName"].(string)
@@ -592,6 +604,12 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
http, _ := stream["httpSettings"].(map[string]interface{}) http, _ := stream["httpSettings"].(map[string]interface{})
params["path"] = http["path"].(string) params["path"] = http["path"].(string)
params["host"] = searchHost(http) params["host"] = searchHost(http)
case "quic":
quic, _ := stream["quicSettings"].(map[string]interface{})
params["quicSecurity"] = quic["security"].(string)
params["key"] = quic["key"].(string)
header := quic["header"].(map[string]interface{})
params["headerType"] = header["type"].(string)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string) params["serviceName"] = grpc["serviceName"].(string)
@@ -821,6 +839,12 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
http, _ := stream["httpSettings"].(map[string]interface{}) http, _ := stream["httpSettings"].(map[string]interface{})
params["path"] = http["path"].(string) params["path"] = http["path"].(string)
params["host"] = searchHost(http) params["host"] = searchHost(http)
case "quic":
quic, _ := stream["quicSettings"].(map[string]interface{})
params["quicSecurity"] = quic["security"].(string)
params["key"] = quic["key"].(string)
header := quic["header"].(map[string]interface{})
params["headerType"] = header["type"].(string)
case "grpc": case "grpc":
grpc, _ := stream["grpcSettings"].(map[string]interface{}) grpc, _ := stream["grpcSettings"].(map[string]interface{})
params["serviceName"] = grpc["serviceName"].(string) params["serviceName"] = grpc["serviceName"].(string)

View File

@@ -471,6 +471,7 @@ class StreamSettings extends CommonClass {
this.kcp = kcpSettings; this.kcp = kcpSettings;
this.ws = wsSettings; this.ws = wsSettings;
this.http = httpSettings; this.http = httpSettings;
this.quic = quicSettings;
this.grpc = grpcSettings; this.grpc = grpcSettings;
this.httpupgrade = httpupgradeSettings; this.httpupgrade = httpupgradeSettings;
this.splithttp = splithttpSettings; this.splithttp = splithttpSettings;
@@ -522,6 +523,7 @@ class StreamSettings extends CommonClass {
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined, kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
wsSettings: network === 'ws' ? this.ws.toJson() : undefined, wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
httpSettings: network === 'http' ? this.http.toJson() : undefined, httpSettings: network === 'http' ? this.http.toJson() : undefined,
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined, splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined,
@@ -589,7 +591,7 @@ class Outbound extends CommonClass {
canEnableTls() { canEnableTls() {
if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false; if (![Protocols.VMess, Protocols.VLESS, Protocols.Trojan, Protocols.Shadowsocks].includes(this.protocol)) return false;
return ["tcp", "ws", "http", "grpc", "httpupgrade", "splithttp"].includes(this.stream.network); return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade", "splithttp"].includes(this.stream.network);
} }
//this is used for xtls-rprx-vision //this is used for xtls-rprx-vision
@@ -705,6 +707,11 @@ class Outbound extends CommonClass {
stream.http = new HttpStreamSettings( stream.http = new HttpStreamSettings(
json.path, json.path,
json.host); json.host);
} else if (network === 'quic') {
stream.quic = new QuicStreamSettings(
json.host ? json.host : 'none',
json.path,
json.type ? json.type : 'none');
} else if (network === 'grpc') { } else if (network === 'grpc') {
stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi'); stream.grpc = new GrpcStreamSettings(json.path, json.authority, json.type == 'multi');
} else if (network === 'httpupgrade') { } else if (network === 'httpupgrade') {
@@ -746,6 +753,11 @@ class Outbound extends CommonClass {
stream.ws = new WsStreamSettings(path, host); stream.ws = new WsStreamSettings(path, host);
} else if (type === 'http' || type == 'h2') { } else if (type === 'http' || type == 'h2') {
stream.http = new HttpStreamSettings(path, host); stream.http = new HttpStreamSettings(path, host);
} else if (type === 'quic') {
stream.quic = new QuicStreamSettings(
url.searchParams.get('quicSecurity') ?? 'none',
url.searchParams.get('key') ?? '',
headerType ?? 'none');
} else if (type === 'grpc') { } else if (type === 'grpc') {
stream.grpc = new GrpcStreamSettings( stream.grpc = new GrpcStreamSettings(
url.searchParams.get('serviceName') ?? '', url.searchParams.get('serviceName') ?? '',
@@ -851,44 +863,39 @@ Outbound.Settings = class extends CommonClass {
Outbound.FreedomSettings = class extends CommonClass { Outbound.FreedomSettings = class extends CommonClass {
constructor( constructor(
domainStrategy = '', domainStrategy = '',
timeout = '',
redirect = '', redirect = '',
fragment = {}, fragment = {},
noises = [] noise = {}
) { ) {
super(); super();
this.domainStrategy = domainStrategy; this.domainStrategy = domainStrategy;
this.timeout = timeout;
this.redirect = redirect; this.redirect = redirect;
this.fragment = fragment; this.fragment = fragment;
this.noises = noises; this.noise = noise;
}
addNoise() {
this.noises.push(new Outbound.FreedomSettings.Noise());
}
delNoise(index) {
this.noises.splice(index, 1);
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new Outbound.FreedomSettings( return new Outbound.FreedomSettings(
json.domainStrategy, json.domainStrategy,
json.timeout,
json.redirect, json.redirect,
json.fragment ? Outbound.FreedomSettings.Fragment.fromJson(json.fragment) : undefined, json.fragment ? Outbound.FreedomSettings.Fragment.fromJson(json.fragment) : undefined,
json.noises ? json.noises.map(noise => Outbound.FreedomSettings.Noise.fromJson(noise)) : [new Outbound.FreedomSettings.Noise()], json.noise ? Outbound.FreedomSettings.Noise.fromJson(json.noise) : undefined,
); );
} }
toJson() { toJson() {
return { return {
domainStrategy: ObjectUtil.isEmpty(this.domainStrategy) ? undefined : this.domainStrategy, domainStrategy: ObjectUtil.isEmpty(this.domainStrategy) ? undefined : this.domainStrategy,
timeout: this.timeout,
redirect: this.redirect, redirect: this.redirect,
fragment: Object.keys(this.fragment).length === 0 ? undefined : this.fragment, fragment: Object.keys(this.fragment).length === 0 ? undefined : this.fragment,
noises: Outbound.FreedomSettings.Noise.toJsonArray(this.noises), noise: Object.keys(this.noise).length === 0 ? undefined : this.noise,
}; };
} }
}; };
Outbound.FreedomSettings.Fragment = class extends CommonClass { Outbound.FreedomSettings.Fragment = class extends CommonClass {
constructor(packets = '1-3', length = '', interval = '') { constructor(packets = '1-3', length = '', interval = '') {
super(); super();
@@ -905,38 +912,19 @@ Outbound.FreedomSettings.Fragment = class extends CommonClass {
); );
} }
}; };
Outbound.FreedomSettings.Noise = class extends CommonClass { Outbound.FreedomSettings.Noise = class extends CommonClass {
constructor( constructor(packet = '', delay = '') {
type = 'rand',
packet = '10-20',
delay = '10-16'
) {
super(); super();
this.type = type;
this.packet = packet; this.packet = packet;
this.delay = delay; this.delay = delay;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
return new Outbound.FreedomSettings.Noise( return new Outbound.FreedomSettings.Noise(
json.type,
json.packet, json.packet,
json.delay, json.delay,
); );
} }
toJson() {
return {
type: this.type,
packet: this.packet,
delay: this.delay,
};
}
static toJsonArray(noises) {
return noises.map(noise => noise.toJson());
}
}; };
Outbound.BlackholeSettings = class extends CommonClass { Outbound.BlackholeSettings = class extends CommonClass {
@@ -958,19 +946,11 @@ Outbound.BlackholeSettings = class extends CommonClass {
} }
}; };
Outbound.DNSSettings = class extends CommonClass { Outbound.DNSSettings = class extends CommonClass {
constructor( constructor(network = 'udp', address = '1.1.1.1', port = 53) {
network = 'udp',
address = '1.1.1.1',
port = 53,
nonIPQuery = 'drop',
blockTypes = []
) {
super(); super();
this.network = network; this.network = network;
this.address = address; this.address = address;
this.port = port; this.port = port;
this.nonIPQuery = nonIPQuery;
this.blockTypes = blockTypes;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
@@ -978,8 +958,6 @@ Outbound.DNSSettings = class extends CommonClass {
json.network, json.network,
json.address, json.address,
json.port, json.port,
json.nonIPQuery,
json.blockTypes,
); );
} }
}; };

View File

@@ -7,7 +7,7 @@ class AllSetting {
this.webCertFile = ""; this.webCertFile = "";
this.webKeyFile = ""; this.webKeyFile = "";
this.webBasePath = "/"; this.webBasePath = "/";
this.sessionMaxAge = 60; this.sessionMaxAge = 0;
this.pageSize = 50; this.pageSize = 50;
this.expireDiff = 0; this.expireDiff = 0;
this.trafficDiff = 0; this.trafficDiff = 0;
@@ -38,7 +38,7 @@ class AllSetting {
this.subURI = ""; this.subURI = "";
this.subJsonURI = ""; this.subJsonURI = "";
this.subJsonFragment = ""; this.subJsonFragment = "";
this.subJsonNoises = ""; this.subJsonNoise = "";
this.subJsonMux = ""; this.subJsonMux = "";
this.subJsonRules = ""; this.subJsonRules = "";

View File

@@ -449,6 +449,37 @@ class HttpStreamSettings extends XrayCommonClass {
} }
} }
class QuicStreamSettings extends XrayCommonClass {
constructor(
security = 'none',
key = RandomUtil.randomSeq(10),
type = 'none'
) {
super();
this.security = security;
this.key = key;
this.type = type;
}
static fromJson(json = {}) {
return new QuicStreamSettings(
json.security,
json.key,
json.header ? json.header.type : 'none',
);
}
toJson() {
return {
security: this.security,
key: this.key,
header: {
type: this.type,
}
}
}
}
class GrpcStreamSettings extends XrayCommonClass { class GrpcStreamSettings extends XrayCommonClass {
constructor( constructor(
serviceName = "", serviceName = "",
@@ -529,12 +560,6 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
scMinPostsIntervalMs = "10-50", scMinPostsIntervalMs = "10-50",
noSSEHeader = false, noSSEHeader = false,
xPaddingBytes = "100-1000", xPaddingBytes = "100-1000",
xmux = {
maxConcurrency: 0,
maxConnections: 0,
cMaxReuseTimes: 0,
cMaxLifetimeMs: 0
}
) { ) {
super(); super();
this.path = path; this.path = path;
@@ -545,7 +570,6 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
this.scMinPostsIntervalMs = scMinPostsIntervalMs; this.scMinPostsIntervalMs = scMinPostsIntervalMs;
this.noSSEHeader = noSSEHeader; this.noSSEHeader = noSSEHeader;
this.xPaddingBytes = xPaddingBytes; this.xPaddingBytes = xPaddingBytes;
this.xmux = xmux;
} }
addHeader(name, value) { addHeader(name, value) {
@@ -566,7 +590,6 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
json.scMinPostsIntervalMs, json.scMinPostsIntervalMs,
json.noSSEHeader, json.noSSEHeader,
json.xPaddingBytes, json.xPaddingBytes,
json.xmux,
); );
} }
@@ -580,12 +603,6 @@ class SplitHTTPStreamSettings extends XrayCommonClass {
scMinPostsIntervalMs: this.scMinPostsIntervalMs, scMinPostsIntervalMs: this.scMinPostsIntervalMs,
noSSEHeader: this.noSSEHeader, noSSEHeader: this.noSSEHeader,
xPaddingBytes: this.xPaddingBytes, xPaddingBytes: this.xPaddingBytes,
xmux: {
maxConcurrency: this.xmux.maxConcurrency,
maxConnections: this.xmux.maxConnections,
cMaxReuseTimes: this.xmux.cMaxReuseTimes,
cMaxLifetimeMs: this.xmux.cMaxLifetimeMs
}
}; };
} }
} }
@@ -1075,6 +1092,7 @@ class StreamSettings extends XrayCommonClass {
kcpSettings = new KcpStreamSettings(), kcpSettings = new KcpStreamSettings(),
wsSettings = new WsStreamSettings(), wsSettings = new WsStreamSettings(),
httpSettings = new HttpStreamSettings(), httpSettings = new HttpStreamSettings(),
quicSettings = new QuicStreamSettings(),
grpcSettings = new GrpcStreamSettings(), grpcSettings = new GrpcStreamSettings(),
httpupgradeSettings = new HTTPUpgradeStreamSettings(), httpupgradeSettings = new HTTPUpgradeStreamSettings(),
splithttpSettings = new SplitHTTPStreamSettings(), splithttpSettings = new SplitHTTPStreamSettings(),
@@ -1091,6 +1109,7 @@ class StreamSettings extends XrayCommonClass {
this.kcp = kcpSettings; this.kcp = kcpSettings;
this.ws = wsSettings; this.ws = wsSettings;
this.http = httpSettings; this.http = httpSettings;
this.quic = quicSettings;
this.grpc = grpcSettings; this.grpc = grpcSettings;
this.httpupgrade = httpupgradeSettings; this.httpupgrade = httpupgradeSettings;
this.splithttp = splithttpSettings; this.splithttp = splithttpSettings;
@@ -1154,6 +1173,7 @@ class StreamSettings extends XrayCommonClass {
KcpStreamSettings.fromJson(json.kcpSettings), KcpStreamSettings.fromJson(json.kcpSettings),
WsStreamSettings.fromJson(json.wsSettings), WsStreamSettings.fromJson(json.wsSettings),
HttpStreamSettings.fromJson(json.httpSettings), HttpStreamSettings.fromJson(json.httpSettings),
QuicStreamSettings.fromJson(json.quicSettings),
GrpcStreamSettings.fromJson(json.grpcSettings), GrpcStreamSettings.fromJson(json.grpcSettings),
HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings), HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
SplitHTTPStreamSettings.fromJson(json.splithttpSettings), SplitHTTPStreamSettings.fromJson(json.splithttpSettings),
@@ -1174,6 +1194,7 @@ class StreamSettings extends XrayCommonClass {
kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined, kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
wsSettings: network === 'ws' ? this.ws.toJson() : undefined, wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
httpSettings: network === 'http' ? this.http.toJson() : undefined, httpSettings: network === 'http' ? this.http.toJson() : undefined,
quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined, grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined, httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined, splithttpSettings: network === 'splithttp' ? this.splithttp.toJson() : undefined,
@@ -1211,27 +1232,6 @@ class Sniffing extends XrayCommonClass {
} }
} }
class Allocate extends XrayCommonClass {
constructor(
strategy = "always",
refresh = 5,
concurrency = 3,
) {
super();
this.strategy = strategy;
this.refresh = refresh;
this.concurrency = concurrency;
}
static fromJson(json = {}) {
return new Allocate(
json.strategy,
json.refresh,
json.concurrency,
);
}
}
class Inbound extends XrayCommonClass { class Inbound extends XrayCommonClass {
constructor( constructor(
port = RandomUtil.randomIntRange(10000, 60000), port = RandomUtil.randomIntRange(10000, 60000),
@@ -1241,7 +1241,6 @@ class Inbound extends XrayCommonClass {
streamSettings = new StreamSettings(), streamSettings = new StreamSettings(),
tag = '', tag = '',
sniffing = new Sniffing(), sniffing = new Sniffing(),
allocate = new Allocate(),
clientStats = '', clientStats = '',
) { ) {
super(); super();
@@ -1252,7 +1251,6 @@ class Inbound extends XrayCommonClass {
this.stream = streamSettings; this.stream = streamSettings;
this.tag = tag; this.tag = tag;
this.sniffing = sniffing; this.sniffing = sniffing;
this.allocate = allocate;
this.clientStats = clientStats; this.clientStats = clientStats;
} }
getClientStats() { getClientStats() {
@@ -1313,6 +1311,10 @@ class Inbound extends XrayCommonClass {
return this.network === "kcp"; return this.network === "kcp";
} }
get isQuic() {
return this.network === "quic"
}
get isGrpc() { get isGrpc() {
return this.network === "grpc"; return this.network === "grpc";
} }
@@ -1391,6 +1393,18 @@ class Inbound extends XrayCommonClass {
return null; return null;
} }
get quicSecurity() {
return this.stream.quic.security;
}
get quicKey() {
return this.stream.quic.key;
}
get quicType() {
return this.stream.quic.type;
}
get kcpType() { get kcpType() {
return this.stream.kcp.type; return this.stream.kcp.type;
} }
@@ -1410,7 +1424,7 @@ class Inbound extends XrayCommonClass {
canEnableTls() { canEnableTls() {
if (![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false; if (![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false;
return ["tcp", "ws", "http", "grpc", "httpupgrade", "splithttp"].includes(this.network); return ["tcp", "ws", "http", "quic", "grpc", "httpupgrade", "splithttp"].includes(this.network);
} }
//this is used for xtls-rprx-vision //this is used for xtls-rprx-vision
@@ -1443,7 +1457,6 @@ class Inbound extends XrayCommonClass {
this.stream = new StreamSettings(); this.stream = new StreamSettings();
this.tag = ''; this.tag = '';
this.sniffing = new Sniffing(); this.sniffing = new Sniffing();
this.allocate = new Allocate();
} }
genVmessLink(address = '', port = this.port, forceTls, remark = '', clientId, security) { genVmessLink(address = '', port = this.port, forceTls, remark = '', clientId, security) {
@@ -1484,6 +1497,10 @@ class Inbound extends XrayCommonClass {
obj.net = 'h2'; obj.net = 'h2';
obj.path = this.stream.http.path; obj.path = this.stream.http.path;
obj.host = this.stream.http.host.join(','); obj.host = this.stream.http.host.join(',');
} else if (network === 'quic') {
obj.type = this.stream.quic.type;
obj.host = this.stream.quic.security;
obj.path = this.stream.quic.key;
} else if (network === 'grpc') { } else if (network === 'grpc') {
obj.path = this.stream.grpc.serviceName; obj.path = this.stream.grpc.serviceName;
obj.authority = this.stream.grpc.authority; obj.authority = this.stream.grpc.authority;
@@ -1553,6 +1570,12 @@ class Inbound extends XrayCommonClass {
params.set("path", http.path); params.set("path", http.path);
params.set("host", http.host); params.set("host", http.host);
break; break;
case "quic":
const quic = this.stream.quic;
params.set("quicSecurity", quic.security);
params.set("key", quic.key);
params.set("headerType", quic.type);
break;
case "grpc": case "grpc":
const grpc = this.stream.grpc; const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName); params.set("serviceName", grpc.serviceName);
@@ -1668,6 +1691,12 @@ class Inbound extends XrayCommonClass {
params.set("path", http.path); params.set("path", http.path);
params.set("host", http.host); params.set("host", http.host);
break; break;
case "quic":
const quic = this.stream.quic;
params.set("quicSecurity", quic.security);
params.set("key", quic.key);
params.set("headerType", quic.type);
break;
case "grpc": case "grpc":
const grpc = this.stream.grpc; const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName); params.set("serviceName", grpc.serviceName);
@@ -1750,6 +1779,12 @@ class Inbound extends XrayCommonClass {
params.set("path", http.path); params.set("path", http.path);
params.set("host", http.host); params.set("host", http.host);
break; break;
case "quic":
const quic = this.stream.quic;
params.set("quicSecurity", quic.security);
params.set("key", quic.key);
params.set("headerType", quic.type);
break;
case "grpc": case "grpc":
const grpc = this.stream.grpc; const grpc = this.stream.grpc;
params.set("serviceName", grpc.serviceName); params.set("serviceName", grpc.serviceName);
@@ -1923,7 +1958,6 @@ class Inbound extends XrayCommonClass {
StreamSettings.fromJson(json.streamSettings), StreamSettings.fromJson(json.streamSettings),
json.tag, json.tag,
Sniffing.fromJson(json.sniffing), Sniffing.fromJson(json.sniffing),
Allocate.fromJson(json.allocate),
json.clientStats json.clientStats
) )
} }
@@ -1941,7 +1975,6 @@ class Inbound extends XrayCommonClass {
streamSettings: streamSettings, streamSettings: streamSettings,
tag: this.tag, tag: this.tag,
sniffing: this.sniffing.toJson(), sniffing: this.sniffing.toJson(),
allocate: this.allocate.toJson(),
clientStats: this.clientStats clientStats: this.clientStats
}; };
} }
@@ -2513,13 +2546,15 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
address, address,
port, port,
network = 'tcp,udp', network = 'tcp,udp',
followRedirect = false followRedirect = false,
timeout = 30
) { ) {
super(protocol); super(protocol);
this.address = address; this.address = address;
this.port = port; this.port = port;
this.network = network; this.network = network;
this.followRedirect = followRedirect; this.followRedirect = followRedirect;
this.timeout = timeout;
} }
static fromJson(json = {}) { static fromJson(json = {}) {
@@ -2529,6 +2564,7 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
json.port, json.port,
json.network, json.network,
json.followRedirect, json.followRedirect,
json.timeout,
); );
} }
@@ -2538,6 +2574,7 @@ Inbound.DokodemoSettings = class extends Inbound.Settings {
port: this.port, port: this.port,
network: this.network, network: this.network,
followRedirect: this.followRedirect, followRedirect: this.followRedirect,
timeout: this.timeout,
}; };
} }
}; };
@@ -2597,14 +2634,9 @@ Inbound.SocksSettings.SocksAccount = class extends XrayCommonClass {
}; };
Inbound.HttpSettings = class extends Inbound.Settings { Inbound.HttpSettings = class extends Inbound.Settings {
constructor( constructor(protocol, accounts = [new Inbound.HttpSettings.HttpAccount()]) {
protocol,
accounts = [new Inbound.HttpSettings.HttpAccount()],
allowTransparent = false,
) {
super(protocol); super(protocol);
this.accounts = accounts; this.accounts = accounts;
this.allowTransparent = allowTransparent;
} }
addAccount(account) { addAccount(account) {
@@ -2619,14 +2651,12 @@ Inbound.HttpSettings = class extends Inbound.Settings {
return new Inbound.HttpSettings( return new Inbound.HttpSettings(
Protocols.HTTP, Protocols.HTTP,
json.accounts.map(account => Inbound.HttpSettings.HttpAccount.fromJson(account)), json.accounts.map(account => Inbound.HttpSettings.HttpAccount.fromJson(account)),
json.allowTransparent,
); );
} }
toJson() { toJson() {
return { return {
accounts: Inbound.HttpSettings.toJsonArray(this.accounts), accounts: Inbound.HttpSettings.toJsonArray(this.accounts),
allowTransparent: this.allowTransparent,
}; };
} }
}; };

View File

@@ -83,6 +83,10 @@ func (a *IndexController) login(c *gin.Context) {
logger.Warning("Unable to get session's max age from DB") logger.Warning("Unable to get session's max age from DB")
} }
if sessionMaxAge <= 0 {
sessionMaxAge = 60
}
err = session.SetMaxAge(c, sessionMaxAge*60) err = session.SetMaxAge(c, sessionMaxAge*60)
if err != nil { if err != nil {
logger.Warning("Unable to set session's max age") logger.Warning("Unable to set session's max age")

View File

@@ -42,12 +42,12 @@ func jsonMsgObj(c *gin.Context, msg string, obj interface{}, err error) {
if err == nil { if err == nil {
m.Success = true m.Success = true
if msg != "" { if msg != "" {
m.Msg = msg + " " + I18nWeb(c, "success") m.Msg = msg + I18nWeb(c, "success")
} }
} else { } else {
m.Success = false m.Success = false
m.Msg = msg + " " + I18nWeb(c, "fail") + ": " + err.Error() m.Msg = msg + I18nWeb(c, "fail") + ": " + err.Error()
logger.Warning(msg+" "+I18nWeb(c, "fail")+": ", err) logger.Warning(msg+I18nWeb(c, "fail")+": ", err)
} }
c.JSON(http.StatusOK, m) c.JSON(http.StatusOK, m)
} }

View File

@@ -52,7 +52,7 @@ type AllSetting struct {
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"` SubJsonPath string `json:"subJsonPath" form:"subJsonPath"`
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"` SubJsonURI string `json:"subJsonURI" form:"subJsonURI"`
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"` SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"`
SubJsonNoises string `json:"subJsonNoises" form:"subJsonNoises"` SubJsonNoise string `json:"subJsonNoise" form:"subJsonNoise"`
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"` SubJsonMux string `json:"subJsonMux" form:"subJsonMux"`
SubJsonRules string `json:"subJsonRules" form:"subJsonRules"` SubJsonRules string `json:"subJsonRules" form:"subJsonRules"`
Datepicker string `json:"datepicker" form:"datepicker"` Datepicker string `json:"datepicker" form:"datepicker"`

View File

@@ -449,7 +449,7 @@
<a-row justify="center" class="centered"> <a-row justify="center" class="centered">
<a-col :span="24"> <a-col :span="24">
<a-select ref="selectLang" v-model="lang" <a-select ref="selectLang" v-model="lang"
@change="setLang(lang)" style="width: 200px;" @change="setLang(lang)" style="width: 150px;"
:dropdown-class-name="themeSwitcher.currentTheme"> :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option :value="l.value" label="English" v-for="l in supportLangs"> <a-select-option :value="l.value" label="English" v-for="l in supportLangs">
<span role="img" aria-label="l.name" v-text="l.icon"></span> <span role="img" aria-label="l.name" v-text="l.icon"></span>

View File

@@ -28,7 +28,7 @@
<a-form-item label='{{ i18n "pages.client.clientCount" }}' v-if="clientsBulkModal.emailMethod < 2"> <a-form-item label='{{ i18n "pages.client.clientCount" }}' v-if="clientsBulkModal.emailMethod < 2">
<a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number> <a-input-number v-model="clientsBulkModal.quantity" :min="1" :max="100"></a-input-number>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "security" }}' v-if="inbound.protocol === Protocols.VMESS"> <a-form-item v-if="inbound.protocol === Protocols.VMESS" label='Security'>
<a-select v-model="clientsBulkModal.security" :dropdown-class-name="themeSwitcher.currentTheme"> <a-select v-model="clientsBulkModal.security" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>

View File

@@ -1,7 +1,5 @@
{{define "dnsModal"}} {{define "dnsModal"}}
<a-modal id="dns-modal" v-model="dnsModal.visible" :title="dnsModal.title" @ok="dnsModal.ok" :closable="true" <a-modal id="dns-modal" v-model="dnsModal.visible" :title="dnsModal.title" @ok="dnsModal.ok" :closable="true" :mask-closable="false" :ok-text="dnsModal.okText" cancel-text='{{ i18n "close" }}' :class="themeSwitcher.currentTheme">
:mask-closable="false" :ok-text="dnsModal.okText" cancel-text='{{ i18n "close" }}'
:class="themeSwitcher.currentTheme">
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }"> <a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<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>
@@ -10,29 +8,18 @@
<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">
<a-input v-model.trim="dnsModal.dnsServer.domains[index]"> <a-input v-model.trim="dnsModal.dnsServer.domains[index]">
<a-button icon="minus" size="small" slot="addonAfter" <a-button icon="minus" size="small" slot="addonAfter" @click="dnsModal.dnsServer.domains.splice(index,1)"></a-button>
@click="dnsModal.dnsServer.domains.splice(index,1)"></a-button>
</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-form-item label='{{ i18n "pages.xray.dns.strategy" }}' v-if="isAdvanced">
<a-select v-model="dnsModal.dnsServer.queryStrategy" style="width: 100%" <a-select v-model="dnsModal.dnsServer.queryStrategy" 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']"> [[ l ]] </a-select-option> <a-select-option :value="l" :label="l" v-for="l in ['UseIP', 'UseIPv4', 'UseIPv6']"> [[ l ]] </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label='Skip Fallback' v-if="isAdvanced"> <a-form-item label='Skip Fallback' v-if="isAdvanced">
<a-switch v-model="dnsModal.dnsServer.skipFallback"></a-switch> <a-switch v-model="dnsModal.dnsServer.skipFallback"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label='{{ i18n "pages.xray.dns.expectIPs"}}'>
<a-button icon="plus" size="small" type="primary" @click="dnsModal.dnsServer.expectIPs.push('')"></a-button>
<template v-for="(domain, index) in dnsModal.dnsServer.expectIPs">
<a-input v-model.trim="dnsModal.dnsServer.expectIPs[index]">
<a-button icon="minus" size="small" slot="addonAfter"
@click="dnsModal.dnsServer.expectIPs.splice(index,1)"></a-button>
</a-input>
</template>
</a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
<script> <script>
@@ -45,24 +32,20 @@
dnsServer: { dnsServer: {
address: "localhost", address: "localhost",
domains: [], domains: [],
expectIPs: [],
queryStrategy: 'UseIP', queryStrategy: 'UseIP',
skipFallback: true, skipFallback: true,
}, },
ok() { ok() {
domains = dnsModal.dnsServer.domains.filter(d => d.length > 0); domains = dnsModal.dnsServer.domains.filter(d => d.length > 0);
expectIPs = dnsModal.dnsServer.expectIPs.filter(ip => ip.length > 0);
dnsModal.dnsServer.domains = domains; dnsModal.dnsServer.domains = domains;
dnsModal.dnsServer.expectIPs = expectIPs; newDnsServer = domains.length > 0 ? dnsModal.dnsServer : dnsModal.dnsServer.address;
newDnsServer = (domains.length > 0 || expectIPs.length > 0) ? dnsModal.dnsServer : dnsModal.dnsServer.address;
ObjectUtil.execute(dnsModal.confirm, newDnsServer); ObjectUtil.execute(dnsModal.confirm, newDnsServer);
}, },
show({ show({
title = '', title = '',
okText = '{{ i18n "confirm" }}', okText = '{{ i18n "confirm" }}',
dnsServer, dnsServer,
confirm = (dnsServer) => { }, confirm = (dnsServer) => {},
isEdit = false isEdit = false
}) { }) {
this.title = title; this.title = title;
@@ -76,7 +59,6 @@
this.dnsServer = { this.dnsServer = {
address: dnsServer ?? "", address: dnsServer ?? "",
domains: [], domains: [],
expectIPs: [],
queryStrategy: 'UseIP', queryStrategy: 'UseIP',
skipFallback: true, skipFallback: true,
} }
@@ -85,7 +67,6 @@
this.dnsServer = { this.dnsServer = {
address: "localhost", address: "localhost",
domains: [], domains: [],
expectIPs: [],
queryStrategy: 'UseIP', queryStrategy: 'UseIP',
skipFallback: true, skipFallback: true,
} }
@@ -104,8 +85,8 @@
}, },
computed: { computed: {
isAdvanced: { isAdvanced: {
get: function () { get: function() {
return dnsModal.dnsServer.domains.length > 0; return dnsModal.dnsServer.domains.length > 0
} }
} }
} }

View File

@@ -1,15 +0,0 @@
{{define "form/allocate"}}
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item label='Strategy'>
<a-select v-model="inbound.allocate.strategy" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="s in ['always','random']" :value="s">[[ s ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='Refresh'>
<a-input-number v-model.number="inbound.allocate.refresh" min="0"></a-input-number>
</a-form-item>
<a-form-item label='Concurrency'>
<a-input-number v-model.number="inbound.allocate.concurrency" min="0"></a-input-number>
</a-form-item>
</a-form>
{{end}}

View File

@@ -39,7 +39,7 @@
</template> </template>
<a-input v-model.trim="client.id"></a-input> <a-input v-model.trim="client.id"></a-input>
</a-form-item> </a-form-item>
<a-form-item v-if="inbound.protocol === Protocols.VMESS" label='{{ i18n "security" }}'> <a-form-item v-if="inbound.protocol === Protocols.VMESS" label='Security'>
<a-select v-model="client.security" :dropdown-class-name="themeSwitcher.currentTheme"> <a-select v-model="client.security" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
@@ -104,7 +104,7 @@
</a-textarea> </a-textarea>
</a-form> </a-form>
</a-form-item> </a-form-item>
<a-form-item v-if="inbound.stream.isXtls" label='Flow'> <a-form-item v-if="inbound.xtls" label='Flow'>
<a-select v-model="client.flow" :dropdown-class-name="themeSwitcher.currentTheme"> <a-select v-model="client.flow" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="" selected>{{ i18n "none" }}</a-select-option> <a-select-option value="" selected>{{ i18n "none" }}</a-select-option>
<a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in XTLS_FLOW_CONTROL" :value="key">[[ key ]]</a-select-option>

View File

@@ -115,19 +115,7 @@
</template> </template>
<!-- sniffing --> <!-- sniffing -->
<a-collapse> <template>
<a-collapse-panel header='Sniffing'> {{template "form/sniffing"}}
{{template "form/sniffing"}} </template>
</a-collapse-panel>
</a-collapse>
<!-- allocate -->
<!-- Temporarily disabled until we accepts range for port allocation
<a-collapse>
<a-collapse-panel header='Allocate'>
{{template "form/allocate"}}
</a-collapse-panel>
</a-collapse>
-->
{{end}} {{end}}

View File

@@ -22,6 +22,9 @@
<a-select-option v-for="s in OutboundDomainStrategies" :value="s">[[ s ]]</a-select-option> <a-select-option v-for="s in OutboundDomainStrategies" :value="s">[[ s ]]</a-select-option>
</a-select> </a-select>
</a-form-item> </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='Redirect'> <a-form-item label='Redirect'>
<a-input v-model="outbound.settings.redirect"></a-input> <a-input v-model="outbound.settings.redirect"></a-input>
</a-form-item> </a-form-item>
@@ -43,39 +46,16 @@
<a-input v-model.trim="outbound.settings.fragment.interval"></a-input> <a-input v-model.trim="outbound.settings.fragment.interval"></a-input>
</a-form-item> </a-form-item>
</template> </template>
<a-form-item label='Noise'>
<!-- Switch for Noises --> <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 label='Noises'>
<a-switch :checked="outbound.settings.noises.length > 0"
@change="checked => outbound.settings.noises = checked ? [new Outbound.FreedomSettings.Noise()] : []">
</a-switch>
</a-form-item> </a-form-item>
<template v-if="Object.keys(outbound.settings.noise).length >0">
<!-- Add Noise Button --> <a-form-item label='Packet'>
<template v-if="outbound.settings.noises.length > 0"> <a-input v-model.trim="outbound.settings.noise.packet"></a-input>
<a-form-item label="Noises"> </a-form-item>
<a-button icon="plus" type="primary" size="small" @click="outbound.settings.addNoise()"></a-button> <a-form-item label='Delay'>
<a-input v-model.trim="outbound.settings.noise.delay"></a-input>
</a-form-item> </a-form-item>
<!-- Noise Configurations -->
<a-form v-for="(noise, index) in outbound.settings.noises" :key="index" :colon="false" :label-col="{ md: {span:8} }"
:wrapper-col="{ md: {span:14} }">
<a-divider style="margin:0;"> Noise [[ index + 1 ]]
<a-icon v-if="outbound.settings.noises.length > 1" type="delete" @click="() => outbound.settings.delNoise(index)"
style="color: rgb(255, 77, 79); cursor: pointer;"></a-icon>
</a-divider>
<a-form-item label='Type'>
<a-select v-model="noise.type" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="s in ['rand','base64','str']" :value="s">[[ s ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='Packet'>
<a-input v-model.trim="noise.packet"></a-input>
</a-form-item>
<a-form-item label='Delay'>
<a-input v-model.trim="noise.delay"></a-input>
</a-form-item>
</a-form>
</template> </template>
</template> </template>
@@ -95,14 +75,6 @@
<a-select-option v-for="s in ['udp','tcp']" :value="s">[[ s ]]</a-select-option> <a-select-option v-for="s in ['udp','tcp']" :value="s">[[ s ]]</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label='non-IP queries'>
<a-select v-model="outbound.settings.nonIPQuery" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="s in ['drop','skip']" :value="s">[[ s ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item v-if="outbound.settings.nonIPQuery === 'skip'" label='Block Types' >
<a-input v-model.number="outbound.settings.blockTypes"></a-input>
</a-form-item>
</template> </template>
<!-- wireguard settings --> <!-- wireguard settings -->
@@ -207,15 +179,11 @@
<a-form-item label='ID'> <a-form-item label='ID'>
<a-input v-model.trim="outbound.settings.id"></a-input> <a-input v-model.trim="outbound.settings.id"></a-input>
</a-form-item> </a-form-item>
<a-form-item label='Security'>
<!-- vmess settings --> <a-select v-model="outbound.settings.security" :dropdown-class-name="themeSwitcher.currentTheme">
<template v-if="outbound.protocol === Protocols.VMess"> <a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
<a-form-item label='Security'> </a-select>
<a-select v-model="outbound.settings.security" :dropdown-class-name="themeSwitcher.currentTheme"> </a-form-item>
<a-select-option v-for="key in USERS_SECURITY" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
</template>
<!-- vless settings --> <!-- vless settings -->
<template v-if="outbound.canEnableTlsFlow()"> <template v-if="outbound.canEnableTlsFlow()">
@@ -271,6 +239,7 @@
<a-select-option value="kcp">mKCP</a-select-option> <a-select-option value="kcp">mKCP</a-select-option>
<a-select-option value="ws">WebSocket</a-select-option> <a-select-option value="ws">WebSocket</a-select-option>
<a-select-option value="http">H2</a-select-option> <a-select-option value="http">H2</a-select-option>
<a-select-option value="quic">QUIC</a-select-option>
<a-select-option value="grpc">gRPC</a-select-option> <a-select-option value="grpc">gRPC</a-select-option>
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option> <a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
<a-select-option value="splithttp">SplitHTTP</a-select-option> <a-select-option value="splithttp">SplitHTTP</a-select-option>
@@ -349,6 +318,30 @@
</a-form-item> </a-form-item>
</template> </template>
<!-- quic -->
<template v-if="outbound.stream.network === 'quic'">
<a-form-item label='{{ i18n "pages.inbounds.stream.quic.encryption" }}'>
<a-select v-model="outbound.stream.quic.security" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="none">None</a-select-option>
<a-select-option value="aes-128-gcm">AES-128-GCM</a-select-option>
<a-select-option value="chacha20-poly1305">CHACHA20-POLY1305</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='{{ i18n "password" }}'>
<a-input v-model.trim="outbound.stream.quic.key"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "camouflage" }}'>
<a-select v-model="outbound.stream.quic.type" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="none">None</a-select-option>
<a-select-option value="srtp">SRTP</a-select-option>
<a-select-option value="utp">uTP</a-select-option>
<a-select-option value="wechat-video">WeChat</a-select-option>
<a-select-option value="dtls">DTLS 1.2</a-select-option>
<a-select-option value="wireguard">WireGuard</a-select-option>
</a-select>
</a-form-item>
</template>
<!-- grpc --> <!-- grpc -->
<template v-if="outbound.stream.network === 'grpc'"> <template v-if="outbound.stream.network === 'grpc'">
<a-form-item label='Service Name'> <a-form-item label='Service Name'>

View File

@@ -16,5 +16,8 @@
<a-form-item label='Follow Redirect'> <a-form-item label='Follow Redirect'>
<a-switch v-model="inbound.settings.followRedirect"></a-switch> <a-switch v-model="inbound.settings.followRedirect"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label='Timeout'>
<a-input-number v-model.number="inbound.settings.timeout" :min="0"></a-input-number>
</a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -19,8 +19,5 @@
</template> </template>
</a-input> </a-input>
</a-input-group> </a-input-group>
<a-form-item label="Allow Transparent">
<a-switch v-model="inbound.settings.allowTransparent" />
</a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -10,7 +10,7 @@
<tr class="client-table-header"> <tr class="client-table-header">
<th>{{ i18n "pages.inbounds.email" }}</th> <th>{{ i18n "pages.inbounds.email" }}</th>
<th>ID</th> <th>ID</th>
<th>{{ i18n "security" }}</th> <th>Security</th>
</tr> </tr>
<tr v-for="(client, index) in inbound.settings.vmesses" :class="index % 2 == 1 ? 'client-table-odd-row' : ''"> <tr v-for="(client, index) in inbound.settings.vmesses" :class="index % 2 == 1 ? 'client-table-odd-row' : ''">
<td>[[ client.email ]]</td> <td>[[ client.email ]]</td>

View File

@@ -1,56 +0,0 @@
{{define "form/realitySettings"}}
<template>
<a-form-item label='Show'>
<a-switch v-model="inbound.stream.reality.show"></a-switch>
</a-form-item>
<a-form-item label='Xver'>
<a-input-number v-model.number="inbound.stream.reality.xver" :min="0"></a-input-number>
</a-form-item>
<a-form-item label='uTLS'>
<a-select v-model="inbound.stream.reality.settings.fingerprint" style="width: 50%"
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='Dest'>
<a-input v-model.trim="inbound.stream.reality.dest"></a-input>
</a-form-item>
<a-form-item label='SNI'>
<a-input v-model.trim="inbound.stream.reality.serverNames"></a-input>
</a-form-item>
<a-form-item label='Max Time Diff (ms)'>
<a-input-number v-model.number="inbound.stream.reality.maxTimediff" :min="0"></a-input-number>
</a-form-item>
<!-- we also have this but i think it's not necessary
<a-form-item label='Min Client'>
<a-input v-model.trim="inbound.stream.reality.minClient"></a-input>
</a-form-item>
<a-form-item label='Max Client'>
<a-input v-model.trim="inbound.stream.reality.maxClient"></a-input>
</a-form-item>
-->
<a-form-item>
<template slot="label">
<a-tooltip>
<template slot="title">
<span>{{ i18n "reset" }}</span>
</template> Short IDs <a-icon @click="inbound.stream.reality.shortIds = RandomUtil.randomShortIds()"
type="sync"></a-icon>
</a-tooltip>
</template>
<a-input v-model.trim="inbound.stream.reality.shortIds"></a-input>
</a-form-item>
<a-form-item label='SpiderX'>
<a-input v-model.trim="inbound.stream.reality.settings.spiderX"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
<a-input v-model.trim="inbound.stream.reality.privateKey"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
<a-input v-model.trim="inbound.stream.reality.settings.publicKey"></a-input>
</a-form-item>
<a-form-item label=" ">
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Cert</a-button>
</a-form-item>
</template>
{{end}}

View File

@@ -1,8 +1,9 @@
{{define "form/sniffing"}} {{define "form/sniffing"}}
<a-divider style="margin:5px 0 0;"></a-divider>
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }"> <a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item> <a-form-item>
<span slot="label"> <span slot="label">
{{ i18n "enabled" }} Sniffing
<a-tooltip> <a-tooltip>
<template slot="title"> <template slot="title">
<span>{{ i18n "pages.inbounds.noRecommendKeepDefault" }}</span> <span>{{ i18n "pages.inbounds.noRecommendKeepDefault" }}</span>

View File

@@ -0,0 +1,33 @@
{{define "form/streamQUIC"}}
<a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
<a-form-item label='{{ i18n "pages.inbounds.stream.quic.encryption" }}'>
<a-select v-model="inbound.stream.quic.security" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="none">None</a-select-option>
<a-select-option value="aes-128-gcm">AES-128-GCM</a-select-option>
<a-select-option value="chacha20-poly1305">CHACHA20-POLY1305</a-select-option>
</a-select>
</a-form-item>
<a-form-item>
<template slot="label">
<a-tooltip>
<template slot="title">
<span>{{ i18n "reset" }}</span>
</template>
{{ i18n "password" }}
<a-icon @click="inbound.stream.quic.key = RandomUtil.randomSeq(10)"type="sync"> </a-icon>
</a-tooltip>
</template>
<a-input v-model.trim="inbound.stream.quic.key"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "camouflage" }}'>
<a-select v-model="inbound.stream.quic.type" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="none">None</a-select-option>
<a-select-option value="srtp">SRTP</a-select-option>
<a-select-option value="utp">uTP</a-select-option>
<a-select-option value="wechat-video">WeChat</a-select-option>
<a-select-option value="dtls">DTLS 1.2</a-select-option>
<a-select-option value="wireguard">WireGuard</a-select-option>
</a-select>
</a-form-item>
</a-form>
{{end}}

View File

@@ -4,10 +4,11 @@
<a-form-item label='{{ i18n "transmission" }}'> <a-form-item label='{{ i18n "transmission" }}'>
<a-select v-model="inbound.stream.network" style="width: 75%" @change="streamNetworkChange" <a-select v-model="inbound.stream.network" style="width: 75%" @change="streamNetworkChange"
:dropdown-class-name="themeSwitcher.currentTheme"> :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value="tcp">TCP (RAW)</a-select-option> <a-select-option value="tcp">TCP</a-select-option>
<a-select-option value="kcp">mKCP</a-select-option> <a-select-option value="kcp">mKCP</a-select-option>
<a-select-option value="ws">WebSocket</a-select-option> <a-select-option value="ws">WebSocket</a-select-option>
<a-select-option value="http">H2</a-select-option> <a-select-option value="http">H2</a-select-option>
<a-select-option value="quic">QUIC</a-select-option>
<a-select-option value="grpc">gRPC</a-select-option> <a-select-option value="grpc">gRPC</a-select-option>
<a-select-option value="httpupgrade">HTTPUpgrade</a-select-option> <a-select-option value="httpupgrade">HTTPUpgrade</a-select-option>
<a-select-option value="splithttp">SplitHTTP</a-select-option> <a-select-option value="splithttp">SplitHTTP</a-select-option>
@@ -35,6 +36,11 @@
{{template "form/streamHTTP"}} {{template "form/streamHTTP"}}
</template> </template>
<!-- quic -->
<template v-if="inbound.stream.network === 'quic'">
{{template "form/streamQUIC"}}
</template>
<!-- grpc --> <!-- grpc -->
<template v-if="inbound.stream.network === 'grpc'"> <template v-if="inbound.stream.network === 'grpc'">
{{template "form/streamGRPC"}} {{template "form/streamGRPC"}}

View File

@@ -34,17 +34,5 @@
<a-form-item label="No SSE Header"> <a-form-item label="No SSE Header">
<a-switch v-model="inbound.stream.splithttp.noSSEHeader"></a-switch> <a-switch v-model="inbound.stream.splithttp.noSSEHeader"></a-switch>
</a-form-item> </a-form-item>
<a-form-item label="Max Concurrency">
<a-input-number v-model="inbound.stream.splithttp.xmux.maxConcurrency"></a-input-number>
</a-form-item>
<a-form-item label="Max Connections">
<a-input-number v-model="inbound.stream.splithttp.xmux.maxConnections"></a-input-number>
</a-form-item>
<a-form-item label="Max Reuse Times">
<a-input-number v-model="inbound.stream.splithttp.xmux.cMaxReuseTimes"></a-input-number>
</a-form-item>
<a-form-item label="Max Lifetime (ms)">
<a-input-number v-model="inbound.stream.splithttp.xmux.cMaxLifetimeMs"></a-input-number>
</a-form-item>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -34,19 +34,16 @@
</a-form-item> </a-form-item>
<a-form-item label="Min/Max Version"> <a-form-item label="Min/Max Version">
<a-input-group compact> <a-input-group compact>
<a-select v-model="inbound.stream.tls.minVersion" style="width: 50%" <a-select v-model="inbound.stream.tls.minVersion" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
<a-select v-model="inbound.stream.tls.maxVersion" style="width: 50%" <a-select v-model="inbound.stream.tls.maxVersion" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in TLS_VERSION_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
</a-input-group> </a-input-group>
</a-form-item> </a-form-item>
<a-form-item label="uTLS"> <a-form-item label="uTLS">
<a-select v-model="inbound.stream.tls.settings.fingerprint" style="width: 50%" <a-select v-model="inbound.stream.tls.settings.fingerprint" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option value=''>None</a-select-option> <a-select-option value=''>None</a-select-option>
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option> <a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
</a-select> </a-select>
@@ -74,10 +71,8 @@
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button> <a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button> <a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
</a-radio-group> </a-radio-group>
<a-button icon="plus" v-if="index === 0" type="primary" size="small" @click="inbound.stream.tls.addCert()" <a-button icon="plus" v-if="index === 0" type="primary" size="small" @click="inbound.stream.tls.addCert()" style="margin-left: 10px"></a-button>
style="margin-left: 10px"></a-button> <a-button icon="minus" v-if="inbound.stream.tls.certs.length>1" type="primary" size="small" @click="inbound.stream.tls.removeCert(index)" style="margin-left: 10px"></a-button>
<a-button icon="minus" v-if="inbound.stream.tls.certs.length>1" type="primary" size="small"
@click="inbound.stream.tls.removeCert(index)" style="margin-left: 10px"></a-button>
</a-form-item> </a-form-item>
<template v-if="cert.useFile"> <template v-if="cert.useFile">
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'> <a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
@@ -87,8 +82,7 @@
<a-input v-model.trim="cert.keyFile"></a-input> <a-input v-model.trim="cert.keyFile"></a-input>
</a-form-item> </a-form-item>
<a-form-item label=" "> <a-form-item label=" ">
<a-button type="primary" icon="import" @click="setDefaultCertData(index)"> <a-button type="primary" icon="import" @click="setDefaultCertData(index)">{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
</a-form-item> </a-form-item>
</template> </template>
<template v-else> <template v-else>
@@ -117,13 +111,101 @@
</template> </template>
<!-- xtls settings --> <!-- xtls settings -->
<template v-else-if="inbound.stream.isXtls"> <template v-else-if="inbound.xtls">
{{template "form/xtlsSettings"}} <a-form-item label="SNI" placeholder="Server Name Indication">
<a-input v-model.trim="inbound.stream.xtls.sni"></a-input>
</a-form-item>
<a-form-item label="ALPN">
<a-select mode="multiple" :dropdown-class-name="themeSwitcher.currentTheme" v-model="inbound.stream.xtls.alpn">
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Allow Insecure">
<a-switch v-model="inbound.stream.xtls.settings.allowInsecure"></a-switch>
</a-form-item>
<template v-for="cert,index in inbound.stream.xtls.certs">
<a-form-item label='{{ i18n "certificate" }}'>
<a-radio-group v-model="cert.useFile" button-style="solid">
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
</a-radio-group>
<a-button icon="plus" v-if="index === 0" type="primary" size="small" @click="inbound.stream.xtls.addCert()" style="margin-left: 10px"></a-button>
<a-button icon="minus" v-if="inbound.stream.xtls.certs.length>1" type="primary" size="small" @click="inbound.stream.xtls.removeCert(index)" style="margin-left: 10px"></a-button>
</a-form-item>
<template v-if="cert.useFile">
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
<a-input v-model.trim="cert.certFile"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
<a-input v-model.trim="cert.keyFile"></a-input>
</a-form-item>
<a-form-item label=" ">
<a-button type="primary" icon="import" @click="setDefaultCertXtls(index)">{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
</a-form-item>
</template>
<template v-else>
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
<a-input type="textarea" :rows="3" v-model="cert.cert"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
<a-input type="textarea" :rows="3" v-model="cert.key"></a-input>
</a-form-item>
</template>
<a-form-item label='OCSP stapling'>
<a-input-number v-model.number="cert.ocspStapling" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="One Time Loading">
<a-switch v-model="cert.oneTimeLoading"></a-switch>
</a-form-item>
<a-form-item label='Usage Option'>
<a-select v-model="cert.usage" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in USAGE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
</template>
</template> </template>
<!-- reality settings --> <!-- reality settings -->
<template v-if="inbound.stream.isReality"> <template v-if="inbound.stream.isReality">
{{template "form/realitySettings"}} <a-form-item label='Show'>
<a-switch v-model="inbound.stream.reality.show"></a-switch>
</a-form-item>
<a-form-item label='Xver'>
<a-input-number v-model.number="inbound.stream.reality.xver" :min="0"></a-input-number>
</a-form-item>
<a-form-item label='uTLS'>
<a-select v-model="inbound.stream.reality.settings.fingerprint" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in UTLS_FINGERPRINT" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label='Dest'>
<a-input v-model.trim="inbound.stream.reality.dest"></a-input>
</a-form-item>
<a-form-item label='SNI'>
<a-input v-model.trim="inbound.stream.reality.serverNames"></a-input>
</a-form-item>
<a-form-item>
<template slot="label">
<a-tooltip>
<template slot="title">
<span>{{ i18n "reset" }}</span>
</template> Short IDs <a-icon @click="inbound.stream.reality.shortIds = RandomUtil.randomShortIds()" type="sync"></a-icon>
</a-tooltip>
</template>
<a-input v-model.trim="inbound.stream.reality.shortIds"></a-input>
</a-form-item>
<a-form-item label='SpiderX'>
<a-input v-model.trim="inbound.stream.reality.settings.spiderX"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
<a-input v-model.trim="inbound.stream.reality.privateKey"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
<a-input v-model.trim="inbound.stream.reality.settings.publicKey"></a-input>
</a-form-item>
<a-form-item label=" ">
<a-button type="primary" icon="import" @click="getNewX25519Cert">Get New Cert</a-button>
</a-form-item>
</template> </template>
</a-form> </a-form>
{{end}} {{end}}

View File

@@ -1,58 +0,0 @@
{{define "form/xtlsSettings"}}
<template>
<a-form-item label="SNI" placeholder="Server Name Indication">
<a-input v-model.trim="inbound.stream.xtls.sni"></a-input>
</a-form-item>
<a-form-item label="ALPN">
<a-select mode="multiple" :dropdown-class-name="themeSwitcher.currentTheme" v-model="inbound.stream.xtls.alpn">
<a-select-option v-for="alpn in ALPN_OPTION" :value="alpn">[[ alpn ]]</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="Allow Insecure">
<a-switch v-model="inbound.stream.xtls.settings.allowInsecure"></a-switch>
</a-form-item>
<template v-for="cert,index in inbound.stream.xtls.certs">
<a-form-item label='{{ i18n "certificate" }}'>
<a-radio-group v-model="cert.useFile" button-style="solid">
<a-radio-button :value="true">{{ i18n "pages.inbounds.certificatePath" }}</a-radio-button>
<a-radio-button :value="false">{{ i18n "pages.inbounds.certificateContent" }}</a-radio-button>
</a-radio-group>
<a-button icon="plus" v-if="index === 0" type="primary" size="small" @click="inbound.stream.xtls.addCert()"
style="margin-left: 10px"></a-button>
<a-button icon="minus" v-if="inbound.stream.xtls.certs.length>1" type="primary" size="small"
@click="inbound.stream.xtls.removeCert(index)" style="margin-left: 10px"></a-button>
</a-form-item>
<template v-if="cert.useFile">
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
<a-input v-model.trim="cert.certFile"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
<a-input v-model.trim="cert.keyFile"></a-input>
</a-form-item>
<a-form-item label=" ">
<a-button type="primary" icon="import" @click="setDefaultCertXtls(index)">
{{ i18n "pages.inbounds.setDefaultCert" }}</a-button>
</a-form-item>
</template>
<template v-else>
<a-form-item label='{{ i18n "pages.inbounds.publicKey" }}'>
<a-input type="textarea" :rows="3" v-model="cert.cert"></a-input>
</a-form-item>
<a-form-item label='{{ i18n "pages.inbounds.privatekey" }}'>
<a-input type="textarea" :rows="3" v-model="cert.key"></a-input>
</a-form-item>
</template>
<a-form-item label='OCSP stapling'>
<a-input-number v-model.number="cert.ocspStapling" :min="0"></a-input-number>
</a-form-item>
<a-form-item label="One Time Loading">
<a-switch v-model="cert.oneTimeLoading"></a-switch>
</a-form-item>
<a-form-item label='Usage Option'>
<a-select v-model="cert.usage" style="width: 50%" :dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option v-for="key in USAGE_OPTION" :value="key">[[ key ]]</a-select-option>
</a-select>
</a-form-item>
</template>
</template>
{{end}}

View File

@@ -58,6 +58,26 @@
</td> </td>
</tr> </tr>
</template> </template>
<template v-if="inbound.isQuic">
<tr>
<td>quic {{ i18n "encryption" }}</td>
<td>
<a-tag>[[ inbound.quicSecurity ]]</a-tag>
</td>
</tr>
<tr>
<td>quic {{ i18n "password" }}</td>
<td>
<a-tag>[[ inbound.quicKey ]]</a-tag>
</td>
</tr>
<tr>
<td>quic {{ i18n "camouflage" }}</td>
<td>
<a-tag>[[ inbound.quicType ]]</a-tag>
</td>
</tr>
</template>
<template v-if="inbound.isKcp"> <template v-if="inbound.isKcp">
<tr> <tr>
<td>kcp {{ i18n "encryption" }}</td> <td>kcp {{ i18n "encryption" }}</td>
@@ -139,12 +159,6 @@
<a-tag>[[ infoModal.clientSettings.id ]]</a-tag> <a-tag>[[ infoModal.clientSettings.id ]]</a-tag>
</td> </td>
</tr> </tr>
<tr v-if="dbInbound.isVMess">
<td>{{ i18n "security" }}</td>
<td>
<a-tag>[[ infoModal.clientSettings.security ]]</a-tag>
</td>
</tr>
<tr v-if="infoModal.inbound.canEnableTlsFlow()"> <tr v-if="infoModal.inbound.canEnableTlsFlow()">
<td>Flow</td> <td>Flow</td>
<td v-if="infoModal.clientSettings.flow"> <td v-if="infoModal.clientSettings.flow">

View File

@@ -733,7 +733,7 @@
this.inbounds.push(to_inbound); this.inbounds.push(to_inbound);
this.dbInbounds.push(dbInbound); this.dbInbounds.push(dbInbound);
if ([Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(inbound.protocol)) { if ([Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(inbound.protocol)) {
if (dbInbound.isSS && (!to_inbound.isSSMultiUser)) { if (inbound.protocol === Protocols.SHADOWSOCKS && (!to_inbound.isSSMultiUser)) {
continue; continue;
} }
this.clientCount[inbound.id] = this.getClientCounts(inbound, to_inbound); this.clientCount[inbound.id] = this.getClientCounts(inbound, to_inbound);
@@ -935,7 +935,6 @@
settings: Inbound.Settings.getSettings(baseInbound.protocol).toString(), settings: Inbound.Settings.getSettings(baseInbound.protocol).toString(),
streamSettings: baseInbound.stream.toString(), streamSettings: baseInbound.stream.toString(),
sniffing: baseInbound.sniffing.toString(), sniffing: baseInbound.sniffing.toString(),
allocate: baseInbound.allocate.toString(),
}; };
await this.submit('/panel/inbound/add', data, inModal); await this.submit('/panel/inbound/add', data, inModal);
}, },
@@ -981,7 +980,6 @@
}; };
if (inbound.canEnableStream()) data.streamSettings = inbound.stream.toString(); if (inbound.canEnableStream()) data.streamSettings = inbound.stream.toString();
data.sniffing = inbound.sniffing.toString(); data.sniffing = inbound.sniffing.toString();
data.allocate = inbound.allocate.toString();
await this.submit('/panel/inbound/add', data, inModal); await this.submit('/panel/inbound/add', data, inModal);
}, },
@@ -1001,7 +999,6 @@
}; };
if (inbound.canEnableStream()) data.streamSettings = inbound.stream.toString(); if (inbound.canEnableStream()) data.streamSettings = inbound.stream.toString();
data.sniffing = inbound.sniffing.toString(); data.sniffing = inbound.sniffing.toString();
data.allocate = inbound.allocate.toString();
await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal); await this.submit(`/panel/inbound/update/${dbInbound.id}`, data, inModal);
}, },

View File

@@ -138,7 +138,7 @@
<setting-list-item type="text" title='{{ i18n "pages.settings.publicKeyPath"}}' desc='{{ i18n "pages.settings.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item> <setting-list-item type="text" title='{{ i18n "pages.settings.publicKeyPath"}}' desc='{{ i18n "pages.settings.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.settings.privateKeyPath"}}' desc='{{ i18n "pages.settings.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item> <setting-list-item type="text" title='{{ i18n "pages.settings.privateKeyPath"}}' desc='{{ i18n "pages.settings.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
<setting-list-item type="text" title='{{ i18n "pages.settings.panelUrlPath"}}' desc='{{ i18n "pages.settings.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item> <setting-list-item type="text" title='{{ i18n "pages.settings.panelUrlPath"}}' desc='{{ i18n "pages.settings.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.settings.sessionMaxAge" }}' desc='{{ i18n "pages.settings.sessionMaxAgeDesc" }}' v-model="allSetting.sessionMaxAge" :min="60"></setting-list-item> <setting-list-item type="number" title='{{ i18n "pages.settings.sessionMaxAge" }}' desc='{{ i18n "pages.settings.sessionMaxAgeDesc" }}' v-model="allSetting.sessionMaxAge" :min="0"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.settings.pageSize" }}' desc='{{ i18n "pages.settings.pageSizeDesc" }}' v-model="allSetting.pageSize" :min="0" :step="5"></setting-list-item> <setting-list-item type="number" title='{{ i18n "pages.settings.pageSize" }}' desc='{{ i18n "pages.settings.pageSizeDesc" }}' v-model="allSetting.pageSize" :min="0" :step="5"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item> <setting-list-item type="number" title='{{ i18n "pages.settings.expireTimeDiff" }}' desc='{{ i18n "pages.settings.expireTimeDiffDesc" }}' v-model="allSetting.expireDiff" :min="0"></setting-list-item>
<setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item> <setting-list-item type="number" title='{{ i18n "pages.settings.trafficDiff" }}' desc='{{ i18n "pages.settings.trafficDiffDesc" }}' v-model="allSetting.trafficDiff" :min="0"></setting-list-item>
@@ -305,38 +305,20 @@
<a-list-item style="padding: 20px"> <a-list-item style="padding: 20px">
<a-row> <a-row>
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<a-list-item-meta title='Noises'> <a-list-item-meta title='Noise'>
<template slot="description">{{ i18n "pages.settings.noisesDesc"}}</template> <template slot="description">{{ i18n "pages.settings.noiseDesc"}}</template>
</a-list-item-meta> </a-list-item-meta>
</a-col> </a-col>
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<a-switch v-model="noises"></a-switch> <a-switch v-model="noise"></a-switch>
</a-col> </a-col>
</a-row> </a-row>
<a-collapse v-if="noises" style="margin-top: 14px;"> <a-collapse v-if="noise" style="margin-top: 14px;">
<a-collapse-panel v-for="(noise, index) in noisesArray" :key="index" :header="`Noise ${index + 1}`"> <a-collapse-panel header='{{ i18n "pages.settings.noiseSett"}}' v-if="noise">
<a-list-item style="padding: 10px 20px"> <setting-list-item style="padding: 10px 20px" type="text" title='Packet (ms)' v-model="noisePacket" placeholder="rand:5-10"></setting-list-item>
<a-row> <setting-list-item style="padding: 10px 20px" type="text" title='Delay (ms)' v-model="noiseDelay" placeholder="10-20"></setting-list-item>
<a-col :lg="24" :xl="12">
<a-list-item-meta title='Type'></a-list-item-meta>
</a-col>
<a-col :lg="24" :xl="12">
<a-select :value="noise.type" style="width: 100%" :dropdown-class-name="themeSwitcher.currentTheme"
@change="(value) => updateNoiseType(index, value)">
<a-select-option :value="p" :label="p" v-for="p in ['rand', 'base64', 'str']" :key="p">
[[ p ]] </a-select-option>
</a-select>
</a-col>
</a-row>
</a-list-item>
<setting-list-item style="padding: 10px 20px" type="text" title='Packet' :value="noise.packet"
@input="(value) => updateNoisePacket(index, value)" placeholder="5-10"></setting-list-item>
<setting-list-item style="padding: 10px 20px" type="text" title='Delay (ms)' :value="noise.delay"
@input="(value) => updateNoiseDelay(index, value)" placeholder="10-20"></setting-list-item>
<a-button v-if="noisesArray.length > 1" type="danger" @click="removeNoise(index)">Remove</a-button>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
<a-button v-if="noises" type="primary" @click="addNoise" style="margin-top: 10px">Add Noise</a-button>
</a-list-item> </a-list-item>
<a-list-item style="padding: 20px"> <a-list-item style="padding: 20px">
<a-row> <a-row>
@@ -380,14 +362,9 @@
</a-col> </a-col>
</a-row> </a-row>
<a-collapse v-if="enableDirect" style="margin-top: 14px;"> <a-collapse v-if="enableDirect" style="margin-top: 14px;">
<a-collapse-panel header='{{ i18n "pages.xray.directips"}}'> <a-collapse-panel header='{{ i18n "pages.settings.directSett"}}'>
<a-list-item style="padding: 10px 20px"> <a-list-item style="padding: 10px 20px">
<a-checkbox-group v-model="geoIP" :options="geoIPOptions"></a-checkbox-group> <a-checkbox-group v-model="directCountries" name="Countries" :options="countryOptions"></a-checkbox-group>
</a-list-item>
</a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.directdomains"}}'>
<a-list-item style="padding: 10px 20px">
<a-checkbox-group v-model="geoSite" :options="geoSiteOptions"></a-checkbox-group>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
</a-collapse> </a-collapse>
@@ -442,14 +419,15 @@
} }
} }
}, },
defaultNoises: { defaultNoise: {
tag: "noises", tag: "noise",
protocol: "freedom", protocol: "freedom",
settings: { settings: {
domainStrategy: "AsIs", domainStrategy: "AsIs",
noises: [ noise: {
{ type: "rand", packet: "10-20", delay: "10-16" }, packet: "rand:5-10",
], delay: "10-20",
}
}, },
}, },
defaultMux: { defaultMux: {
@@ -463,7 +441,8 @@
type: "field", type: "field",
outboundTag: "direct", outboundTag: "direct",
domain: [ domain: [
"geosite:category-ir" "geosite:category-ir",
"geosite:cn"
], ],
"enabled": true "enabled": true
}, },
@@ -472,30 +451,17 @@
outboundTag: "direct", outboundTag: "direct",
ip: [ ip: [
"geoip:private", "geoip:private",
"geoip:ir" "geoip:ir",
"geoip:cn"
], ],
enabled: true enabled: true
}, },
], ],
geoIPOptions: [ countryOptions: [
{ label: 'Private IP', value: 'private' }, { label: 'Private IP/Domain', value: 'private' },
{ label: '🇮🇷 Iran', value: 'ir' }, { label: '🇮🇷 Iran', value: 'ir' },
{ label: '🇨🇳 China', value: 'cn' }, { label: '🇨🇳 China', value: 'cn' },
{ label: '🇷🇺 Russia', value: 'ru' }, { label: '🇷🇺 Russia', value: 'ru' },
{ label: '🇻🇳 Vietnam', value: 'vn' },
{ label: '🇪🇸 Spain', value: 'es' },
{ label: '🇮🇩 Indonesia', value: 'id' },
{ label: '🇺🇦 Ukraine', value: 'ua' },
{ label: '🇹🇷 Türkiye', value: 'tr' },
{ label: '🇧🇷 Brazil', value: 'br' },
],
geoSiteOptions: [
{ label: '🇮🇷 Iran', value: 'ir' },
{ label: '🇨🇳 China', value: 'cn' },
{ label: '🇷🇺 Russia', value: 'ru' },
{ label: 'Apple', value: 'apple' },
{ label: 'Meta', value: 'meta' },
{ label: 'Google', value: 'google' },
], ],
get remarkModel() { get remarkModel() {
rm = this.allSetting.remarkModel; rm = this.allSetting.remarkModel;
@@ -625,30 +591,6 @@
this.user.loginSecret = ""; this.user.loginSecret = "";
} }
}, },
addNoise() {
const newNoise = { type: "rand", packet: "10-20", delay: "10-16" };
this.noisesArray = [...this.noisesArray, newNoise];
},
removeNoise(index) {
const newNoises = [...this.noisesArray];
newNoises.splice(index, 1);
this.noisesArray = newNoises;
},
updateNoiseType(index, value) {
const updatedNoises = [...this.noisesArray];
updatedNoises[index] = { ...updatedNoises[index], type: value };
this.noisesArray = updatedNoises;
},
updateNoisePacket(index, value) {
const updatedNoises = [...this.noisesArray];
updatedNoises[index] = { ...updatedNoises[index], packet: value };
this.noisesArray = updatedNoises;
},
updateNoiseDelay(index, value) {
const updatedNoises = [...this.noisesArray];
updatedNoises[index] = { ...updatedNoises[index], delay: value };
this.noisesArray = updatedNoises;
},
}, },
computed: { computed: {
fragment: { fragment: {
@@ -687,27 +629,29 @@
} }
} }
}, },
noises: { noise: {
get() { get: function () { return this.allSetting?.subJsonNoise != ""; },
return this.allSetting?.subJsonNoises != ""; set: function (v) {
}, this.allSetting.subJsonNoise = v ? JSON.stringify(this.defaultNoise) : "";
set(v) { }
if (v) { },
this.allSetting.subJsonNoises = JSON.stringify(this.defaultNoises); noisePacket: {
} else { get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.packet : ""; },
this.allSetting.subJsonNoises = ""; set: function (v) {
if (v != "") {
newNoise = JSON.parse(this.allSetting.subJsonNoise);
newNoise.settings.noise.packet = v;
this.allSetting.subJsonNoise = JSON.stringify(newNoise);
} }
} }
}, },
noisesArray: { noiseDelay: {
get() { get: function () { return this.noise ? JSON.parse(this.allSetting.subJsonNoise).settings.noise.delay : ""; },
return this.noises ? JSON.parse(this.allSetting.subJsonNoises).settings.noises : []; set: function (v) {
}, if (v != "") {
set(value) { newNoise = JSON.parse(this.allSetting.subJsonNoise);
if (this.noises) { newNoise.settings.noise.delay = v;
const newNoises = JSON.parse(this.allSetting.subJsonNoises); this.allSetting.subJsonNoise = JSON.stringify(newNoise);
newNoises.settings.noises = value;
this.allSetting.subJsonNoises = JSON.stringify(newNoises);
} }
} }
}, },
@@ -747,49 +691,28 @@
this.allSetting.subJsonRules = v ? JSON.stringify(this.defaultRules) : ""; this.allSetting.subJsonRules = v ? JSON.stringify(this.defaultRules) : "";
} }
}, },
geoIP: { directCountries: {
get: function () { get: function () {
if (!this.enableDirect) return []; if (!this.enableDirect) return [];
const rules = JSON.parse(this.allSetting.subJsonRules); rules = JSON.parse(this.allSetting.subJsonRules);
return Array.isArray(rules) ? rules[1].ip.map(d => d.replace("geoip:", "")) : []; return Array.isArray(rules) ? rules[1].ip.map(d => d.replace("geoip:", "")) : [];
}, },
set: function (v) { set: function (v) {
const rules = JSON.parse(this.allSetting.subJsonRules); rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return; if (!Array.isArray(rules)) return;
rules[0].domain = [];
rules[1].ip = []; rules[1].ip = [];
v.forEach(d => {
rules[1].ip.push("geoip:" + d);
});
this.allSetting.subJsonRules = JSON.stringify(rules);
}
},
geoSite: {
get: function () {
if (!this.enableDirect) return [];
const rules = JSON.parse(this.allSetting.subJsonRules);
return Array.isArray(rules) ?
rules[0].domain.map(d => {
if (d.startsWith("geosite:category-")) {
return d.replace("geosite:category-", "");
}
return d.replace("geosite:", "");
})
: [];
},
set: function (v) {
const rules = JSON.parse(this.allSetting.subJsonRules);
if (!Array.isArray(rules)) return;
rules[0].domain = [];
v.forEach(d => { v.forEach(d => {
let category = ''; let category = '';
if (["cn", "apple", "meta", "google"].includes(d)) { if (["cn", "private"].includes(d)) {
category = ""; category = "";
} else if (["ru", "ir"].includes(d)) { } else if (d === 'ru') {
category = "category-gov-";
} else {
category = "category-"; category = "category-";
} }
rules[0].domain.push("geosite:" + category + d); rules[0].domain.push("geosite:" + category + d);
rules[1].ip.push("geoip:" + d);
}); });
this.allSetting.subJsonRules = JSON.stringify(rules); this.allSetting.subJsonRules = JSON.stringify(rules);
} }

View File

@@ -163,8 +163,8 @@
</a-col> </a-col>
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<template> <template>
<a-select v-model="logLevel" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%"> <a-select v-model="setLogLevel" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%">
<a-select-option v-for="s in log.loglevel" :value="s">[[ s ]]</a-select-option> <a-select-option v-for="s in logLevel" :value="s">[[ s ]]</a-select-option>
</a-select> </a-select>
</template> </template>
</a-col> </a-col>
@@ -178,8 +178,7 @@
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<template> <template>
<a-select v-model="accessLog" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%"> <a-select v-model="accessLog" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%">
<a-select-option value=''>Empty</a-select-option> <a-select-option v-for="s in access" :key="s" :value="s">[[ s ]]</a-select-option>
<a-select-option v-for="s in log.access" :value="s">[[ s ]]</a-select-option>
</a-select> </a-select>
</template> </template>
</a-col> </a-col>
@@ -193,28 +192,11 @@
<a-col :lg="24" :xl="12"> <a-col :lg="24" :xl="12">
<template> <template>
<a-select v-model="errorLog" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%"> <a-select v-model="errorLog" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%">
<a-select-option value=''>Empty</a-select-option> <a-select-option v-for="s in error" :key="s" :value="s">[[ s ]]</a-select-option>
<a-select-option v-for="s in log.error" :value="s">[[ s ]]</a-select-option>
</a-select> </a-select>
</template> </template>
</a-col> </a-col>
</a-row> </a-row>
<a-row style="padding: 10px 20px">
<a-col :lg="24" :xl="12">
<a-list-item-meta title='{{ i18n "pages.xray.maskAddress" }}'
description='{{ i18n "pages.xray.maskAddressDesc" }}'>
</a-list-item-meta>
</a-col>
<a-col :lg="24" :xl="12">
<template>
<a-select v-model="maskAddressLog" :dropdown-class-name="themeSwitcher.currentTheme" style="width: 100%">
<a-select-option value=''>Empty</a-select-option>
<a-select-option v-for="s in log.maskAddress" :value="s">[[ s ]]</a-select-option>
</a-select>
</template>
</a-col>
</a-row>
<setting-list-item type="switch" title='{{ i18n "pages.xray.dnsLog"}}' desc='{{ i18n "pages.xray.dnsLogDesc"}}' v-model="dnslog"></setting-list-item>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.blockConfigs"}}'> <a-collapse-panel header='{{ i18n "pages.xray.blockConfigs"}}'>
@@ -235,78 +217,44 @@
<setting-list-item type="switch" title='{{ i18n "pages.xray.Speedtest"}}' desc='{{ i18n "pages.xray.SpeedtestDesc"}}' v-model="SpeedTestSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.Speedtest"}}' desc='{{ i18n "pages.xray.SpeedtestDesc"}}' v-model="SpeedTestSettings"></setting-list-item>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.blockConnectionsConfigs"}}'> <a-collapse-panel header='{{ i18n "pages.xray.blockCountryConfigs"}}'>
<a-row :xs="24" :sm="24" :lg="12"> <a-row :xs="24" :sm="24" :lg="12">
<a-alert type="warning" style="text-align: center;"> <a-alert type="warning" style="text-align: center;">
<template slot="message"> <template slot="message">
<a-icon type="exclamation-circle" theme="filled" style="color: #FFA031"></a-icon> <a-icon type="exclamation-circle" theme="filled" style="color: #FFA031"></a-icon>
{{ i18n "pages.xray.blockConnectionsConfigsDesc" }} {{ i18n "pages.xray.blockCountryConfigsDesc" }}
</template> </template>
</a-alert> </a-alert>
</a-row> </a-row>
<a-list-item> <a-list-item>
<a-collapse> <setting-list-item type="switch" title='{{ i18n "pages.xray.IRIp"}}' desc='{{ i18n "pages.xray.IRIpDesc"}}' v-model="IRIpSettings"></setting-list-item>
<a-collapse-panel header='{{ i18n "pages.xray.blockips"}}'> <setting-list-item type="switch" title='{{ i18n "pages.xray.IRDomain"}}' desc='{{ i18n "pages.xray.IRDomainDesc"}}' v-model="IRDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇮🇷 Iran' <setting-list-item type="switch" title='{{ i18n "pages.xray.ChinaIp"}}' desc='{{ i18n "pages.xray.ChinaIpDesc"}}' v-model="ChinaIpSettings"></setting-list-item>
v-model="IRIpSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.ChinaDomain"}}' desc='{{ i18n "pages.xray.ChinaDomainDesc"}}' v-model="ChinaDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇨🇳 China' <setting-list-item type="switch" title='{{ i18n "pages.xray.RussiaIp"}}' desc='{{ i18n "pages.xray.RussiaIpDesc"}}' v-model="RussiaIpSettings"></setting-list-item>
v-model="ChinaIpSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.RussiaDomain"}}' desc='{{ i18n "pages.xray.RussiaDomainDesc"}}' v-model="RussiaDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇷🇺 Russia' <setting-list-item type="switch" title='{{ i18n "pages.xray.VNIp"}}' desc='{{ i18n "pages.xray.VNIpDesc"}}' v-model="VNIpSettings"></setting-list-item>
v-model="RussiaIpSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.VNDomain"}}' desc='{{ i18n "pages.xray.VNDomainDesc"}}' v-model="VNDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇻🇳 Vietnam'
v-model="VNIpSettings"></setting-list-item>
</a-collapse-panel>
</a-collapse>
<br>
<a-collapse>
<a-collapse-panel header='{{ i18n "pages.xray.blockdomains"}}'>
<setting-list-item type="switch" title='🇮🇷 Iran'
v-model="IRDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇨🇳 China'
v-model="ChinaDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇷🇺 Russia'
v-model="RussiaDomainSettings"></setting-list-item>
<setting-list-item type="switch" title='🇻🇳 Vietnam'
v-model="VNDomainSettings"></setting-list-item>
</a-collapse-panel>
</a-collapse>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.directConnectionsConfigs"}}'> <a-collapse-panel header='{{ i18n "pages.xray.directCountryConfigs"}}'>
<a-row :xs="24" :sm="24" :lg="12"> <a-row :xs="24" :sm="24" :lg="12">
<a-alert type="warning" style="text-align: center;"> <a-alert type="warning" style="text-align: center;">
<template slot="message"> <template slot="message">
<a-icon type="exclamation-circle" theme="filled" style="color: #FFA031"></a-icon> <a-icon type="exclamation-circle" theme="filled" style="color: #FFA031"></a-icon>
{{ i18n "pages.xray.directConnectionsConfigsDesc" }} {{ i18n "pages.xray.directCountryConfigsDesc" }}
</template> </template>
</a-alert> </a-alert>
</a-row> </a-row>
<a-list-item> <a-list-item>
<a-collapse> <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectIRIp"}}' desc='{{ i18n "pages.xray.DirectIRIpDesc"}}' v-model="IRIpDirectSettings"></setting-list-item>
<a-collapse-panel header='{{ i18n "pages.xray.directips"}}'> <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectIRDomain"}}' desc='{{ i18n "pages.xray.DirectIRDomainDesc"}}' v-model="IRDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇮🇷 Iran' <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectChinaIp"}}' desc='{{ i18n "pages.xray.DirectChinaIpDesc"}}' v-model="ChinaIpDirectSettings"></setting-list-item>
v-model="IRIpDirectSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectChinaDomain"}}' desc='{{ i18n "pages.xray.DirectChinaDomainDesc"}}' v-model="ChinaDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇨🇳 China' <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectRussiaIp"}}' desc='{{ i18n "pages.xray.DirectRussiaIpDesc"}}' v-model="RussiaIpDirectSettings"></setting-list-item>
v-model="ChinaIpDirectSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectRussiaDomain"}}' desc='{{ i18n "pages.xray.DirectRussiaDomainDesc"}}' v-model="RussiaDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇷🇺 Russia' <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectVNIp"}}' desc='{{ i18n "pages.xray.DirectVNIpDesc"}}' v-model="VNIpDirectSettings"></setting-list-item>
v-model="RussiaIpDirectSettings"></setting-list-item> <setting-list-item type="switch" title='{{ i18n "pages.xray.DirectVNDomain"}}' desc='{{ i18n "pages.xray.DirectVNDomainDesc"}}' v-model="VNDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇻🇳 Vietnam'
v-model="VNIpDirectSettings"></setting-list-item>
</a-collapse-panel>
</a-collapse>
<br>
<a-collapse>
<a-collapse-panel header='{{ i18n "pages.xray.directdomains"}}'>
<setting-list-item type="switch" title='🇮🇷 Iran'
v-model="IRDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇨🇳 China'
v-model="ChinaDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇷🇺 Russia'
v-model="RussiaDomainDirectSettings"></setting-list-item>
<setting-list-item type="switch" title='🇻🇳 Vietnam'
v-model="VNDomainDirectSettings"></setting-list-item>
</a-collapse-panel>
</a-collapse>
</a-list-item> </a-list-item>
</a-collapse-panel> </a-collapse-panel>
<a-collapse-panel header='{{ i18n "pages.xray.ipv4Configs"}}'> <a-collapse-panel header='{{ i18n "pages.xray.ipv4Configs"}}'>
@@ -621,90 +569,86 @@
</a-radio-group> </a-radio-group>
<textarea style="position:absolute; left: -800px;" id="obsSetting"></textarea> <textarea style="position:absolute; left: -800px;" id="obsSetting"></textarea>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="tpl-dns" tab='DNS' style="padding-top: 20px;" force-render="true"> <a-tab-pane key="tpl-dns" tab='DNS' style="padding-top: 20px;" force-render="true">
<setting-list-item type="switch" title='{{ i18n "pages.xray.dns.enable" }}' <setting-list-item type="switch" title='{{ i18n "pages.xray.dns.enable" }}' desc='{{ i18n "pages.xray.dns.enableDesc" }}' v-model="enableDNS"></setting-list-item>
desc='{{ i18n "pages.xray.dns.enableDesc" }}' v-model="enableDNS"></setting-list-item>
<template v-if="enableDNS"> <template v-if="enableDNS">
<setting-list-item style="padding: 10px 20px" type="text" title='{{ i18n "pages.xray.dns.tag" }}' <setting-list-item style="padding: 10px 20px" type="text" title='{{ i18n "pages.xray.dns.tag" }}' desc='{{ i18n "pages.xray.dns.tagDesc" }}' v-model="dnsTag"></setting-list-item>
desc='{{ i18n "pages.xray.dns.tagDesc" }}' v-model="dnsTag"></setting-list-item> <a-list-item style="padding: 10px 20px">
<a-list-item style="padding: 10px 20px"> <a-row>
<a-row> <a-col :lg="24" :xl="12">
<a-col :lg="24" :xl="12"> <a-list-item-meta title='{{ i18n "pages.xray.dns.strategy" }}' description='{{ i18n "pages.xray.dns.strategyDesc" }}' />
<a-list-item-meta title='{{ i18n "pages.xray.dns.strategy" }}' </a-col>
description='{{ i18n "pages.xray.dns.strategyDesc" }}' /> <a-col :lg="24" :xl="12">
</a-col> <a-select
<a-col :lg="24" :xl="12"> v-model="dnsStrategy"
<a-select v-model="dnsStrategy" style="width: 100%" 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 ['UseIP', 'UseIPv4', 'UseIPv6']">
[[ l ]] [[ l ]]
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-col> </a-col>
</a-row> </a-row>
</a-list-item> </a-list-item>
<a-divider>DNS</a-divider> <a-divider>DNS</a-divider>
<a-button type="primary" icon="plus" @click="addDNSServer()" style="margin-bottom: 10px;">{{ i18n <a-button type="primary" icon="plus" @click="addDNSServer()" style="margin-bottom: 10px;">{{ i18n "pages.xray.dns.add" }}</a-button>
"pages.xray.dns.add" }}</a-button> <a-table :columns="dnsColumns" bordered v-if="dnsServers.length>0"
<a-table :columns="dnsColumns" bordered v-if="dnsServers.length>0" :row-key="r => r.key" :row-key="r => r.key"
:data-source="dnsServers" :scroll="isMobile ? {} : { x: 200 }" :pagination="false" :indent-size="0" :data-source="dnsServers"
:style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'"> :scroll="isMobile ? {} : { x: 200 }"
<template slot="action" slot-scope="text,dns,index"> :pagination="false"
[[ index+1 ]] :indent-size="0"
<a-dropdown :trigger="['click']"> :style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'">
<a-icon @click="e => e.preventDefault()" type="more" <template slot="action" slot-scope="text,dns,index">
style="font-size: 16px; text-decoration: bold;"></a-icon> [[ index+1 ]]
<a-menu slot="overlay" :theme="themeSwitcher.currentTheme"> <a-dropdown :trigger="['click']">
<a-menu-item @click="editDNSServer(index)"> <a-icon @click="e => e.preventDefault()" type="more" style="font-size: 16px; text-decoration: bold;"></a-icon>
<a-icon type="edit"></a-icon> <a-menu slot="overlay" :theme="themeSwitcher.currentTheme">
{{ i18n "edit" }} <a-menu-item @click="editDNSServer(index)">
</a-menu-item> <a-icon type="edit"></a-icon>
<a-menu-item @click="deleteDNSServer(index)"> {{ i18n "edit" }}
<span style="color: #FF4D4F"> </a-menu-item>
<a-icon type="delete"></a-icon> {{ i18n "delete"}} <a-menu-item @click="deleteDNSServer(index)">
</span> <span style="color: #FF4D4F">
</a-menu-item> <a-icon type="delete"></a-icon> {{ i18n "delete"}}
</a-menu> </span>
</a-dropdown> </a-menu-item>
</template> </a-menu>
<template slot="address" slot-scope="dns,index"> </a-dropdown>
<span v-if="typeof dns == 'object'">[[ dns.address ]]</span> </template>
<span v-else>[[ dns ]]</span> <template slot="address" slot-scope="dns,index">
</template> <span v-if="typeof dns == 'object'">[[ dns.address ]]</span>
<template slot="domain" slot-scope="dns,index"> <span v-else>[[ dns ]]</span>
<span v-if="typeof dns == 'object'">[[ dns.domains.join(",") ]]</span> </template>
</template> <template slot="domain" slot-scope="dns,index">
<template slot="expectIPs" slot-scope="dns,index"> <span v-if="typeof dns == 'object'">[[ dns.domains.join(",") ]]</span>
<span v-if="typeof dns == 'object'">[[ dns.expectIPs.join(",") ]]</span> </template>
</template> </a-table>
</a-table> <a-divider>Fake DNS</a-divider>
<a-divider>Fake DNS</a-divider> <a-button type="primary" icon="plus" @click="addFakedns()" style="margin-bottom: 10px;">{{ i18n "pages.xray.fakedns.add" }}</a-button>
<a-button type="primary" icon="plus" @click="addFakedns()" style="margin-bottom: 10px;">{{ i18n <a-table :columns="fakednsColumns" bordered v-if="fakeDns && fakeDns.length>0" :row-key="r => r.key"
"pages.xray.fakedns.add" }}</a-button> :data-source="fakeDns" :scroll="isMobile ? {} : { x: 200 }" :pagination="false" :indent-size="0"
<a-table :columns="fakednsColumns" bordered v-if="fakeDns && fakeDns.length>0" :row-key="r => r.key" :style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'">
:data-source="fakeDns" :scroll="isMobile ? {} : { x: 200 }" :pagination="false" :indent-size="0" <template slot="action" slot-scope="text,fakedns,index">
:style="isMobile ? 'padding: 5px 0' : 'margin-left: 1px;'"> [[ index+1 ]]
<template slot="action" slot-scope="text,fakedns,index"> <a-dropdown :trigger="['click']">
[[ index+1 ]] <a-icon @click="e => e.preventDefault()" type="more" style="font-size: 16px; text-decoration: bold;"></a-icon>
<a-dropdown :trigger="['click']"> <a-menu slot="overlay" :theme="themeSwitcher.currentTheme">
<a-icon @click="e => e.preventDefault()" type="more" <a-menu-item @click="editFakedns(index)">
style="font-size: 16px; text-decoration: bold;"></a-icon> <a-icon type="edit"></a-icon>
<a-menu slot="overlay" :theme="themeSwitcher.currentTheme"> {{ i18n "edit" }}
<a-menu-item @click="editFakedns(index)"> </a-menu-item>
<a-icon type="edit"></a-icon> <a-menu-item @click="deleteFakedns(index)">
{{ i18n "edit" }} <span style="color: #FF4D4F">
</a-menu-item> <a-icon type="delete"></a-icon> {{ i18n "delete"}}
<a-menu-item @click="deleteFakedns(index)"> </span>
<span style="color: #FF4D4F"> </a-menu-item>
<a-icon type="delete"></a-icon> {{ i18n "delete"}} </a-menu>
</span> </a-dropdown>
</a-menu-item> </template>
</a-menu> </a-table>
</a-dropdown>
</template>
</a-table>
</template> </template>
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' style="padding-top: 20px;" force-render="true"> <a-tab-pane key="tpl-advanced" tab='{{ i18n "pages.xray.advancedTemplate"}}' style="padding-top: 20px;" force-render="true">
<a-list-item-meta title='{{ i18n "pages.xray.Template"}}' description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta> <a-list-item-meta title='{{ i18n "pages.xray.Template"}}' description='{{ i18n "pages.xray.TemplateDesc"}}'></a-list-item-meta>
<a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" style="margin: 10px 0;" :size="isMobile ? 'small' : ''"> <a-radio-group v-model="advSettings" @change="changeCode" button-style="solid" style="margin: 10px 0;" :size="isMobile ? 'small' : ''">
@@ -786,7 +730,6 @@
{ title: "#", align: 'center', width: 20, scopedSlots: { customRender: 'action' } }, { title: "#", align: 'center', width: 20, scopedSlots: { customRender: 'action' } },
{ title: '{{ i18n "pages.xray.outbound.address"}}', align: 'center', width: 50, scopedSlots: { customRender: 'address' } }, { title: '{{ i18n "pages.xray.outbound.address"}}', align: 'center', width: 50, scopedSlots: { customRender: 'address' } },
{ title: '{{ i18n "pages.xray.dns.domains"}}', align: 'center', width: 50, scopedSlots: { customRender: 'domain' } }, { title: '{{ i18n "pages.xray.dns.domains"}}', align: 'center', width: 50, scopedSlots: { customRender: 'domain' } },
{ title: '{{ i18n "pages.xray.dns.expectIPs"}}', align: 'center', width: 50, scopedSlots: { customRender: 'expectIPs' } },
]; ];
const fakednsColumns = [ const fakednsColumns = [
@@ -848,13 +791,9 @@
protocol: "freedom" protocol: "freedom"
}, },
routingDomainStrategies: ["AsIs", "IPIfNonMatch", "IPOnDemand"], routingDomainStrategies: ["AsIs", "IPIfNonMatch", "IPOnDemand"],
log: { logLevel: ["none" , "debug" , "info" , "warning", "error"],
loglevel: ["none", "debug", "info", "warning", "error"], access: [],
access: ["none", "./access.log"], error: [],
error: ["none", "./error.log"],
dnsLog: false,
maskAddress: ["quarter", "half", "full"],
},
settingsData: { settingsData: {
protocols: { protocols: {
bittorrent: ["bittorrent"], bittorrent: ["bittorrent"],
@@ -885,19 +824,17 @@
apple: ["geosite:apple"], apple: ["geosite:apple"],
reddit: ["geosite:reddit"], reddit: ["geosite:reddit"],
cn: [ cn: [
"regexp:.*\\.cn$", "geosite:cn",
"geosite:cn" "regexp:.*\\.cn$"
], ],
ru: [ ru: [
"regexp:.*\\.ru$", "geosite:category-gov-ru",
"geosite:category-ru" //https://github.com/v2fly/domain-list-community/blob/master/data/category-ru "regexp:.*\\.ru$"
], ],
ir: [ ir: [
"regexp:.*\\.ir$", "regexp:.*\\.ir$",
"ext:geosite_IR.dat:ir", "regexp:.*\\.xn--mgba3a4f16a$", // .ایران
"geosite:category-ir", // https://github.com/v2fly/domain-list-community/blob/master/data/category-ir "ext:geosite_IR.dat:ir"
"regexp:.*\\.xn--mgba3a4f16a$" // .ایران
], ],
vn: [ vn: [
"regexp:.*\\.vn$", "regexp:.*\\.vn$",
@@ -1582,11 +1519,27 @@
templateSettings: { templateSettings: {
get: function () { get: function () {
const parsedSettings = this.xraySetting ? JSON.parse(this.xraySetting) : null; const parsedSettings = this.xraySetting ? JSON.parse(this.xraySetting) : null;
let accessLogPath = "./access.log";
let errorLogPath = "./error.log";
if (parsedSettings && parsedSettings.log) {
if (parsedSettings.log.access && parsedSettings.log.access !== "none") {
accessLogPath = parsedSettings.log.access;
}
if (parsedSettings.log.error && parsedSettings.log.error !== "none") {
errorLogPath = parsedSettings.log.error;
}
}
this.access = ["none", accessLogPath];
this.error = ["none", errorLogPath];
return parsedSettings; return parsedSettings;
}, },
set: function (newValue) { set: function (newValue) {
if (newValue) { if (newValue && newValue.log) {
this.xraySetting = JSON.stringify(newValue, null, 2); this.xraySetting = JSON.stringify(newValue, null, 2);
this.access = ["none", newValue.log.access || "./access.log"];
this.error = ["none", newValue.log.error || "./error.log"];
} }
}, },
}, },
@@ -1735,7 +1688,7 @@
this.templateSettings = newTemplateSettings; this.templateSettings = newTemplateSettings;
} }
}, },
logLevel: { setLogLevel: {
get: function () { get: function () {
if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.loglevel) return "warning"; if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.loglevel) return "warning";
return this.templateSettings.log.loglevel; return this.templateSettings.log.loglevel;
@@ -1768,28 +1721,6 @@
this.templateSettings = newTemplateSettings; this.templateSettings = newTemplateSettings;
} }
}, },
dnslog: {
get: function () {
if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.dnsLog) return false;
return this.templateSettings.log.dnsLog;
},
set: function (newValue) {
newTemplateSettings = this.templateSettings;
newTemplateSettings.log.dnsLog = newValue;
this.templateSettings = newTemplateSettings;
}
},
maskAddressLog: {
get: function () {
if (!this.templateSettings || !this.templateSettings.log || !this.templateSettings.log.maskAddress) return "";
return this.templateSettings.log.maskAddress;
},
set: function (newValue) {
newTemplateSettings = this.templateSettings;
newTemplateSettings.log.maskAddress = newValue;
this.templateSettings = newTemplateSettings;
}
},
blockedIPs: { blockedIPs: {
get: function () { get: function () {
return this.templateRuleGetter({ outboundTag: "blocked", property: "ip" }); return this.templateRuleGetter({ outboundTag: "blocked", property: "ip" });

View File

@@ -36,15 +36,20 @@ func (j *CheckClientIpJob) Run() {
} }
shouldClearAccessLog := false shouldClearAccessLog := false
iplimitActive := j.hasLimitIp() f2bInstalled := j.checkFail2BanInstalled()
f2bInstalled := j.checkFail2BanInstalled(iplimitActive) isAccessLogAvailable := j.checkAccessLogAvailable(f2bInstalled)
isAccessLogAvailable := j.checkAccessLogAvailable(iplimitActive)
if iplimitActive && f2bInstalled && isAccessLogAvailable { if j.hasLimitIp() {
shouldClearAccessLog = j.processLogFile() if f2bInstalled && isAccessLogAvailable {
shouldClearAccessLog = j.processLogFile()
} else {
if !f2bInstalled {
logger.Warning("[iplimit] fail2ban is not installed. IP limiting may not work properly.")
}
}
} }
if shouldClearAccessLog || (isAccessLogAvailable && time.Now().Unix()-j.lastClear > 3600) { if shouldClearAccessLog || isAccessLogAvailable && time.Now().Unix()-j.lastClear > 3600 {
j.clearAccessLog() j.clearAccessLog()
} }
} }
@@ -117,13 +122,13 @@ func (j *CheckClientIpJob) processLogFile() bool {
for scanner.Scan() { for scanner.Scan() {
line := scanner.Text() line := scanner.Text()
ipRegx, _ := regexp.Compile(`from \[?([0-9a-fA-F:.]+)\]?:\d+ accepted`) ipRegx, _ := regexp.Compile(`(\d+\.\d+\.\d+\.\d+).* accepted`)
emailRegx, _ := regexp.Compile(`email: (\S+)$`) emailRegx, _ := regexp.Compile(`email:.+`)
matches := ipRegx.FindStringSubmatch(line) matches := ipRegx.FindStringSubmatch(line)
if len(matches) > 1 { if len(matches) > 1 {
ip := matches[1] ip := matches[1]
if ip == "127.0.0.1" || ip == "::1" { if ip == "127.0.0.1" {
continue continue
} }
@@ -131,7 +136,7 @@ func (j *CheckClientIpJob) processLogFile() bool {
if matchesEmail == "" { if matchesEmail == "" {
continue continue
} }
matchesEmail = strings.Split(matchesEmail, "email: ")[1] matchesEmail = strings.TrimSpace(strings.Split(matchesEmail, "email: ")[1])
if InboundClientIps[matchesEmail] != nil { if InboundClientIps[matchesEmail] != nil {
if j.contains(InboundClientIps[matchesEmail], ip) { if j.contains(InboundClientIps[matchesEmail], ip) {
@@ -162,33 +167,35 @@ func (j *CheckClientIpJob) processLogFile() bool {
return shouldCleanLog return shouldCleanLog
} }
func (j *CheckClientIpJob) checkFail2BanInstalled(iplimitActive bool) bool { func (j *CheckClientIpJob) checkFail2BanInstalled() bool {
cmd := "fail2ban-client" cmd := "fail2ban-client"
args := []string{"-h"} args := []string{"-h"}
err := exec.Command(cmd, args...).Run() err := exec.Command(cmd, args...).Run()
return err == nil
if iplimitActive && err != nil {
logger.Warning("[LimitIP] Fail2Ban is not installed, Please install Fail2Ban from the x-ui bash menu.")
return false
}
return true
} }
func (j *CheckClientIpJob) checkAccessLogAvailable(iplimitActive bool) bool { func (j *CheckClientIpJob) checkAccessLogAvailable(handleWarning bool) bool {
isAvailable := true
warningMsg := ""
accessLogPath, err := xray.GetAccessLogPath() accessLogPath, err := xray.GetAccessLogPath()
if err != nil { if err != nil {
return false return false
} }
if accessLogPath == "none" || accessLogPath == "" { // access log is not available if it is set to 'none' or an empty string
if iplimitActive { switch accessLogPath {
logger.Warning("[LimitIP] Access log path is not set, Please configure the access log path in Xray configs.") case "none":
} warningMsg = "Access log is set to 'none', check your Xray Configs"
return false isAvailable = false
case "":
warningMsg = "Access log doesn't exist in your Xray Configs"
isAvailable = false
} }
return true if handleWarning && warningMsg != "" {
logger.Warning(warningMsg)
}
return isAvailable
} }
func (j *CheckClientIpJob) checkError(e error) { func (j *CheckClientIpJob) checkError(e error) {

View File

@@ -2,9 +2,8 @@
"log": { "log": {
"access": "none", "access": "none",
"dnsLog": false, "dnsLog": false,
"error": "", "error": "./error.log",
"loglevel": "warning", "loglevel": "warning"
"maskAddress": ""
}, },
"api": { "api": {
"tag": "api", "tag": "api",

View File

@@ -2,9 +2,7 @@ package service
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -331,7 +329,6 @@ func (s *InboundService) UpdateInbound(inbound *model.Inbound) (*model.Inbound,
oldInbound.Settings = inbound.Settings oldInbound.Settings = inbound.Settings
oldInbound.StreamSettings = inbound.StreamSettings oldInbound.StreamSettings = inbound.StreamSettings
oldInbound.Sniffing = inbound.Sniffing oldInbound.Sniffing = inbound.Sniffing
oldInbound.Allocate = inbound.Allocate
if inbound.Listen == "" || inbound.Listen == "0.0.0.0" || inbound.Listen == "::" || inbound.Listen == "::0" { if inbound.Listen == "" || inbound.Listen == "0.0.0.0" || inbound.Listen == "::" || inbound.Listen == "::0" {
oldInbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port) oldInbound.Tag = fmt.Sprintf("inbound-%v", inbound.Port)
} else { } else {
@@ -414,12 +411,6 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
return false, err return false, err
} }
email := clients[0].Email
valid, err := validateEmail(email)
if !valid {
return false, err
}
var settings map[string]interface{} var settings map[string]interface{}
err = json.Unmarshal([]byte(data.Settings), &settings) err = json.Unmarshal([]byte(data.Settings), &settings)
if err != nil { if err != nil {
@@ -610,12 +601,6 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
return false, err return false, err
} }
email := clients[0].Email
valid, err := validateEmail(email)
if !valid {
return false, err
}
var settings map[string]interface{} var settings map[string]interface{}
err = json.Unmarshal([]byte(data.Settings), &settings) err = json.Unmarshal([]byte(data.Settings), &settings)
if err != nil { if err != nil {
@@ -2022,20 +2007,3 @@ func (s *InboundService) MigrateDB() {
func (s *InboundService) GetOnlineClients() []string { func (s *InboundService) GetOnlineClients() []string {
return p.GetOnlineClients() return p.GetOnlineClients()
} }
func validateEmail(email string) (bool, error) {
if strings.Contains(email, " ") {
return false, errors.New("email contains spaces, please remove them")
}
if email != strings.ToLower(email) {
return false, errors.New("email contains uppercase letters, please convert to lowercase")
}
emailPattern := `^[a-z0-9@._-]+$`
if !regexp.MustCompile(emailPattern).MatchString(email) {
return false, errors.New("email contains invalid characters, please use only lowercase letters, digits, and @._-")
}
return true, nil
}

View File

@@ -32,7 +32,7 @@ var defaultValueMap = map[string]string{
"webKeyFile": "", "webKeyFile": "",
"secret": random.Seq(32), "secret": random.Seq(32),
"webBasePath": "/", "webBasePath": "/",
"sessionMaxAge": "60", "sessionMaxAge": "0",
"pageSize": "50", "pageSize": "50",
"expireDiff": "0", "expireDiff": "0",
"trafficDiff": "0", "trafficDiff": "0",
@@ -62,7 +62,7 @@ var defaultValueMap = map[string]string{
"subJsonPath": "/json/", "subJsonPath": "/json/",
"subJsonURI": "", "subJsonURI": "",
"subJsonFragment": "", "subJsonFragment": "",
"subJsonNoises": "", "subJsonNoise": "",
"subJsonMux": "", "subJsonMux": "",
"subJsonRules": "", "subJsonRules": "",
"datepicker": "gregorian", "datepicker": "gregorian",
@@ -459,8 +459,8 @@ func (s *SettingService) GetSubJsonFragment() (string, error) {
return s.getString("subJsonFragment") return s.getString("subJsonFragment")
} }
func (s *SettingService) GetSubJsonNoises() (string, error) { func (s *SettingService) GetSubJsonNoise() (string, error) {
return s.getString("subJsonNoises") return s.getString("subJsonNoise")
} }
func (s *SettingService) GetSubJsonMux() (string, error) { func (s *SettingService) GetSubJsonMux() (string, error) {

View File

@@ -43,8 +43,8 @@
"domainName" = "Domain Name" "domainName" = "Domain Name"
"monitor" = "Listen IP" "monitor" = "Listen IP"
"certificate" = "Digital Certificate" "certificate" = "Digital Certificate"
"fail" = "Failed" "fail" = " Failed"
"success" = "Successfully" "success" = " Successfully"
"getVersion" = "Get Version" "getVersion" = "Get Version"
"install" = "Install" "install" = "Install"
"clients" = "Clients" "clients" = "Clients"
@@ -143,7 +143,7 @@
"destinationPort" = "Destination Port" "destinationPort" = "Destination Port"
"targetAddress" = "Target Address" "targetAddress" = "Target Address"
"monitorDesc" = "Leave blank to listen on all IPs" "monitorDesc" = "Leave blank to listen on all IPs"
"meansNoLimit" = "= Unlimited. (unit: GB)" "meansNoLimit" = " = Unlimited. (unit: GB)"
"totalFlow" = "Total Flow" "totalFlow" = "Total Flow"
"leaveBlankToNeverExpire" = "Leave blank to never expire" "leaveBlankToNeverExpire" = "Leave blank to never expire"
"noRecommendKeepDefault" = "It is recommended to keep the default" "noRecommendKeepDefault" = "It is recommended to keep the default"
@@ -225,6 +225,9 @@
"requestHeader" = "Request Header" "requestHeader" = "Request Header"
"responseHeader" = "Response Header" "responseHeader" = "Response Header"
[pages.inbounds.stream.quic]
"encryption" = "Encryption"
[pages.settings] [pages.settings]
"title" = "Panel Settings" "title" = "Panel Settings"
"save" = "Save" "save" = "Save"
@@ -309,14 +312,14 @@
"fragment" = "Fragmentation" "fragment" = "Fragmentation"
"fragmentDesc" = "Enable fragmentation for TLS hello packet." "fragmentDesc" = "Enable fragmentation for TLS hello packet."
"fragmentSett" = "Fragmentation Settings" "fragmentSett" = "Fragmentation Settings"
"noisesDesc" = "Enable Noises." "noiseDesc" = "Enable Noise."
"noisesSett" = "Noises Settings" "noiseSett" = "Noise Settings"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Transmit multiple independent data streams within an established data stream." "muxDesc" = "Transmit multiple independent data streams within an established data stream."
"muxSett" = "Mux Settings" "muxSett" = "Mux Settings"
"direct" = "Direct Connection" "direct" = "Direct Connection"
"directDesc" = "Directly establishes connections with domains or IP ranges of a specific country." "directDesc" = "Directly establishes connections with domains or IP ranges of a specific country."
"directSett" = "Direct Connection Options"
[pages.xray] [pages.xray]
"title" = "Xray Configs" "title" = "Xray Configs"
@@ -330,14 +333,10 @@
"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" "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."
"blockConnectionsConfigs" = "Block Connections" "blockCountryConfigs" = "Block Country"
"blockConnectionsConfigsDesc" = "These options will block traffic based on the specific requested country." "blockCountryConfigsDesc" = "These options will block traffic based on the specific requested country."
"directConnectionsConfigs" = "Direct Connections" "directCountryConfigs" = "Direct Country"
"directConnectionsConfigsDesc" = "A direct connection ensures that specific traffic is not routed through another server." "directCountryConfigsDesc" = "A direct connection ensures that specific traffic is not routed through another server."
"blockips" = "Block IPs"
"blockdomains" = "Block Domains"
"directips" = "Direct IPs"
"directdomains" = "Direct Domains"
"ipv4Configs" = "IPv4 Routing" "ipv4Configs" = "IPv4 Routing"
"ipv4ConfigsDesc" = "These options will route traffic based on a specific destination via IPv4." "ipv4ConfigsDesc" = "These options will route traffic based on a specific destination via IPv4."
"warpConfigs" = "WARP Routing" "warpConfigs" = "WARP Routing"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Blocks malware, phishing, and cryptominers websites." "SecurityDesc" = "Blocks malware, phishing, and cryptominers websites."
"Speedtest" = "Block Speedtest" "Speedtest" = "Block Speedtest"
"SpeedtestDesc" = "Blocks establishing connectins to speedtest websites." "SpeedtestDesc" = "Blocks establishing connectins to speedtest websites."
"IRIp" = "Block Connection to Iran IPs"
"IRIpDesc" = "Blocks establishing connections to Iran IP ranges."
"IRDomain" = "Block Connection to Iran Domains"
"IRDomainDesc" = "Blocks establishing connections to Iran domains."
"ChinaIp" = "Block Connection to China IPs"
"ChinaIpDesc" = "Blocks establishing connections to China IP ranges."
"ChinaDomain" = "Block Connection to China Domains"
"ChinaDomainDesc" = "Blocks establishing connections to China domains."
"RussiaIp" = "Block Connection to Russia IPs"
"RussiaIpDesc" = "Blocks establishing connections to Russia IP ranges."
"RussiaDomain" = "Block Connection to Russia Domains"
"RussiaDomainDesc" = "Blocks establishing connections to Russia domains."
"VNIp" = "Block Connection to Vietnam IPs"
"VNIpDesc" = "Blocks establishing connections to Vietnam IP ranges."
"VNDomain" = "Block Connection to Vietnam Domains"
"VNDomainDesc" = "Blocks establishing connections to Vietnam domains."
"DirectIRIp" = "Direct Connection to Iran IPs"
"DirectIRIpDesc" = "Directly establishes connections to Iran IP ranges."
"DirectIRDomain" = "Direct Connection to Iran Domains"
"DirectIRDomainDesc" = "Directly establishes connections to Iran domains."
"DirectChinaIp" = "Direct Connection to China IPs"
"DirectChinaIpDesc" = "Directly establishes connections to China IP ranges."
"DirectChinaDomain" = "Direct Connection to China Domains"
"DirectChinaDomainDesc" = "Directly establishes connections to China domains."
"DirectRussiaIp" = "Direct Connection to Russia IPs"
"DirectRussiaIpDesc" = "Directly establishes connections to Russia IP ranges."
"DirectRussiaDomain" = "Direct Connection to Russia Domains"
"DirectRussiaDomainDesc" = "Directly establishes connections to Russia domains."
"DirectVNIp" = "Direct Connection to Vietnam IPs"
"DirectVNIpDesc" = "Directly establishes connections to Vietnam IP ranges."
"DirectVNDomain" = "Direct Connection to Vietnam Domains"
"DirectVNDomainDesc" = "Directly establishes connections to Vietnam domains."
"GoogleIPv4" = "Google" "GoogleIPv4" = "Google"
"GoogleIPv4Desc" = "Routes traffic to Google via IPv4." "GoogleIPv4Desc" = "Routes traffic to Google via IPv4."
"NetflixIPv4" = "Netflix" "NetflixIPv4" = "Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "The file path for the access log. The special value 'none' disabled access logs" "accessLogDesc" = "The file path for the access log. The special value 'none' disabled access logs"
"errorLog" = "Error Log" "errorLog" = "Error Log"
"errorLogDesc" = "The file path for the error log. The special value 'none' disabled error logs" "errorLogDesc" = "The file path for the error log. The special value 'none' disabled error logs"
"dnsLog" = "DNS Log"
"dnsLogDesc" = "Whether to enable DNS query logs"
"maskAddress" = "Mask Address"
"maskAddressDesc" = "IP address mask, when enabled, will automatically replace the IP address that appears in the log."
[pages.xray.rules] [pages.xray.rules]
"first" = "First" "first" = "First"
@@ -460,7 +487,6 @@
"add" = "Add Server" "add" = "Add Server"
"edit" = "Edit Server" "edit" = "Edit Server"
"domains" = "Domains" "domains" = "Domains"
"expectIPs" = "Expect IPs"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Add Fake DNS" "add" = "Add Fake DNS"

View File

@@ -143,7 +143,7 @@
"destinationPort" = "Puerto de Destino" "destinationPort" = "Puerto de Destino"
"targetAddress" = "Dirección de Destino" "targetAddress" = "Dirección de Destino"
"monitorDesc" = "Dejar en blanco por defecto" "monitorDesc" = "Dejar en blanco por defecto"
"meansNoLimit" = "= illimitata. (unidad: GB)" "meansNoLimit" = " = illimitata. (unidad: GB)"
"totalFlow" = "Flujo Total" "totalFlow" = "Flujo Total"
"leaveBlankToNeverExpire" = "Dejar en Blanco para Nunca Expirar" "leaveBlankToNeverExpire" = "Dejar en Blanco para Nunca Expirar"
"noRecommendKeepDefault" = "No hay requisitos especiales para mantener la configuración predeterminada" "noRecommendKeepDefault" = "No hay requisitos especiales para mantener la configuración predeterminada"
@@ -225,6 +225,9 @@
"requestHeader" = "Encabezado de solicitud" "requestHeader" = "Encabezado de solicitud"
"responseHeader" = "Encabezado de respuesta" "responseHeader" = "Encabezado de respuesta"
[pages.inbounds.stream.quic]
"encryption" = "Cifrado"
[pages.settings] [pages.settings]
"title" = "Configuraciones" "title" = "Configuraciones"
"save" = "Guardar" "save" = "Guardar"
@@ -309,14 +312,14 @@
"fragment" = "Fragmentación" "fragment" = "Fragmentación"
"fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS" "fragmentDesc" = "Habilitar la fragmentación para el paquete de saludo de TLS"
"fragmentSett" = "Configuración de Fragmentación" "fragmentSett" = "Configuración de Fragmentación"
"noisesDesc" = "Activar Noises." "noiseDesc" = "Activar Noise."
"noisesSett" = "Configuración de Noises" "noiseSett" = "Configuración de Noise"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido." "muxDesc" = "Transmite múltiples flujos de datos independientes dentro de un flujo de datos establecido."
"muxSett" = "Configuración Mux" "muxSett" = "Configuración Mux"
"direct" = "Conexión Directa" "direct" = "Conexión Directa"
"directDesc" = "Establece conexiones directas con dominios o rangos de IP de un país específico." "directDesc" = "Establece conexiones directas con dominios o rangos de IP de un país específico."
"directSett" = "Opciones de Conexión Directa"
[pages.xray] [pages.xray]
"title" = "Xray Configuración" "title" = "Xray Configuración"
@@ -330,14 +333,10 @@
"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" "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."
"blockConnectionsConfigs" = "Bloquear Conexiones" "blockCountryConfigs" = "Configuraciones de Bloqueo por País"
"blockConnectionsConfigsDesc" = "Estas opciones bloquearán el tráfico según el país solicitado específico." "blockCountryConfigsDesc" = "Estas opciones evitarán que los usuarios se conecten a dominios de países específicos."
"directConnectionsConfigs" = "Conexiones Directas" "directCountryConfigs" = "Configuraciones de Conexión Directa por País"
"directConnectionsConfigsDesc" = "Una conexión directa asegura que el tráfico específico no sea enrutado a través de otro servidor." "directCountryConfigsDesc" = "Una conexión directa asegura que el tráfico específico no se enruta a través de otro servidor."
"blockips" = "Bloquear IPs"
"blockdomains" = "Bloquear Dominios"
"directips" = "IPs Directas"
"directdomains" = "Dominios Directos"
"ipv4Configs" = "Configuraciones IPv4" "ipv4Configs" = "Configuraciones IPv4"
"ipv4ConfigsDesc" = "Estas opciones solo enrutarán a los dominios objetivo a través de IPv4." "ipv4ConfigsDesc" = "Estas opciones solo enrutarán a los dominios objetivo a través de IPv4."
"warpConfigs" = "Configuraciones de WARP" "warpConfigs" = "Configuraciones de WARP"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Cambiar la plantilla de configuración para la protección de seguridad." "SecurityDesc" = "Cambiar la plantilla de configuración para la protección de seguridad."
"Speedtest" = "Bloquear Sitios Web de Pruebas de Velocidad" "Speedtest" = "Bloquear Sitios Web de Pruebas de Velocidad"
"SpeedtestDesc" = "Cambia la plantilla de configuración para evitar la conexión a sitios web de pruebas de velocidad." "SpeedtestDesc" = "Cambia la plantilla de configuración para evitar la conexión a sitios web de pruebas de velocidad."
"IRIp" = "Desactivar Conexión a Rangos de IP de Irán"
"IRIpDesc" = "Cambia la plantilla de configuración para evitar la conexión a rangos de IP de Irán."
"IRDomain" = "Desactivar Conexión a Dominios de Irán"
"IRDomainDesc" = "Cambia la plantilla de configuración para evitar la conexión a dominios de Irán."
"ChinaIp" = "Desactivar Conexión a Rangos de IP de China"
"ChinaIpDesc" = "Cambia la plantilla de configuración para evitar la conexión a rangos de IP de China."
"ChinaDomain" = "Desactivar Conexión a Dominios de China"
"ChinaDomainDesc" = "Cambia la plantilla de configuración para evitar la conexión a dominios de China."
"RussiaIp" = "Desactivar Conexión a Rangos de IP de Rusia"
"RussiaIpDesc" = "Cambia la plantilla de configuración para evitar la conexión a rangos de IP de Rusia."
"RussiaDomain" = "Desactivar Conexión a Dominios de Rusia"
"RussiaDomainDesc" = "Cambia la plantilla de configuración para evitar la conexión a dominios de Rusia."
"VNIp" = "Deshabilitar la conexión a las IP de Vietnam"
"VNIpDesc" = "Cambie la plantilla de configuración para evitar conectarse a rangos de IP de Vietnam."
"VNDomain" = "Deshabilitar la conexión a dominios de Vietnam"
"VNDomainDesc" = "Cambie la plantilla de configuración para evitar conectarse a dominios de Vietnam."
"DirectIRIp" = "Conexión Directa a Rangos de IP de Irán"
"DirectIRIpDesc" = "Cambia la plantilla de configuración para conectarse directamente a rangos de IP de Irán."
"DirectIRDomain" = "Conexión Directa a Dominios de Irán"
"DirectIRDomainDesc" = "Cambia la plantilla de configuración para conectarse directamente a dominios de Irán."
"DirectChinaIp" = "Conexión Directa a Rangos de IP de China"
"DirectChinaIpDesc" = "Cambia la plantilla de configuración para conectarse directamente a rangos de IP de China."
"DirectChinaDomain" = "Conexión Directa a Dominios de China"
"DirectChinaDomainDesc" = "Cambia la plantilla de configuración para conectarse directamente a dominios de China."
"DirectRussiaIp" = "Conexión Directa a Rangos de IP de Rusia"
"DirectRussiaIpDesc" = "Cambia la plantilla de configuración para conectarse directamente a rangos de IP de Rusia."
"DirectRussiaDomain" = "Conexión Directa a Dominios de Rusia"
"DirectRussiaDomainDesc" = "Cambia la plantilla de configuración para conectarse directamente a dominios de Rusia."
"DirectVNIp" = "Conexión directa a IP de Vietnam"
"DirectVNIpDesc" = "Cambie la plantilla de configuración para la conexión directa a rangos de IP de Vietnam."
"DirectVNDomain" = "Conexión directa a dominios de Vietnam"
"DirectVNDomainDesc" = "Cambie la plantilla de configuración para la conexión directa a dominios de Vietnam."
"GoogleIPv4" = "Usar IPv4 para Google" "GoogleIPv4" = "Usar IPv4 para Google"
"GoogleIPv4Desc" = "Agregar enrutamiento para que Google se conecte con IPv4." "GoogleIPv4Desc" = "Agregar enrutamiento para que Google se conecte con IPv4."
"NetflixIPv4" = "Usar IPv4 para Netflix" "NetflixIPv4" = "Usar IPv4 para Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "La ruta del archivo para el registro de acceso. El valor especial 'ninguno' deshabilita los registros de acceso" "accessLogDesc" = "La ruta del archivo para el registro de acceso. El valor especial 'ninguno' deshabilita los registros de acceso"
"errorLog" = "Registro de Errores" "errorLog" = "Registro de Errores"
"errorLogDesc" = "La ruta del archivo para el registro de errores. El valor especial 'none' desactiva los registros de errores." "errorLogDesc" = "La ruta del archivo para el registro de errores. El valor especial 'none' desactiva los registros de errores."
"dnsLog" = "Registro DNS"
"dnsLogDesc" = "Si habilitar los registros de consulta DNS"
"maskAddress" = "Enmascarar Dirección"
"maskAddressDesc" = "Máscara de dirección IP, cuando se habilita, reemplazará automáticamente la dirección IP que aparece en el registro."
[pages.xray.rules] [pages.xray.rules]
"first" = "Primero" "first" = "Primero"
@@ -458,7 +485,6 @@
"add" = "Agregar Servidor" "add" = "Agregar Servidor"
"edit" = "Editar Servidor" "edit" = "Editar Servidor"
"domains" = "Dominios" "domains" = "Dominios"
"expectIPs" = "IPs esperadas"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Agregar DNS Falso" "add" = "Agregar DNS Falso"
@@ -568,7 +594,7 @@
"confirmResetTraffic" = "✅ ¿Confirmar Reinicio de Tráfico?" "confirmResetTraffic" = "✅ ¿Confirmar Reinicio de Tráfico?"
"confirmClearIps" = "✅ ¿Confirmar Limpiar IPs?" "confirmClearIps" = "✅ ¿Confirmar Limpiar IPs?"
"confirmRemoveTGUser" = "✅ ¿Confirmar Eliminar Usuario de Telegram?" "confirmRemoveTGUser" = "✅ ¿Confirmar Eliminar Usuario de Telegram?"
"confirmToggle" = "✅ ¿Confirmar habilitar/deshabilitar usuario?" "confirmToggle" = " ✅ ¿Confirmar habilitar/deshabilitar usuario?"
"dbBackup" = "Obtener Copia de Seguridad de BD" "dbBackup" = "Obtener Copia de Seguridad de BD"
"serverUsage" = "Uso del Servidor" "serverUsage" = "Uso del Servidor"
"getInbounds" = "Obtener Entradas" "getInbounds" = "Obtener Entradas"

View File

@@ -44,7 +44,7 @@
"monitor" = "آی‌پی اتصال" "monitor" = "آی‌پی اتصال"
"certificate" = "گواهی دیجیتال" "certificate" = "گواهی دیجیتال"
"fail" = "ناموفق" "fail" = "ناموفق"
"success" = "موفق" "success" = " موفق"
"getVersion" = "دریافت نسخه" "getVersion" = "دریافت نسخه"
"install" = "نصب" "install" = "نصب"
"clients" = "کاربران" "clients" = "کاربران"
@@ -109,7 +109,7 @@
"backup" = "پشتیبان‌گیری" "backup" = "پشتیبان‌گیری"
"backupTitle" = "پشتیبان‌گیری دیتابیس" "backupTitle" = "پشتیبان‌گیری دیتابیس"
"backupDescription" = "توصیه‌می‌شود قبل‌از واردکردن یک دیتابیس جدید، نسخه پشتیبان تهیه ‌کنید" "backupDescription" = "توصیه‌می‌شود قبل‌از واردکردن یک دیتابیس جدید، نسخه پشتیبان تهیه ‌کنید"
"exportDatabase" = "پشتیبان‌گیری" "exportDatabase" = " پشتیبان‌گیری"
"importDatabase" = "بازگرداندن" "importDatabase" = "بازگرداندن"
[pages.inbounds] [pages.inbounds]
@@ -225,6 +225,9 @@
"requestHeader" = "سربرگ درخواست" "requestHeader" = "سربرگ درخواست"
"responseHeader" = "سربرگ پاسخ" "responseHeader" = "سربرگ پاسخ"
[pages.inbounds.stream.quic]
"encryption" = "رمزنگاری"
[pages.settings] [pages.settings]
"title" = "تنظیمات پنل" "title" = "تنظیمات پنل"
"save" = "ذخیره" "save" = "ذخیره"
@@ -285,7 +288,7 @@
"timeZoneDesc" = "وظایف برنامه ریزی شده بر اساس این منطقه‌زمانی اجرا می‌شود" "timeZoneDesc" = "وظایف برنامه ریزی شده بر اساس این منطقه‌زمانی اجرا می‌شود"
"subSettings" = "سابسکریپشن" "subSettings" = "سابسکریپشن"
"subEnable" = "فعال‌سازی سرویس سابسکریپشن" "subEnable" = "فعال‌سازی سرویس سابسکریپشن"
"subEnableDesc" = "سرویس سابسکریپشن‌ را فعال‌می‌کند" "subEnableDesc" = " سرویس سابسکریپشن‌ را فعال‌می‌کند"
"subListen" = "آدرس آی‌پی" "subListen" = "آدرس آی‌پی"
"subListenDesc" = "آدرس آی‌پی برای سرویس سابسکریپشن. برای گوش دادن به‌تمام آی‌پی‌ها خالی‌بگذارید" "subListenDesc" = "آدرس آی‌پی برای سرویس سابسکریپشن. برای گوش دادن به‌تمام آی‌پی‌ها خالی‌بگذارید"
"subPort" = "پورت" "subPort" = "پورت"
@@ -309,14 +312,14 @@
"fragment" = "فرگمنت" "fragment" = "فرگمنت"
"fragmentDesc" = "فعال کردن فرگمنت برای بسته‌ی نخست تی‌ال‌اس" "fragmentDesc" = "فعال کردن فرگمنت برای بسته‌ی نخست تی‌ال‌اس"
"fragmentSett" = "تنظیمات فرگمنت" "fragmentSett" = "تنظیمات فرگمنت"
"noisesDesc" = "فعال کردن Noises." "noiseDesc" = "فعال کردن Noise."
"noisesSett" = "تنظیمات Noises" "noiseSett" = "تنظیمات Noise"
"mux" = "ماکس" "mux" = "ماکس"
"muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند" "muxDesc" = "چندین جریان داده مستقل را در یک جریان داده ثابت منتقل می کند"
"muxSett" = "تنظیمات ماکس" "muxSett" = "تنظیمات ماکس"
"direct" = "اتصال مستقیم" "direct" = "اتصال مستقیم"
"directDesc" = "به طور مستقیم با دامنه ها یا محدوده آی‌پی یک کشور خاص ارتباط برقرار می کند" "directDesc" = "به طور مستقیم با دامنه ها یا محدوده آی‌پی یک کشور خاص ارتباط برقرار می کند"
"directSett" = "گزینه های اتصال مستقیم"
[pages.xray] [pages.xray]
"title" = "پیکربندی ایکس‌ری" "title" = "پیکربندی ایکس‌ری"
@@ -330,14 +333,10 @@
"logConfigsDesc" = "گزارش‌ها ممکن است بر کارایی سرور شما تأثیر بگذارد. توصیه می شود فقط در صورت نیاز آن را عاقلانه فعال کنید" "logConfigsDesc" = "گزارش‌ها ممکن است بر کارایی سرور شما تأثیر بگذارد. توصیه می شود فقط در صورت نیاز آن را عاقلانه فعال کنید"
"blockConfigs" = "سپر محافظ" "blockConfigs" = "سپر محافظ"
"blockConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس پروتکل‌های درخواستی خاص، و وب سایت‌ها مسدود می‌کند" "blockConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس پروتکل‌های درخواستی خاص، و وب سایت‌ها مسدود می‌کند"
"blockConnectionsConfigs" = "مسدود کردن اتصالات" "blockCountryConfigs" = "مسدودسازی کشور"
"blockConnectionsConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس کشور درخواست‌شده خاص مسدود می‌کنند." "blockCountryConfigsDesc" = "این گزینه‌ها ترافیک را بر اساس کشور درخواستی خاص مسدود می‌کند"
"directConnectionsConfigs" = "اتصالات مستقیم" "directCountryConfigs" = "اتصال مستقیم کشور"
"directConnectionsConfigsDesc" = "یک اتصال مستقیم تضمین می‌کند که ترافیک خاص از طریق سرور دیگری مسیریابی نشود." "directCountryConfigsDesc" = "اتصال مستقیم اطمینان حاصل می‌کند که ترافیک خاص از طریق یک سرور دیگر هدایت نمی‌شود."
"blockips" = "مسدود کردن آی‌پی‌ها"
"blockdomains" = "مسدود کردن دامنه‌ها"
"directips" = "آی‌پی‌های مستقیم"
"directdomains" = "دامنه‌های مستقیم"
"ipv4Configs" = "IPv4 مسیریابی" "ipv4Configs" = "IPv4 مسیریابی"
"ipv4ConfigsDesc" = "این گزینه‌ها ترافیک‌ را از طریق آیپینسخه4 به مقصد هدایت می‌کند" "ipv4ConfigsDesc" = "این گزینه‌ها ترافیک‌ را از طریق آیپینسخه4 به مقصد هدایت می‌کند"
"warpConfigs" = "WARP مسیریابی" "warpConfigs" = "WARP مسیریابی"
@@ -360,6 +359,38 @@
"SecurityDesc" = "وب‌سایت‌های ناامن، بدافزار، فیشینگ، و کریپتوماینرها را مسدود می‌کند" "SecurityDesc" = "وب‌سایت‌های ناامن، بدافزار، فیشینگ، و کریپتوماینرها را مسدود می‌کند"
"Speedtest" = "مسدودسازی اسپیدتست" "Speedtest" = "مسدودسازی اسپیدتست"
"SpeedtestDesc" = "اتصال به وب‌سایت‌های تست سرعت را مسدود می‌کند" "SpeedtestDesc" = "اتصال به وب‌سایت‌های تست سرعت را مسدود می‌کند"
"IRIp" = "مسدودسازی اتصال به آی‌پی‌های ایران"
"IRIpDesc" = "اتصال به آی‌پی‌های کشور ایران را مسدود می‌کند"
"IRDomain" = "مسدودسازی اتصال به دامنه‌های‌ ایران"
"IRDomainDesc" = "اتصال به دامنه‌های کشور ایران را مسدود می‌کند"
"ChinaIp" = "مسدودسازی اتصال به آی‌‌پی‌های چین"
"ChinaIpDesc" = "اتصال به آی‌پی‌های کشور چین را مسدود می‌کند"
"ChinaDomain" = "مسدودسازی اتصال به دامنه‌های چین"
"ChinaDomainDesc" = "اتصال به دامنه‌های کشور چین را مسدود می‌کند"
"RussiaIp" = "مسدودسازی اتصال به آی‌پی‌های روسیه"
"RussiaIpDesc" = "اتصال به آی‌پی‌های کشور روسیه را مسدود می‌کند"
"RussiaDomain" = "مسدودسازی اتصال به دامنه‌های روسیه"
"RussiaDomainDesc" = "اتصال به دامنه‌های کشور روسیه را مسدود می‌کند"
"VNIp" = "مسدودسازی اتصال به آی‌پی‌های ویتنام"
"VNIpDesc" = "اتصال به آی‌پی‌های کشور ویتنام را مسدود می‌کند"
"VNDomain" = "مسدودسازی اتصال به دامنه های ویتنام"
"VNDomainDesc" = "اتصال به دامنه‌های کشور ویتنام را مسدود می‌کند"
"DirectIRIp" = "اتصال مستقیم آی‌پی‌های ایران"
"DirectIRIpDesc" = "اتصال مستقیم به آی‌پی‌های کشور ایران"
"DirectIRDomain" = "اتصال مستقیم دامنه‌های ایران"
"DirectIRDomainDesc" = "اتصال مستقیم به دامنه‌های کشور ایران"
"DirectChinaIp" = "اتصال مستقیم آی‌پی‌های چین"
"DirectChinaIpDesc" = "اتصال مستقیم به آی‌پی‌های کشور چین"
"DirectChinaDomain" = "اتصال مستقیم دامنه‌های چین"
"DirectChinaDomainDesc" = "اتصال مستقیم به دامنه‌های کشور چین"
"DirectRussiaIp" = "اتصال مستقیم آی‌پی‌های روسیه"
"DirectRussiaIpDesc" = "اتصال مستقیم به آی‌پی‌های کشور روسیه"
"DirectRussiaDomain" = "اتصال مستقیم دامنه‌های روسیه"
"DirectRussiaDomainDesc" = "اتصال مستقیم به دامنه‌های کشور روسیه"
"DirectVNIp" = "اتصال مستقیم آی‌پی‌های ویتنام"
"DirectVNIpDesc" = "اتصال مستقیم به آی‌پی‌های کشور ویتنام"
"DirectVNDomain" = "اتصال مستقیم دامنه‌های ویتنام"
"DirectVNDomainDesc" = "اتصال مستقیم به دامنه‌های کشور ویتنام"
"GoogleIPv4" = "گوگل" "GoogleIPv4" = "گوگل"
"GoogleIPv4Desc" = "ترافیک را از طریق آیپینسخه4 به گوگل هدایت می‌کند" "GoogleIPv4Desc" = "ترافیک را از طریق آیپینسخه4 به گوگل هدایت می‌کند"
"NetflixIPv4" = "نتفلیکس" "NetflixIPv4" = "نتفلیکس"
@@ -373,11 +404,11 @@
"MetaWARP" = "متا" "MetaWARP" = "متا"
"MetaWARPDesc" = "ترافیک را از طریق وارپ به متا (اینستاگرام، فیس بوک، واتساپ، تردز و...) هدایت می کند." "MetaWARPDesc" = "ترافیک را از طریق وارپ به متا (اینستاگرام، فیس بوک، واتساپ، تردز و...) هدایت می کند."
"AppleWARP" = "اپل" "AppleWARP" = "اپل"
"AppleWARPDesc" = "ترافیک را از طریق وارپ به اپل هدایت می‌کند" "AppleWARPDesc" = " ترافیک را از طریق وارپ به اپل هدایت می‌کند"
"RedditWARP" = "ردیت" "RedditWARP" = "ردیت"
"RedditWARPDesc" = "ترافیک را از طریق وارپ به ردیت هدایت می‌کند" "RedditWARPDesc" = " ترافیک را از طریق وارپ به ردیت هدایت می‌کند"
"SpotifyWARP" = "اسپاتیفای" "SpotifyWARP" = "اسپاتیفای"
"SpotifyWARPDesc" = "ترافیک را از طریق وارپ به اسپاتیفای هدایت می‌کند" "SpotifyWARPDesc" = " ترافیک را از طریق وارپ به اسپاتیفای هدایت می‌کند"
"IRWARP" = "دامنه‌های ایران" "IRWARP" = "دامنه‌های ایران"
"IRWARPDesc" = "ترافیک را از طریق وارپ به دامنه‌های کشور ایران هدایت می‌کند" "IRWARPDesc" = "ترافیک را از طریق وارپ به دامنه‌های کشور ایران هدایت می‌کند"
"Inbounds" = "ورودی‌ها" "Inbounds" = "ورودی‌ها"
@@ -394,10 +425,6 @@
"accessLogDesc" = "مسیر فایل برای گزارش دسترسی. مقدار ویژه «هیچ» گزارش‌های دسترسی را غیرفعال میکند." "accessLogDesc" = "مسیر فایل برای گزارش دسترسی. مقدار ویژه «هیچ» گزارش‌های دسترسی را غیرفعال میکند."
"errorLog" = "گزارش خطا" "errorLog" = "گزارش خطا"
"errorLogDesc" = "مسیر فایل برای ورود به سیستم خطا. مقدار ویژه «هیچ» گزارش های خطا را غیرفعال میکند" "errorLogDesc" = "مسیر فایل برای ورود به سیستم خطا. مقدار ویژه «هیچ» گزارش های خطا را غیرفعال میکند"
"dnsLog" = "گزارش DNS"
"dnsLogDesc" = "آیا ثبت‌های درخواست DNS را فعال کنید"
"maskAddress" = "پنهان کردن آدرس"
"maskAddressDesc" = "پوشش آدرس IP، هنگامی که فعال می‌شود، به طور خودکار آدرس IP که در لاگ ظاهر می‌شود را جایگزین می‌کند."
[pages.xray.rules] [pages.xray.rules]
"first" = "اولین" "first" = "اولین"
@@ -460,7 +487,6 @@
"add" = "افزودن سرور" "add" = "افزودن سرور"
"edit" = "ویرایش سرور" "edit" = "ویرایش سرور"
"domains" = "دامنه‌ها" "domains" = "دامنه‌ها"
"expectIPs" = "آی‌پی‌های مورد انتظار"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "افزودن دی‌ان‌اس جعلی" "add" = "افزودن دی‌ان‌اس جعلی"

View File

@@ -143,7 +143,7 @@
"destinationPort" = "Port Tujuan" "destinationPort" = "Port Tujuan"
"targetAddress" = "Alamat Target" "targetAddress" = "Alamat Target"
"monitorDesc" = "Biarkan kosong untuk mendengarkan semua IP" "monitorDesc" = "Biarkan kosong untuk mendengarkan semua IP"
"meansNoLimit" = "= Unlimited. (unit: GB)" "meansNoLimit" = " = Unlimited. (unit: GB)"
"totalFlow" = "Total Aliran" "totalFlow" = "Total Aliran"
"leaveBlankToNeverExpire" = "Biarkan kosong untuk tidak pernah kedaluwarsa" "leaveBlankToNeverExpire" = "Biarkan kosong untuk tidak pernah kedaluwarsa"
"noRecommendKeepDefault" = "Disarankan untuk tetap menggunakan pengaturan default" "noRecommendKeepDefault" = "Disarankan untuk tetap menggunakan pengaturan default"
@@ -225,6 +225,9 @@
"requestHeader" = "Header Permintaan" "requestHeader" = "Header Permintaan"
"responseHeader" = "Header Respons" "responseHeader" = "Header Respons"
[pages.inbounds.stream.quic]
"encryption" = "Enkripsi"
[pages.settings] [pages.settings]
"title" = "Pengaturan Panel" "title" = "Pengaturan Panel"
"save" = "Simpan" "save" = "Simpan"
@@ -309,14 +312,14 @@
"fragment" = "Fragmentasi" "fragment" = "Fragmentasi"
"fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS" "fragmentDesc" = "Aktifkan fragmentasi untuk paket hello TLS"
"fragmentSett" = "Pengaturan Fragmentasi" "fragmentSett" = "Pengaturan Fragmentasi"
"noisesDesc" = "Aktifkan Noises." "noiseDesc" = "Aktifkan Noise."
"noisesSett" = "Pengaturan Noises" "noiseSett" = "Pengaturan Noise"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada." "muxDesc" = "Mengirimkan beberapa aliran data independen dalam aliran data yang sudah ada."
"muxSett" = "Pengaturan Mux" "muxSett" = "Pengaturan Mux"
"direct" = "Koneksi langsung" "direct" = "Koneksi langsung"
"directDesc" = "Secara langsung membuat koneksi dengan domain atau rentang IP negara tertentu." "directDesc" = "Secara langsung membuat koneksi dengan domain atau rentang IP negara tertentu."
"directSett" = "Opsi Koneksi Langsung"
[pages.xray] [pages.xray]
"title" = "Konfigurasi Xray" "title" = "Konfigurasi Xray"
@@ -330,14 +333,10 @@
"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" "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."
"blockConnectionsConfigs" = "Blokir Koneksi" "blockCountryConfigs" = "Blokir Negara"
"blockConnectionsConfigsDesc" = "Opsi ini akan memblokir lalu lintas berdasarkan negara yang diminta." "blockCountryConfigsDesc" = "Opsi ini akan memblokir lalu lintas berdasarkan negara yang diminta."
"directConnectionsConfigs" = "Koneksi Langsung" "directCountryConfigs" = "Langsung ke Negara"
"directConnectionsConfigsDesc" = "Koneksi langsung memastikan bahwa lalu lintas tertentu tidak dialihkan melalui server lain." "directCountryConfigsDesc" = "Koneksi langsung memastikan bahwa lalu lintas tertentu tidak diarahkan melalui server lain."
"blockips" = "Blokir IP"
"blockdomains" = "Blokir Domain"
"directips" = "IP Langsung"
"directdomains" = "Domain Langsung"
"ipv4Configs" = "Pengalihan IPv4" "ipv4Configs" = "Pengalihan IPv4"
"ipv4ConfigsDesc" = "Opsi ini akan mengalihkan lalu lintas berdasarkan tujuan tertentu melalui IPv4." "ipv4ConfigsDesc" = "Opsi ini akan mengalihkan lalu lintas berdasarkan tujuan tertentu melalui IPv4."
"warpConfigs" = "Pengalihan WARP" "warpConfigs" = "Pengalihan WARP"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Memblokir situs web malware, phishing, dan penambang kripto." "SecurityDesc" = "Memblokir situs web malware, phishing, dan penambang kripto."
"Speedtest" = "Blokir Speedtest" "Speedtest" = "Blokir Speedtest"
"SpeedtestDesc" = "Memblokir pembentukan koneksi ke situs web speedtest." "SpeedtestDesc" = "Memblokir pembentukan koneksi ke situs web speedtest."
"IRIp" = "Blokir Koneksi ke IP Iran"
"IRIpDesc" = "Memblokir pembentukan koneksi ke rentang IP Iran."
"IRDomain" = "Blokir Koneksi ke Domain Iran"
"IRDomainDesc" = "Memblokir pembentukan koneksi ke domain Iran."
"ChinaIp" = "Blokir Koneksi ke IP China"
"ChinaIpDesc" = "Memblokir pembentukan koneksi ke rentang IP China."
"ChinaDomain" = "Blokir Koneksi ke Domain China"
"ChinaDomainDesc" = "Memblokir pembentukan koneksi ke domain China."
"RussiaIp" = "Blokir Koneksi ke IP Rusia"
"RussiaIpDesc" = "Memblokir pembentukan koneksi ke rentang IP Rusia."
"RussiaDomain" = "Blokir Koneksi ke Domain Rusia"
"RussiaDomainDesc" = "Memblokir pembentukan koneksi ke domain Rusia."
"VNIp" = "Blokir Koneksi ke IP Vietnam"
"VNIpDesc" = "Memblokir pembentukan koneksi ke rentang IP Vietnam."
"VNDomain" = "Blokir Koneksi ke Domain Vietnam"
"VNDomainDesc" = "Memblokir pembentukan koneksi ke domain Vietnam."
"DirectIRIp" = "Koneksi Langsung ke IP Iran"
"DirectIRIpDesc" = "Membentuk koneksi langsung ke rentang IP Iran."
"DirectIRDomain" = "Koneksi Langsung ke Domain Iran"
"DirectIRDomainDesc" = "Membentuk koneksi langsung ke domain Iran."
"DirectChinaIp" = "Koneksi Langsung ke IP China"
"DirectChinaIpDesc" = "Membentuk koneksi langsung ke rentang IP China."
"DirectChinaDomain" = "Koneksi Langsung ke Domain China"
"DirectChinaDomainDesc" = "Membentuk koneksi langsung ke domain China."
"DirectRussiaIp" = "Koneksi Langsung ke IP Rusia"
"DirectRussiaIpDesc" = "Membentuk koneksi langsung ke rentang IP Rusia."
"DirectRussiaDomain" = "Koneksi Langsung ke Domain Rusia"
"DirectRussiaDomainDesc" = "Membentuk koneksi langsung ke domain Rusia."
"DirectVNIp" = "Koneksi Langsung ke IP Vietnam"
"DirectVNIpDesc" = "Membentuk koneksi langsung ke rentang IP Vietnam."
"DirectVNDomain" = "Koneksi Langsung ke Domain Vietnam"
"DirectVNDomainDesc" = "Membentuk koneksi langsung ke domain Vietnam."
"GoogleIPv4" = "Google" "GoogleIPv4" = "Google"
"GoogleIPv4Desc" = "Rute lalu lintas ke Google melalui IPv4." "GoogleIPv4Desc" = "Rute lalu lintas ke Google melalui IPv4."
"NetflixIPv4" = "Netflix" "NetflixIPv4" = "Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "Jalur file untuk log akses. Nilai khusus 'tidak ada' menonaktifkan log akses" "accessLogDesc" = "Jalur file untuk log akses. Nilai khusus 'tidak ada' menonaktifkan log akses"
"errorLog" = "Catatan eror" "errorLog" = "Catatan eror"
"errorLogDesc" = "Jalur file untuk log kesalahan. Nilai khusus 'tidak ada' menonaktifkan log kesalahan" "errorLogDesc" = "Jalur file untuk log kesalahan. Nilai khusus 'tidak ada' menonaktifkan log kesalahan"
"dnsLog" = "Log DNS"
"dnsLogDesc" = "Apakah akan mengaktifkan log kueri DNS"
"maskAddress" = "Alamat Masker"
"maskAddressDesc" = "Masker alamat IP, ketika diaktifkan, akan secara otomatis mengganti alamat IP yang muncul di log."
[pages.xray.rules] [pages.xray.rules]
"first" = "Pertama" "first" = "Pertama"
@@ -460,7 +487,6 @@
"add" = "Tambahkan Server" "add" = "Tambahkan Server"
"edit" = "Sunting Server" "edit" = "Sunting Server"
"domains" = "Domains" "domains" = "Domains"
"expectIPs" = "IP yang Diharapkan"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Tambahkan DNS Palsu" "add" = "Tambahkan DNS Palsu"

View File

@@ -43,8 +43,8 @@
"domainName" = "Nome de Domínio" "domainName" = "Nome de Domínio"
"monitor" = "IP de Escuta" "monitor" = "IP de Escuta"
"certificate" = "Certificado Digital" "certificate" = "Certificado Digital"
"fail" = "Falhou" "fail" = " Falhou"
"success" = "Com Sucesso" "success" = " Com Sucesso"
"getVersion" = "Obter Versão" "getVersion" = "Obter Versão"
"install" = "Instalar" "install" = "Instalar"
"clients" = "Clientes" "clients" = "Clientes"
@@ -143,7 +143,7 @@
"destinationPort" = "Porta de Destino" "destinationPort" = "Porta de Destino"
"targetAddress" = "Endereço de Destino" "targetAddress" = "Endereço de Destino"
"monitorDesc" = "Deixe em branco para ouvir todos os IPs" "monitorDesc" = "Deixe em branco para ouvir todos os IPs"
"meansNoLimit" = "= Ilimitado. (unidade: GB)" "meansNoLimit" = " = Ilimitado. (unidade: GB)"
"totalFlow" = "Fluxo Total" "totalFlow" = "Fluxo Total"
"leaveBlankToNeverExpire" = "Deixe em branco para nunca expirar" "leaveBlankToNeverExpire" = "Deixe em branco para nunca expirar"
"noRecommendKeepDefault" = "Recomenda-se manter o padrão" "noRecommendKeepDefault" = "Recomenda-se manter o padrão"
@@ -225,6 +225,9 @@
"requestHeader" = "Cabeçalho da Requisição" "requestHeader" = "Cabeçalho da Requisição"
"responseHeader" = "Cabeçalho da Resposta" "responseHeader" = "Cabeçalho da Resposta"
[pages.inbounds.stream.quic]
"encryption" = "Criptografia"
[pages.settings] [pages.settings]
"title" = "Configurações do Painel" "title" = "Configurações do Painel"
"save" = "Salvar" "save" = "Salvar"
@@ -309,14 +312,14 @@
"fragment" = "Fragmentação" "fragment" = "Fragmentação"
"fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello." "fragmentDesc" = "Ativa a fragmentação para o pacote TLS hello."
"fragmentSett" = "Configurações de Fragmentação" "fragmentSett" = "Configurações de Fragmentação"
"noisesDesc" = "Ativar Noises." "noiseDesc" = "Ativar Noise."
"noisesSett" = "Configurações de Noises" "noiseSett" = "Configurações de Noise"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido." "muxDesc" = "Transmitir múltiplos fluxos de dados independentes dentro de um fluxo de dados estabelecido."
"muxSett" = "Configurações de Mux" "muxSett" = "Configurações de Mux"
"direct" = "Conexão Direta" "direct" = "Conexão Direta"
"directDesc" = "Estabelece conexões diretamente com domínios ou intervalos de IP de um país específico." "directDesc" = "Estabelece conexões diretamente com domínios ou intervalos de IP de um país específico."
"directSett" = "Opções de Conexão Direta"
[pages.xray] [pages.xray]
"title" = "Configurações Xray" "title" = "Configurações Xray"
@@ -330,14 +333,10 @@
"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" "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."
"blockConnectionsConfigs" = "Bloquear Conexões" "blockCountryConfigs" = "Bloquear País"
"blockConnectionsConfigsDesc" = "Essas opções bloquearão o tráfego com base no país solicitado." "blockCountryConfigsDesc" = "Essas opções bloqueiam tráfego com base no país solicitado."
"directConnectionsConfigs" = "Conexões Diretas" "directCountryConfigs" = "País Direto"
"directConnectionsConfigsDesc" = "Uma conexão direta garante que o tráfego específico não seja roteado por outro servidor." "directCountryConfigsDesc" = "Uma conexão direta garante que o tráfego específico não seja roteado por outro servidor."
"blockips" = "Bloquear IPs"
"blockdomains" = "Bloquear Domínios"
"directips" = "IPs Diretos"
"directdomains" = "Domínios Diretos"
"ipv4Configs" = "Roteamento IPv4" "ipv4Configs" = "Roteamento IPv4"
"ipv4ConfigsDesc" = "Essas opções roteam o tráfego para um destino específico via IPv4." "ipv4ConfigsDesc" = "Essas opções roteam o tráfego para um destino específico via IPv4."
"warpConfigs" = "Roteamento WARP" "warpConfigs" = "Roteamento WARP"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Bloqueia sites de malware, phishing e mineradores de criptomoedas." "SecurityDesc" = "Bloqueia sites de malware, phishing e mineradores de criptomoedas."
"Speedtest" = "Bloquear Speedtest" "Speedtest" = "Bloquear Speedtest"
"SpeedtestDesc" = "Bloqueia a conexão com sites de teste de velocidade." "SpeedtestDesc" = "Bloqueia a conexão com sites de teste de velocidade."
"IRIp" = "Bloquear Conexão para IPs do Irã"
"IRIpDesc" = "Bloqueia a conexão com faixas de IP do Irã."
"IRDomain" = "Bloquear Conexão para Domínios do Irã"
"IRDomainDesc" = "Bloqueia a conexão com domínios do Irã."
"ChinaIp" = "Bloquear Conexão para IPs da China"
"ChinaIpDesc" = "Bloqueia a conexão com faixas de IP da China."
"ChinaDomain" = "Bloquear Conexão para Domínios da China"
"ChinaDomainDesc" = "Bloqueia a conexão com domínios da China."
"RussiaIp" = "Bloquear Conexão para IPs da Rússia"
"RussiaIpDesc" = "Bloqueia a conexão com faixas de IP da Rússia."
"RussiaDomain" = "Bloquear Conexão para Domínios da Rússia"
"RussiaDomainDesc" = "Bloqueia a conexão com domínios da Rússia."
"VNIp" = "Bloquear Conexão para IPs do Vietnã"
"VNIpDesc" = "Bloqueia a conexão com faixas de IP do Vietnã."
"VNDomain" = "Bloquear Conexão para Domínios do Vietnã"
"VNDomainDesc" = "Bloqueia a conexão com domínios do Vietnã."
"DirectIRIp" = "Conexão Direta para IPs do Irã"
"DirectIRIpDesc" = "Estabelece conexão diretamente com faixas de IP do Irã."
"DirectIRDomain" = "Conexão Direta para Domínios do Irã"
"DirectIRDomainDesc" = "Estabelece conexão diretamente com domínios do Irã."
"DirectChinaIp" = "Conexão Direta para IPs da China"
"DirectChinaIpDesc" = "Estabelece conexão diretamente com faixas de IP da China."
"DirectChinaDomain" = "Conexão Direta para Domínios da China"
"DirectChinaDomainDesc" = "Estabelece conexão diretamente com domínios da China."
"DirectRussiaIp" = "Conexão Direta para IPs da Rússia"
"DirectRussiaIpDesc" = "Estabelece conexão diretamente com faixas de IP da Rússia."
"DirectRussiaDomain" = "Conexão Direta para Domínios da Rússia"
"DirectRussiaDomainDesc" = "Estabelece conexão diretamente com domínios da Rússia."
"DirectVNIp" = "Conexão Direta para IPs do Vietnã"
"DirectVNIpDesc" = "Estabelece conexão diretamente com faixas de IP do Vietnã."
"DirectVNDomain" = "Conexão Direta para Domínios do Vietnã"
"DirectVNDomainDesc" = "Estabelece conexão diretamente com domínios do Vietnã."
"GoogleIPv4" = "Google" "GoogleIPv4" = "Google"
"GoogleIPv4Desc" = "Roteia tráfego para o Google via IPv4." "GoogleIPv4Desc" = "Roteia tráfego para o Google via IPv4."
"NetflixIPv4" = "Netflix" "NetflixIPv4" = "Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "O caminho do arquivo para o log de acesso. O valor especial 'none' desativa os logs de acesso." "accessLogDesc" = "O caminho do arquivo para o log de acesso. O valor especial 'none' desativa os logs de acesso."
"errorLog" = "Log de Erros" "errorLog" = "Log de Erros"
"errorLogDesc" = "O caminho do arquivo para o log de erros. O valor especial 'none' desativa os logs de erro." "errorLogDesc" = "O caminho do arquivo para o log de erros. O valor especial 'none' desativa os logs de erro."
"dnsLog" = "Log DNS"
"dnsLogDesc" = "Se ativar logs de consulta DNS"
"maskAddress" = "Mascarar Endereço"
"maskAddressDesc" = "Máscara de endereço IP, quando ativado, substitui automaticamente o endereço IP que aparece no log."
[pages.xray.rules] [pages.xray.rules]
"first" = "Primeiro" "first" = "Primeiro"
@@ -460,7 +487,6 @@
"add" = "Adicionar Servidor" "add" = "Adicionar Servidor"
"edit" = "Editar Servidor" "edit" = "Editar Servidor"
"domains" = "Domínios" "domains" = "Domínios"
"expectIPs" = "IPs Esperadas"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Adicionar Fake DNS" "add" = "Adicionar Fake DNS"

View File

@@ -143,7 +143,7 @@
"destinationPort" = "Порт назначения" "destinationPort" = "Порт назначения"
"targetAddress" = "Целевой адрес" "targetAddress" = "Целевой адрес"
"monitorDesc" = "Оставьте пустым по умолчанию" "monitorDesc" = "Оставьте пустым по умолчанию"
"meansNoLimit" = "= Без ограничений (значение: ГБ)" "meansNoLimit" = " = Без ограничений (значение: ГБ)"
"totalFlow" = "Общий расход" "totalFlow" = "Общий расход"
"leaveBlankToNeverExpire" = "Оставьте пустым, чтобы не истекало" "leaveBlankToNeverExpire" = "Оставьте пустым, чтобы не истекало"
"noRecommendKeepDefault" = "Нет требований для сохранения настроек по умолчанию" "noRecommendKeepDefault" = "Нет требований для сохранения настроек по умолчанию"
@@ -225,6 +225,9 @@
"requestHeader" = "Заголовок запроса" "requestHeader" = "Заголовок запроса"
"responseHeader" = "Заголовок ответа" "responseHeader" = "Заголовок ответа"
[pages.inbounds.stream.quic]
"encryption" = "Шифрование"
[pages.settings] [pages.settings]
"title" = "Настройки" "title" = "Настройки"
"save" = "Сохранить" "save" = "Сохранить"
@@ -309,14 +312,14 @@
"fragment" = "Фрагментация" "fragment" = "Фрагментация"
"fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS" "fragmentDesc" = "Включить фрагментацию для пакета приветствия TLS"
"fragmentSett" = "Настройки фрагментации" "fragmentSett" = "Настройки фрагментации"
"noisesDesc" = "Включить Noises." "noiseDesc" = "Включить Noise."
"noisesSett" = "Настройки Noises" "noiseSett" = "Настройки Noise"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Передача нескольких независимых потоков данных в рамках установленного потока данных." "muxDesc" = "Передача нескольких независимых потоков данных в рамках установленного потока данных."
"muxSett" = "Mux Настройки" "muxSett" = "Mux Настройки"
"direct" = "Прямая связь" "direct" = "Прямая связь"
"directDesc" = "Напрямую устанавливает соединения с доменами или диапазонами IP конкретной страны." "directDesc" = "Напрямую устанавливает соединения с доменами или диапазонами IP конкретной страны."
"directSett" = "Варианты прямого подключения"
[pages.xray] [pages.xray]
"title" = "Настройки Xray" "title" = "Настройки Xray"
@@ -330,14 +333,10 @@
"logConfigsDesc" = "Журналы могут повлиять на эффективность вашего сервера. Рекомендуется включать их с умом только в случае ваших нужд!" "logConfigsDesc" = "Журналы могут повлиять на эффективность вашего сервера. Рекомендуется включать их с умом только в случае ваших нужд!"
"blockConfigs" = "Блокировка конфигураций" "blockConfigs" = "Блокировка конфигураций"
"blockConfigsDesc" = "Эти параметры не позволят пользователям подключаться к определенным протоколам и веб-сайтам" "blockConfigsDesc" = "Эти параметры не позволят пользователям подключаться к определенным протоколам и веб-сайтам"
"blockConnectionsConfigs" = "Блокировать соединения" "blockCountryConfigs" = "Конфигурации блокировки страны"
"blockConnectionsConfigsDesc" = "Эти параметры будут блокировать трафик в зависимости от запрашиваемой страны." "blockCountryConfigsDesc" = "Эти параметры не позволят пользователям подключаться к доменам определенной страны"
"directConnectionsConfigs" = "Прямые соединения" "directCountryConfigs" = "Настройки прямого подключения для страны"
"directConnectionsConfigsDesc" = "Прямое соединение гарантирует, что определенный трафик не будет перенаправлен через другой сервер." "directCountryConfigsDesc" = "Прямое подключение обеспечивает, что конкретный трафик не направляется через другой сервер."
"blockips" = "Блокировать IP"
"blockdomains" = "Блокировать домены"
"directips" = "Прямые IP"
"directdomains" = "Прямые домены"
"ipv4Configs" = "Настройки IPv4" "ipv4Configs" = "Настройки IPv4"
"ipv4ConfigsDesc" = "Эти параметры позволят пользователям маршрутизироваться к целевым доменам только через IPv4" "ipv4ConfigsDesc" = "Эти параметры позволят пользователям маршрутизироваться к целевым доменам только через IPv4"
"warpConfigs" = "Настройки WARP" "warpConfigs" = "Настройки WARP"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Изменение шаблона конфигурации для защиты безопасности." "SecurityDesc" = "Изменение шаблона конфигурации для защиты безопасности."
"Speedtest" = "Блокировать сайты для проверки скорости" "Speedtest" = "Блокировать сайты для проверки скорости"
"SpeedtestDesc" = "Изменение шаблона конфигурации для предупреждения подключения к веб-сайтам для тестирования скорости" "SpeedtestDesc" = "Изменение шаблона конфигурации для предупреждения подключения к веб-сайтам для тестирования скорости"
"IRIp" = "Заблокировать подключения к диапазонам IP-адресов Ирана"
"IRIpDesc" = "Изменение конфигурации, чтобы заблокировать подключения к диапазонам IP-адресов Ирана"
"IRDomain" = "Заблокировать подключения к доменам Ирана"
"IRDomainDesc" = "Изменение конфигурации, чтобы заблокировать подключения к доменам Ирана"
"ChinaIp" = "Заблокировать подключения к диапазонам IP-адресов Китая"
"ChinaIpDesc" = "Изменение конфигурации, чтобы заблокировать подключения к диапазонам IP-адресов Китая"
"ChinaDomain" = "Заблокировать подключения к доменам Китая"
"ChinaDomainDesc" = "Изменение конфигурации, чтобы заблокировать подключения к доменам Китая"
"RussiaIp" = "Заблокировать подключения к диапазонам IP-адресов России"
"RussiaIpDesc" = "Изменение конфигурации, чтобы заблокировать подключения к диапазонами IP-адресов России"
"RussiaDomain" = "Заблокировать подключения к доменам России"
"RussiaDomainDesc" = "Изменение конфигурации, чтобы заблокировать подключения к доменам России"
"VNIp" = "Отключить подключение к IP-адресам Вьетнама"
"VNIpDesc" = "Измените шаблон конфигурации, чтобы избежать подключения к диапазонам IP-адресов Вьетнама"
"VNDomain" = "Отключить подключение к доменам Вьетнама"
"VNDomainDesc" = "Измените шаблон конфигурации, чтобы избежать подключения к доменам Вьетнама."
"DirectIRIp" = "Прямое подключения к диапазонам IP-адресов Ирана"
"DirectIRIpDesc" = "Изменение шаблона конфигурации для прямого подключения к диапазонам IP-адресов Ирана"
"DirectIRDomain" = "Прямое подключение к доменам Ирана"
"DirectIRDomainDesc" = "Изменение шаблон конфигурации для прямого подключения к доменам Ирана"
"DirectChinaIp" = "Прямое подключение к диапазонам IP-адресов Китая"
"DirectChinaIpDesc" = "Изменение шаблона конфигурации для прямого подключения к диапазонам IP-адресов Китая"
"DirectChinaDomain" = "Прямое подключение к доменам Китая"
"DirectChinaDomainDesc" = "Изменение шаблона конфигурации для прямого подключения к доменам Китая"
"DirectRussiaIp" = "Прямое подключение к диапазонам IP-адресов России"
"DirectRussiaIpDesc" = "Изменение шаблона конфигурации для прямого подключения к диапазонам IP-адресов России"
"DirectRussiaDomain" = "Прямое подключение к доменам России"
"DirectRussiaDomainDesc" = "Изменение шаблона конфигурации для прямого подключения к доменам России"
"DirectVNIp" = "Прямое подключение к IP-адресам Вьетнама"
"DirectVNIpDesc" = "Измените шаблон конфигурации для прямого подключения к диапазонам IP-адресов Вьетнама"
"DirectVNDomain" = "Прямое подключение к доменам Вьетнама"
"DirectVNDomainDesc" = "Измените шаблон конфигурации для прямого подключения к доменам Вьетнама"
"GoogleIPv4" = "Использовать IPv4 для Google" "GoogleIPv4" = "Использовать IPv4 для Google"
"GoogleIPv4Desc" = "Добавить маршрутизацию для Google для подключения к IPv4" "GoogleIPv4Desc" = "Добавить маршрутизацию для Google для подключения к IPv4"
"NetflixIPv4" = "Использовать IPv4 для Netflix" "NetflixIPv4" = "Использовать IPv4 для Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "Путь к файлу журнала доступа. Специальное значение «none» отключило журналы доступа." "accessLogDesc" = "Путь к файлу журнала доступа. Специальное значение «none» отключило журналы доступа."
"errorLog" = "Журнал ошибок" "errorLog" = "Журнал ошибок"
"errorLogDesc" = "Путь к файлу журнала ошибок. Специальное значение «none» отключает журналы ошибок." "errorLogDesc" = "Путь к файлу журнала ошибок. Специальное значение «none» отключает журналы ошибок."
"dnsLog" = "DNS Журнал"
"dnsLogDesc" = "Включить логи запросов DNS"
"maskAddress" = "Маскировать Адрес"
"maskAddressDesc" = "Маска IP-адреса, при активации автоматически заменяет IP-адрес, который появляется в логе."
[pages.xray.rules] [pages.xray.rules]
"first" = "Первый" "first" = "Первый"
@@ -460,7 +487,6 @@
"add" = "Добавить сервер" "add" = "Добавить сервер"
"edit" = "Редактировать сервер" "edit" = "Редактировать сервер"
"domains" = "Домены" "domains" = "Домены"
"expectIPs" = "Ожидаемые IP"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Добавить поддельный DNS" "add" = "Добавить поддельный DNS"

View File

@@ -143,7 +143,7 @@
"destinationPort" = "Hedef Port" "destinationPort" = "Hedef Port"
"targetAddress" = "Hedef Adres" "targetAddress" = "Hedef Adres"
"monitorDesc" = "Tüm IP'leri dinlemek için boş bırakın" "monitorDesc" = "Tüm IP'leri dinlemek için boş bırakın"
"meansNoLimit" = "= Sınırsız. (birim: GB)" "meansNoLimit" = " = Sınırsız. (birim: GB)"
"totalFlow" = "Toplam Akış" "totalFlow" = "Toplam Akış"
"leaveBlankToNeverExpire" = "Hiçbir zaman sona ermemesi için boş bırakın" "leaveBlankToNeverExpire" = "Hiçbir zaman sona ermemesi için boş bırakın"
"noRecommendKeepDefault" = "Varsayılanı korumanız önerilir" "noRecommendKeepDefault" = "Varsayılanı korumanız önerilir"
@@ -225,6 +225,9 @@
"requestHeader" = "İstek Başlığı" "requestHeader" = "İstek Başlığı"
"responseHeader" = "Yanıt Başlığı" "responseHeader" = "Yanıt Başlığı"
[pages.inbounds.stream.quic]
"encryption" = "Şifreleme"
[pages.settings] [pages.settings]
"title" = "Panel Ayarları" "title" = "Panel Ayarları"
"save" = "Kaydet" "save" = "Kaydet"
@@ -309,14 +312,14 @@
"fragment" = "Parçalama" "fragment" = "Parçalama"
"fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir." "fragmentDesc" = "TLS merhaba paketinin parçalanmasını etkinleştir."
"fragmentSett" = "Parçalama Ayarları" "fragmentSett" = "Parçalama Ayarları"
"noisesDesc" = "Noises'i Etkinleştir." "noiseDesc" = "Noise'i Etkinleştir."
"noisesSett" = "Noises Ayarları" "noiseSett" = "Noise Ayarları"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir." "muxDesc" = "Kurulmuş bir veri akışında birden çok bağımsız veri akışını iletir."
"muxSett" = "Mux Ayarları" "muxSett" = "Mux Ayarları"
"direct" = "Doğrudan Bağlantı" "direct" = "Doğrudan Bağlantı"
"directDesc" = "Belirli bir ülkenin alan adları veya IP aralıkları ile doğrudan bağlantı kurar." "directDesc" = "Belirli bir ülkenin alan adları veya IP aralıkları ile doğrudan bağlantı kurar."
"directSett" = "Doğrudan Bağlantı Seçenekleri"
[pages.xray] [pages.xray]
"title" = "Xray Yapılandırmaları" "title" = "Xray Yapılandırmaları"
@@ -330,14 +333,10 @@
"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ı" "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."
"blockConnectionsConfigs" = "Bağlantıları Engelle" "blockCountryConfigs" = "Ülke Engelleme"
"blockConnectionsConfigsDesc" = "Bu seçenekler belirli bir istenen ülkeye göre trafiği engelleyecektir." "blockCountryConfigsDesc" = "Bu seçenekler belirli istek ülkesi temelinde trafiği engeller."
"directConnectionsConfigs" = "Doğrudan Bağlantılar" "directCountryConfigs" = "Doğrudan Ülke"
"directConnectionsConfigsDesc" = "Doğrudan bağlantı, belirli bir trafiğin başka bir sunucu üzerinden yönlendirilmediğini sağlar." "directCountryConfigsDesc" = "Doğrudan bağlantı, belirli trafiğin başka bir sunucu üzerinden yönlendirilmemesini sağlar."
"blockips" = "IP'leri Engelle"
"blockdomains" = "Alan Adlarını Engelle"
"directips" = "Doğrudan IP'ler"
"directdomains" = "Doğrudan Alan Adları"
"ipv4Configs" = "IPv4 Yönlendirme" "ipv4Configs" = "IPv4 Yönlendirme"
"ipv4ConfigsDesc" = "Bu seçenekler belirli bir varış yerine IPv4 üzerinden trafiği yönlendirir." "ipv4ConfigsDesc" = "Bu seçenekler belirli bir varış yerine IPv4 üzerinden trafiği yönlendirir."
"warpConfigs" = "WARP Yönlendirme" "warpConfigs" = "WARP Yönlendirme"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Kötü amaçlı yazılım, kimlik avı ve kripto madencilik web sitelerini engeller." "SecurityDesc" = "Kötü amaçlı yazılım, kimlik avı ve kripto madencilik web sitelerini engeller."
"Speedtest" = "Speedtest Bağlantısını Engelle" "Speedtest" = "Speedtest Bağlantısını Engelle"
"SpeedtestDesc" = "Speedtest web sitelerine bağlantı kurmayı engeller." "SpeedtestDesc" = "Speedtest web sitelerine bağlantı kurmayı engeller."
"IRIp" = "İran IP'lerine Bağlantıyı Engelle"
"IRIpDesc" = "İran IP aralıklarına bağlantı kurmayı engeller."
"IRDomain" = "İran Alan Adlarına Bağlantıyı Engelle"
"IRDomainDesc" = "İran alan adlarına bağlantı kurmayı engeller."
"ChinaIp" = "Çin IP'lerine Bağlantıyı Engelle"
"ChinaIpDesc" = "Çin IP aralıklarına bağlantı kurmayı engeller."
"ChinaDomain" = "Çin Alan Adlarına Bağlantıyı Engelle"
"ChinaDomainDesc" = "Çin alan adlarına bağlantı kurmayı engeller."
"RussiaIp" = "Rusya IP'lerine Bağlantıyı Engelle"
"RussiaIpDesc" = "Rusya IP aralıklarına bağlantı kurmayı engeller."
"RussiaDomain" = "Rusya Alan Adlarına Bağlantıyı Engelle"
"RussiaDomainDesc" = "Rusya alan adlarına bağlantı kurmayı engeller."
"VNIp" = "Vietnam IP'lerine Bağlantıyı Engelle"
"VNIpDesc" = "Vietnam IP aralıklarına bağlantı kurmayı engeller."
"VNDomain" = "Vietnam Alan Adlarına Bağlantıyı Engelle"
"VNDomainDesc" = "Vietnam alan adlarına bağlantı kurmayı engeller."
"DirectIRIp" = "İran IP'lerine Doğrudan Bağlantı"
"DirectIRIpDesc" = "İran IP aralıklarına doğrudan bağlantı kurar."
"DirectIRDomain" = "İran Alan Adlarına Doğrudan Bağlantı"
"DirectIRDomainDesc" = "İran alan adlarına doğrudan bağlantı kurar."
"DirectChinaIp" = "Çin IP'lerine Doğrudan Bağlantı"
"DirectChinaIpDesc" = "Çin IP aralıklarına doğrudan bağlantı kurar."
"DirectChinaDomain" = "Çin Alan Adlarına Doğrudan Bağlantı"
"DirectChinaDomainDesc" = "Çin alan adlarına doğrudan bağlantı kurar."
"DirectRussiaIp" = "Rusya IP'lerine Doğrudan Bağlantı"
"DirectRussiaIpDesc" = "Rusya IP aralıklarına doğrudan bağlantı kurar."
"DirectRussiaDomain" = "Rusya Alan Adlarına Doğrudan Bağlantı"
"DirectRussiaDomainDesc" = "Rusya alan adlarına doğrudan bağlantı kurar."
"DirectVNIp" = "Vietnam IP'lerine Doğrudan Bağlantı"
"DirectVNIpDesc" = "Vietnam IP aralıklarına doğrudan bağlantı kurar."
"DirectVNDomain" = "Vietnam Alan Adlarına Doğrudan Bağlantı"
"DirectVNDomainDesc" = "Vietnam alan adlarına doğrudan bağlantı kurar."
"GoogleIPv4" = "Google" "GoogleIPv4" = "Google"
"GoogleIPv4Desc" = "Google'a trafiği IPv4 üzerinden yönlendirir." "GoogleIPv4Desc" = "Google'a trafiği IPv4 üzerinden yönlendirir."
"NetflixIPv4" = "Netflix" "NetflixIPv4" = "Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "Erişim günlüğü için dosya yolu. 'none' özel değeri erişim günlüklerini devre dışı bırakır" "accessLogDesc" = "Erişim günlüğü için dosya yolu. 'none' özel değeri erişim günlüklerini devre dışı bırakır"
"errorLog" = "Hata Günlüğü" "errorLog" = "Hata Günlüğü"
"errorLogDesc" = "Hata günlüğü için dosya yolu. 'none' özel değeri hata günlüklerini devre dışı bırakır" "errorLogDesc" = "Hata günlüğü için dosya yolu. 'none' özel değeri hata günlüklerini devre dışı bırakır"
"dnsLog" = "DNS Günlüğü"
"dnsLogDesc" = "DNS sorgu günlüklerini etkinleştirin"
"maskAddress" = "Adres Maskesi"
"maskAddressDesc" = "IP adresi maskesi, etkinleştirildiğinde, günlükte görünen IP adresini otomatik olarak değiştirecektir."
[pages.xray.rules] [pages.xray.rules]
"first" = "İlk" "first" = "İlk"
@@ -460,7 +487,6 @@
"add" = "Sunucu Ekle" "add" = "Sunucu Ekle"
"edit" = "Sunucuyu Düzenle" "edit" = "Sunucuyu Düzenle"
"domains" = "Alan Adları" "domains" = "Alan Adları"
"expectIPs" = "Beklenen IP'ler"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Sahte DNS Ekle" "add" = "Sahte DNS Ekle"

View File

@@ -43,8 +43,8 @@
"domainName" = "Доменне ім`я" "domainName" = "Доменне ім`я"
"monitor" = "Слухати IP" "monitor" = "Слухати IP"
"certificate" = "Цифровий сертифікат" "certificate" = "Цифровий сертифікат"
"fail" = "Помилка" "fail" = " Помилка"
"success" = "Успішно" "success" = " Успішно"
"getVersion" = "Отримати версію" "getVersion" = "Отримати версію"
"install" = "Встановити" "install" = "Встановити"
"clients" = "Клієнти" "clients" = "Клієнти"
@@ -143,7 +143,7 @@
"destinationPort" = "Порт призначення" "destinationPort" = "Порт призначення"
"targetAddress" = "Цільова адреса" "targetAddress" = "Цільова адреса"
"monitorDesc" = "Залиште порожнім, щоб слухати всі IP-адреси" "monitorDesc" = "Залиште порожнім, щоб слухати всі IP-адреси"
"meansNoLimit" = "= Необмежено. (одиниця: ГБ)" "meansNoLimit" = " = Необмежено. (одиниця: ГБ)"
"totalFlow" = "Загальна витрата" "totalFlow" = "Загальна витрата"
"leaveBlankToNeverExpire" = "Залиште порожнім, щоб ніколи не закінчувався" "leaveBlankToNeverExpire" = "Залиште порожнім, щоб ніколи не закінчувався"
"noRecommendKeepDefault" = "Рекомендується зберегти значення за замовчуванням" "noRecommendKeepDefault" = "Рекомендується зберегти значення за замовчуванням"
@@ -225,6 +225,9 @@
"requestHeader" = "Заголовок запиту" "requestHeader" = "Заголовок запиту"
"responseHeader" = "Заголовок відповіді" "responseHeader" = "Заголовок відповіді"
[pages.inbounds.stream.quic]
"encryption" = "Шифрування"
[pages.settings] [pages.settings]
"title" = "Параметри панелі" "title" = "Параметри панелі"
"save" = "Зберегти" "save" = "Зберегти"
@@ -309,14 +312,14 @@
"fragment" = "Фрагментація" "fragment" = "Фрагментація"
"fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS" "fragmentDesc" = "Увімкнути фрагментацію для пакету привітання TLS"
"fragmentSett" = "Параметри фрагментації" "fragmentSett" = "Параметри фрагментації"
"noisesDesc" = "Увімкнути Noises." "noiseDesc" = "Увімкнути Noise."
"noisesSett" = "Налаштування Noises" "noiseSett" = "Налаштування Noise"
"mux" = "Mux" "mux" = "Mux"
"muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних." "muxDesc" = "Передавати кілька незалежних потоків даних у межах встановленого потоку даних."
"muxSett" = "Налаштування Mux" "muxSett" = "Налаштування Mux"
"direct" = "Пряме підключення" "direct" = "Пряме підключення"
"directDesc" = "Безпосередньо встановлює з’єднання з доменами або діапазонами IP певної країни." "directDesc" = "Безпосередньо встановлює з’єднання з доменами або діапазонами IP певної країни."
"directSett" = "Параметри прямого підключення"
[pages.xray] [pages.xray]
"title" = "Xray конфігурації" "title" = "Xray конфігурації"
@@ -330,14 +333,10 @@
"logConfigsDesc" = "Журнали можуть вплинути на ефективність вашого сервера. Рекомендується вмикати його з розумом лише у випадку ваших потреб" "logConfigsDesc" = "Журнали можуть вплинути на ефективність вашого сервера. Рекомендується вмикати його з розумом лише у випадку ваших потреб"
"blockConfigs" = "Захисний екран" "blockConfigs" = "Захисний екран"
"blockConfigsDesc" = "Ці параметри блокуватимуть трафік на основі конкретних запитуваних протоколів і веб-сайтів." "blockConfigsDesc" = "Ці параметри блокуватимуть трафік на основі конкретних запитуваних протоколів і веб-сайтів."
"blockConnectionsConfigs" = "Блокувати з'єднання" "blockCountryConfigs" = "Заблокувати країну"
"blockConnectionsConfigsDesc" = "Ці параметри блокуватимуть трафік на основі запитаних країн." "blockCountryConfigsDesc" = "Ці параметри блокуватимуть трафік на основі конкретної запитуваної країни."
"directConnectionsConfigs" = "Прямі з'єднання" "directCountryConfigs" = "Пряма країна"
"directConnectionsConfigsDesc" = "Пряме з'єднання гарантує, що певний трафік не буде маршрутизовано через інший сервер." "directCountryConfigsDesc" = "Пряме підключення забезпечує, що конкретний трафік не маршрутизується через інший сервер."
"blockips" = "Блокувати IP"
"blockdomains" = "Блокувати домени"
"directips" = "Прямі IP"
"directdomains" = "Прямі домени"
"ipv4Configs" = "Маршрутизація IPv4" "ipv4Configs" = "Маршрутизація IPv4"
"ipv4ConfigsDesc" = "Ці параметри спрямовуватимуть трафік на основі певного призначення через IPv4." "ipv4ConfigsDesc" = "Ці параметри спрямовуватимуть трафік на основі певного призначення через IPv4."
"warpConfigs" = "WARP маршрутизація" "warpConfigs" = "WARP маршрутизація"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Блокує веб-сайти шкідливого програмного забезпечення, фішингу та майнерів." "SecurityDesc" = "Блокує веб-сайти шкідливого програмного забезпечення, фішингу та майнерів."
"Speedtest" = "Заблокувати Speedtest" "Speedtest" = "Заблокувати Speedtest"
"SpeedtestDesc" = "Блокує підключення до веб-сайтів для тестування швидкості." "SpeedtestDesc" = "Блокує підключення до веб-сайтів для тестування швидкості."
"IRIp" = "Блокувати підключення до IP-адрес Ірану"
"IRIpDesc" = "Блокує встановлення з'єднань з діапазонами IP Ірану."
"IRDomain" = "Блокувати підключення до доменів Ірану"
"IRDomainDesc" = "Блокує встановлення з'єднань з доменами Ірану."
"ChinaIp" = "Блокувати підключення до IP-адрес Китаю"
"ChinaIpDesc" = "Блокує встановлення з'єднань із діапазонами IP-адрес Китаю."
"ChinaDomain" = "Блокувати підключення до китайських доменів"
"ChinaDomainDesc" = "Блокує встановлення підключень до доменів Китаю."
"RussiaIp" = "Блокувати підключення до російських IP-адрес"
"RussiaIpDesc" = "Блокує встановлення з'єднань з діапазонами IP-адрес Росії."
"RussiaDomain" = "Блокувати підключення до російських доменів"
"RussiaDomainDesc" = "Блокує встановлення з'єднань з російськими доменами."
"VNIp" = "Блокувати підключення до IP-адрес В'єтнаму"
"VNIpDesc" = "Блокує встановлення з'єднань із діапазонами IP-адрес В'єтнаму."
"VNDomain" = "Блокувати підключення до доменів В'єтнаму"
"VNDomainDesc" = "Блокує встановлення з'єднань із доменами В'єтнаму."
"DirectIRIp" = "Пряме підключення до IP-адрес Ірану"
"DirectIRIpDesc" = "Безпосередньо встановлює з'єднання з діапазонами IP Ірану."
"DirectIRDomain" = "Пряме підключення до доменів Ірану"
"DirectIRDomainDesc" = "Безпосередньо встановлює підключення до доменів Ірану."
"DirectChinaIp" = "Пряме підключення до китайських IP-адрес"
"DirectChinaIpDesc" = "Безпосередньо встановлює підключення до IP-діапазонів Китаю."
"DirectChinaDomain" = "Пряме підключення до китайських доменів"
"DirectChinaDomainDesc" = "Безпосередньо встановлює підключення до доменів Китаю."
"DirectRussiaIp" = "Пряме підключення до IP-адрес Росії"
"DirectRussiaIpDesc" = "Безпосередньо встановлює з'єднання з діапазонами IP-адрес Росії."
"DirectRussiaDomain" = "Пряме підключення до російських доменів"
"DirectRussiaDomainDesc" = "Безпосередньо встановлює підключення до російських доменів."
"DirectVNIp" = "Пряме підключення до IP-адрес В'єтнаму"
"DirectVNIpDesc" = "Безпосередньо встановлює з'єднання з діапазонами IP-адрес В'єтнаму."
"DirectVNDomain" = "Пряме підключення до доменів В'єтнаму"
"DirectVNDomainDesc" = "Безпосередньо встановлює з'єднання з доменами В'єтнаму."
"GoogleIPv4" = "Google" "GoogleIPv4" = "Google"
"GoogleIPv4Desc" = "Направляє трафік до Google через IPv4." "GoogleIPv4Desc" = "Направляє трафік до Google через IPv4."
"NetflixIPv4" = "Netflix" "NetflixIPv4" = "Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "Шлях до файлу журналу доступу. Спеціальне значення 'none' вимикає журнали доступу" "accessLogDesc" = "Шлях до файлу журналу доступу. Спеціальне значення 'none' вимикає журнали доступу"
"errorLog" = "Журнал помилок" "errorLog" = "Журнал помилок"
"errorLogDesc" = "Шлях до файлу журналу помилок. Спеціальне значення 'none' вимикає журнали помилок" "errorLogDesc" = "Шлях до файлу журналу помилок. Спеціальне значення 'none' вимикає журнали помилок"
"dnsLog" = "Журнал DNS"
"dnsLogDesc" = "Чи включити журнали запитів DNS"
"maskAddress" = "Маскувати Адресу"
"maskAddressDesc" = "Маска IP-адреси, при активації автоматично замінює IP-адресу, яка з'являється у журналі."
[pages.xray.rules] [pages.xray.rules]
"first" = "Перший" "first" = "Перший"
@@ -460,7 +487,6 @@
"add" = "Додати сервер" "add" = "Додати сервер"
"edit" = "Редагувати сервер" "edit" = "Редагувати сервер"
"domains" = "Домени" "domains" = "Домени"
"expectIPs" = "Очікувані IP"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Додати підроблений DNS" "add" = "Додати підроблений DNS"

View File

@@ -143,7 +143,7 @@
"destinationPort" = "Cổng đích" "destinationPort" = "Cổng đích"
"targetAddress" = "Địa chỉ mục tiêu" "targetAddress" = "Địa chỉ mục tiêu"
"monitorDesc" = "Mặc định để trống" "monitorDesc" = "Mặc định để trống"
"meansNoLimit" = "= Không giới hạn (đơn vị: GB)" "meansNoLimit" = " = Không giới hạn (đơn vị: GB)"
"totalFlow" = "Tổng lưu lượng" "totalFlow" = "Tổng lưu lượng"
"leaveBlankToNeverExpire" = "Để trống để không bao giờ hết hạn" "leaveBlankToNeverExpire" = "Để trống để không bao giờ hết hạn"
"noRecommendKeepDefault" = "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định" "noRecommendKeepDefault" = "Không yêu cầu đặc biệt để giữ nguyên cài đặt mặc định"
@@ -225,6 +225,9 @@
"requestHeader" = "Header yêu cầu" "requestHeader" = "Header yêu cầu"
"responseHeader" = "Header phản hồi" "responseHeader" = "Header phản hồi"
[pages.inbounds.stream.quic]
"encryption" = "Mã hóa"
[pages.settings] [pages.settings]
"title" = "Cài đặt" "title" = "Cài đặt"
"save" = "Lưu" "save" = "Lưu"
@@ -309,14 +312,14 @@
"fragment" = "Sự phân mảnh" "fragment" = "Sự phân mảnh"
"fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello" "fragmentDesc" = "Kích hoạt phân mảnh cho gói TLS hello"
"fragmentSett" = "Cài đặt phân mảnh" "fragmentSett" = "Cài đặt phân mảnh"
"noisesDesc" = "Bật Noises." "noiseDesc" = "Bật Noise."
"noisesSett" = "Cài đặt Noises" "noiseSett" = "Cài đặt Noise"
"mux" = "Mux" "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." "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" "muxSett" = "Mux Cài đặt"
"direct" = "Kết nối trực tiếp" "direct" = "Kết nối trực tiếp"
"directDesc" = "Trực tiếp thiết lập kết nối với tên miền hoặc dải IP của một quốc gia cụ thể." "directDesc" = "Trực tiếp thiết lập kết nối với tên miền hoặc dải IP của một quốc gia cụ thể."
"directSett" = "Tùy chọn kết nối trực tiếp"
[pages.xray] [pages.xray]
"title" = "Cài đặt Xray" "title" = "Cài đặt Xray"
@@ -330,14 +333,10 @@
"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" "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ể."
"blockConnectionsConfigs" = "Chặn Kết Nối" "blockCountryConfigs" = "Cấu hình Chặn Quốc gia"
"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ể." "blockCountryConfigsDesc" = "Những tùy chọn này sẽ ngăn người dùng kết nối đến các tên miền quốc gia cụ thể."
"directConnectionsConfigs" = "Kết Nối Trực Tiếp" "directCountryConfigs" = "Cấu hình Kết nối Trực tiếp Quốc gia"
"directConnectionsConfigsDesc" = "Kết nối trực tiếp đảm bảo rằng lưu lượng truy cập cụ thể không được định tuyến qua máy chủ khác." "directCountryConfigsDesc" = "Một kết nối trực tiếp đảm bảo rằng lưu lượng cụ thể không được định tuyến qua một máy chủ khác."
"blockips" = "Chặn IP"
"blockdomains" = "Chặn Tên Miền"
"directips" = "IP Trực Tiếp"
"directdomains" = "Tên Miền Trực Tiếp"
"ipv4Configs" = "Cấu hình IPv4" "ipv4Configs" = "Cấu hình IPv4"
"ipv4ConfigsDesc" = "Những tùy chọn này sẽ chỉ định kết nối đến các tên miền mục tiêu qua IPv4." "ipv4ConfigsDesc" = "Những tùy chọn này sẽ chỉ định kết nối đến các tên miền mục tiêu qua IPv4."
"warpConfigs" = "Cấu hình WARP" "warpConfigs" = "Cấu hình WARP"
@@ -360,6 +359,38 @@
"SecurityDesc" = "Thay đổi mẫu cấu hình để bảo vệ Bảo mật." "SecurityDesc" = "Thay đổi mẫu cấu hình để bảo vệ Bảo mật."
"Speedtest" = "Chặn Trang web Speedtest" "Speedtest" = "Chặn Trang web Speedtest"
"SpeedtestDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến các trang web Speedtest." "SpeedtestDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến các trang web Speedtest."
"IRIp" = "Vô hiệu hóa kết nối đến dải IP của Iran"
"IRIpDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến dải IP của Iran."
"IRDomain" = "Vô hiệu hóa kết nối đến tên miền của Iran"
"IRDomainDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến các tên miền của Iran."
"ChinaIp" = "Vô hiệu hóa kết nối đến dải IP của Trung Quốc"
"ChinaIpDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến dải IP của Trung Quốc."
"ChinaDomain" = "Vô hiệu hóa kết nối đến tên miền của Trung Quốc"
"ChinaDomainDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến các tên miền của Trung Quốc."
"RussiaIp" = "Vô hiệu hóa kết nối đến dải IP của Nga"
"RussiaIpDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến dải IP của Nga."
"RussiaDomain" = "Vô hiệu hóa kết nối đến tên miền của Nga"
"RussiaDomainDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến các tên miền của Nga."
"VNIp" = "Vô hiệu hóa kết nối đến dải IP của Việt Nam"
"VNIpDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến dải IP của Việt Nam."
"VNDomain" = "Vô hiệu hóa kết nối đến tên miền của Việt Nam"
"VNDomainDesc" = "Thay đổi mẫu cấu hình để tránh kết nối đến các tên miền của Việt Nam."
"DirectIRIp" = "Kết nối trực tiếp đến dải IP của Iran"
"DirectIRIpDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến dải IP của Iran."
"DirectIRDomain" = "Kết nối trực tiếp đến tên miền của Iran"
"DirectIRDomainDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến các tên miền của Iran."
"DirectChinaIp" = "Kết nối trực tiếp đến dải IP của Trung Quốc"
"DirectChinaIpDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến dải IP của Trung Quốc."
"DirectChinaDomain" = "Kết nối trực tiếp đến tên miền của Trung Quốc"
"DirectChinaDomainDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến các tên miền của Trung Quốc."
"DirectRussiaIp" = "Kết nối trực tiếp đến dải IP của Nga"
"DirectRussiaIpDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến dải IP của Nga."
"DirectRussiaDomain" = "Kết nối trực tiếp đến tên miền của Nga"
"DirectRussiaDomainDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến các tên miền của Nga."
"DirectVNIp" = "Kết nối trực tiếp đến dải IP của Việt Nam"
"DirectVNIpDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến dải IP của Việt Nam"
"DirectVNDomain" = "Kết nối trực tiếp đến tên miền của Việt Nam"
"DirectVNDomainDesc" = "Thay đổi mẫu cấu hình cho kết nối trực tiếp đến các tên miền của Việt Nam."
"GoogleIPv4" = "Sử dụng IPv4 cho Google" "GoogleIPv4" = "Sử dụng IPv4 cho Google"
"GoogleIPv4Desc" = "Thêm định tuyến cho Google để kết nối qua IPv4." "GoogleIPv4Desc" = "Thêm định tuyến cho Google để kết nối qua IPv4."
"NetflixIPv4" = "Sử dụng IPv4 cho Netflix" "NetflixIPv4" = "Sử dụng IPv4 cho Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "Đường dẫn tệp cho nhật ký truy cập. Nhật ký truy cập bị vô hiệu hóa có giá trị đặc biệt 'không'" "accessLogDesc" = "Đường dẫn tệp cho nhật ký truy cập. Nhật ký truy cập bị vô hiệu hóa có giá trị đặc biệt 'không'"
"errorLog" = "Nhật ký lỗi" "errorLog" = "Nhật ký lỗi"
"errorLogDesc" = "Đường dẫn tệp cho nhật ký lỗi. Nhật ký lỗi bị vô hiệu hóa có giá trị đặc biệt 'không'" "errorLogDesc" = "Đường dẫn tệp cho nhật ký lỗi. Nhật ký lỗi bị vô hiệu hóa có giá trị đặc biệt 'không'"
"dnsLog" = "Nhật ký DNS"
"dnsLogDesc" = "Có bật nhật ký truy vấn DNS không"
"maskAddress" = "Ẩn Địa Chỉ"
"maskAddressDesc" = "Mặt nạ địa chỉ IP, khi được bật, sẽ tự động thay thế địa chỉ IP xuất hiện trong nhật ký."
[pages.xray.rules] [pages.xray.rules]
"first" = "Đầu tiên" "first" = "Đầu tiên"
@@ -460,7 +487,6 @@
"add" = "Thêm máy chủ" "add" = "Thêm máy chủ"
"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"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "Thêm DNS giả" "add" = "Thêm DNS giả"

View File

@@ -143,7 +143,7 @@
"destinationPort" = "目标端口" "destinationPort" = "目标端口"
"targetAddress" = "目标地址" "targetAddress" = "目标地址"
"monitorDesc" = "留空表示监听所有 IP" "monitorDesc" = "留空表示监听所有 IP"
"meansNoLimit" = "= 无限制单位GB)" "meansNoLimit" = " = 无限制单位GB)"
"totalFlow" = "总流量" "totalFlow" = "总流量"
"leaveBlankToNeverExpire" = "留空表示永不过期" "leaveBlankToNeverExpire" = "留空表示永不过期"
"noRecommendKeepDefault" = "建议保留默认值" "noRecommendKeepDefault" = "建议保留默认值"
@@ -225,6 +225,9 @@
"requestHeader" = "请求头" "requestHeader" = "请求头"
"responseHeader" = "响应头" "responseHeader" = "响应头"
[pages.inbounds.stream.quic]
"encryption" = "加密"
[pages.settings] [pages.settings]
"title" = "面板设置" "title" = "面板设置"
"save" = "保存" "save" = "保存"
@@ -309,14 +312,14 @@
"fragment" = "分片" "fragment" = "分片"
"fragmentDesc" = "启用 TLS hello 数据包分片" "fragmentDesc" = "启用 TLS hello 数据包分片"
"fragmentSett" = "设置" "fragmentSett" = "设置"
"noisesDesc" = "启用 Noises." "noiseDesc" = "启用 Noise."
"noisesSett" = "Noises 设置" "noiseSett" = "Noise 设置"
"mux" = "多路复用器" "mux" = "多路复用器"
"muxDesc" = "在已建立的数据流内传输多个独立的数据流" "muxDesc" = "在已建立的数据流内传输多个独立的数据流"
"muxSett" = "复用器设置" "muxSett" = "复用器设置"
"direct" = "直接连接" "direct" = "直接连接"
"directDesc" = "直接与特定国家的域或IP范围建立连接" "directDesc" = "直接与特定国家的域或IP范围建立连接"
"directSett" = "直接连接选项"
[pages.xray] [pages.xray]
"title" = "Xray 配置" "title" = "Xray 配置"
@@ -330,14 +333,10 @@
"logConfigsDesc" = "日志可能会影响服务器的性能,建议仅在需要时启用" "logConfigsDesc" = "日志可能会影响服务器的性能,建议仅在需要时启用"
"blockConfigs" = "防护屏蔽" "blockConfigs" = "防护屏蔽"
"blockConfigsDesc" = "这些选项将阻止用户连接到特定协议和网站" "blockConfigsDesc" = "这些选项将阻止用户连接到特定协议和网站"
"blockConnectionsConfigs" = "阻止连接" "blockCountryConfigs" = "屏蔽国家/地区"
"blockConnectionsConfigsDesc" = "这些选项将根据特定的请求国家阻止流量。" "blockCountryConfigsDesc" = "这些选项将阻止用户连接到特定国家/地区"
"directConnectionsConfigs" = "直接连接" "directCountryConfigs" = "直连国家/地区"
"directConnectionsConfigsDesc" = "直接连接确保特定流量不会通过其他服务器路由" "directCountryConfigsDesc" = "直接连接确保特定流量不会通过其他服务器路由"
"blockips" = "阻止IP"
"blockdomains" = "阻止域名"
"directips" = "直接IP"
"directdomains" = "直接域名"
"ipv4Configs" = "IPv4 路由" "ipv4Configs" = "IPv4 路由"
"ipv4ConfigsDesc" = "此选项将仅通过 IPv4 路由到目标域" "ipv4ConfigsDesc" = "此选项将仅通过 IPv4 路由到目标域"
"warpConfigs" = "WARP 路由" "warpConfigs" = "WARP 路由"
@@ -360,6 +359,38 @@
"SecurityDesc" = "屏蔽恶意软件、网络钓鱼和挖矿网站" "SecurityDesc" = "屏蔽恶意软件、网络钓鱼和挖矿网站"
"Speedtest" = "屏蔽测速网站" "Speedtest" = "屏蔽测速网站"
"SpeedtestDesc" = "阻止连接到测速网站" "SpeedtestDesc" = "阻止连接到测速网站"
"IRIp" = "屏蔽连接到伊朗 IP"
"IRIpDesc" = "阻止建立到伊朗 IP 范围的连接"
"IRDomain" = "屏蔽连接到伊朗域名"
"IRDomainDesc" = "阻止建立到伊朗域名的连接"
"ChinaIp" = "屏蔽连接到中国 IP"
"ChinaIpDesc" = "阻止建立到中国 IP 范围的连接"
"ChinaDomain" = "屏蔽连接到中国域名"
"ChinaDomainDesc" = "阻止建立到中国域名的连接"
"RussiaIp" = "屏蔽连接到俄罗斯 IP"
"RussiaIpDesc" = "阻止建立到俄罗斯 IP 范围的连接"
"RussiaDomain" = "屏蔽连接到俄罗斯域名"
"RussiaDomainDesc" = "阻止建立到俄罗斯域名的连接"
"VNIp" = "屏蔽连接到越南 IP"
"VNIpDesc" = "阻止建立到越南 IP 范围的连接"
"VNDomain" = "屏蔽连接到越南域名"
"VNDomainDesc" = "阻止建立到越南域名的连接"
"DirectIRIp" = "直连伊朗 IP"
"DirectIRIpDesc" = "直接建立到伊朗 IP 范围的连接"
"DirectIRDomain" = "直连伊朗域名"
"DirectIRDomainDesc" = "直接建立到伊朗域名的连接"
"DirectChinaIp" = "直连中国 IP"
"DirectChinaIpDesc" = "直接建立到中国 IP 范围的连接"
"DirectChinaDomain" = "直连中国域名"
"DirectChinaDomainDesc" = "直接建立到中国域名的连接"
"DirectRussiaIp" = "直连俄罗斯 IP"
"DirectRussiaIpDesc" = "直接建立到俄罗斯 IP 范围的连接"
"DirectRussiaDomain" = "直连俄罗斯域名"
"DirectRussiaDomainDesc" = "直接建立到俄罗斯域名的连接"
"DirectVNIp" = "直连越南 IP"
"DirectVNIpDesc" = "直接建立到越南 IP 范围的连接"
"DirectVNDomain" = "直连越南域名"
"DirectVNDomainDesc" = "直接建立到越南域名的连接"
"GoogleIPv4" = "Google" "GoogleIPv4" = "Google"
"GoogleIPv4Desc" = "通过 IPv4 将流量路由到谷歌" "GoogleIPv4Desc" = "通过 IPv4 将流量路由到谷歌"
"NetflixIPv4" = "Netflix" "NetflixIPv4" = "Netflix"
@@ -394,10 +425,6 @@
"accessLogDesc" = "访问日志的文件路径。特殊值 'none' 禁用访问日志" "accessLogDesc" = "访问日志的文件路径。特殊值 'none' 禁用访问日志"
"errorLog" = "错误日志" "errorLog" = "错误日志"
"errorLogDesc" = "错误日志的文件路径。特殊值 'none' 禁用错误日志" "errorLogDesc" = "错误日志的文件路径。特殊值 'none' 禁用错误日志"
"dnsLog" = "DNS 日志"
"dnsLogDesc" = "是否启用 DNS 查询日志"
"maskAddress" = "隐藏地址"
"maskAddressDesc" = "IP 地址掩码,启用时会自动替换日志中出现的 IP 地址。"
[pages.xray.rules] [pages.xray.rules]
"first" = "置顶" "first" = "置顶"
@@ -460,7 +487,6 @@
"add" = "添加服务器" "add" = "添加服务器"
"edit" = "编辑服务器" "edit" = "编辑服务器"
"domains" = "域" "domains" = "域"
"expectIPs" = "预期 IP"
[pages.xray.fakedns] [pages.xray.fakedns]
"add" = "添加假 DNS" "add" = "添加假 DNS"

81
x-ui.sh
View File

@@ -36,12 +36,12 @@ fi
echo "The OS release is: $release" echo "The OS release is: $release"
os_version="" os_version=""
os_version=$(grep "^VERSION_ID" /etc/os-release | cut -d '=' -f2 | tr -d '"' | tr -d '.') os_version=$(grep -i version_id /etc/os-release | cut -d \" -f2 | cut -d . -f1)
if [[ "${release}" == "arch" ]]; then if [[ "${release}" == "arch" ]]; then
echo "Your OS is Arch Linux" echo "Your OS is Arch Linux"
elif [[ "${release}" == "parch" ]]; then elif [[ "${release}" == "parch" ]]; then
echo "Your OS is Parch Linux" echo "Your OS is Parch linux"
elif [[ "${release}" == "manjaro" ]]; then elif [[ "${release}" == "manjaro" ]]; then
echo "Your OS is Manjaro" echo "Your OS is Manjaro"
elif [[ "${release}" == "armbian" ]]; then elif [[ "${release}" == "armbian" ]]; then
@@ -53,28 +53,24 @@ elif [[ "${release}" == "centos" ]]; then
echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1 echo -e "${red} Please use CentOS 8 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "ubuntu" ]]; then elif [[ "${release}" == "ubuntu" ]]; then
if [[ ${os_version} -lt 2004 ]]; then if [[ ${os_version} -lt 20 ]]; then
echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1 echo -e "${red} Please use Ubuntu 20 or higher version!${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "fedora" ]]; then elif [[ "${release}" == "fedora" ]]; then
if [[ ${os_version} -lt 36 ]]; then if [[ ${os_version} -lt 36 ]]; then
echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1 echo -e "${red} Please use Fedora 36 or higher version!${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "amzn" ]]; then
if [[ ${os_version} != "2023" ]]; then
echo -e "${red} Please use Amazon Linux 2023!${plain}\n" && exit 1
fi
elif [[ "${release}" == "debian" ]]; then elif [[ "${release}" == "debian" ]]; then
if [[ ${os_version} -lt 11 ]]; then if [[ ${os_version} -lt 11 ]]; then
echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1 echo -e "${red} Please use Debian 11 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "almalinux" ]]; then elif [[ "${release}" == "almalinux" ]]; then
if [[ ${os_version} -lt 80 ]]; then if [[ ${os_version} -lt 9 ]]; then
echo -e "${red} Please use AlmaLinux 8.0 or higher ${plain}\n" && exit 1 echo -e "${red} Please use AlmaLinux 9 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "rocky" ]]; then elif [[ "${release}" == "rocky" ]]; then
if [[ ${os_version} -lt 8 ]]; then if [[ ${os_version} -lt 9 ]]; then
echo -e "${red} Please use Rocky Linux 8 or higher ${plain}\n" && exit 1 echo -e "${red} Please use Rocky Linux 9 or higher ${plain}\n" && exit 1
fi fi
elif [[ "${release}" == "oracle" ]]; then elif [[ "${release}" == "oracle" ]]; then
if [[ ${os_version} -lt 8 ]]; then if [[ ${os_version} -lt 8 ]]; then
@@ -91,12 +87,12 @@ else
echo "- Parch Linux" echo "- Parch Linux"
echo "- Manjaro" echo "- Manjaro"
echo "- Armbian" echo "- Armbian"
echo "- AlmaLinux 8.0+" echo "- AlmaLinux 9+"
echo "- Rocky Linux 8+" echo "- Rocky Linux 9+"
echo "- Oracle Linux 8+" echo "- Oracle Linux 8+"
echo "- OpenSUSE Tumbleweed" echo "- OpenSUSE Tumbleweed"
echo "- Amazon Linux 2023"
exit 1 exit 1
fi fi
# Declare Variables # Declare Variables
@@ -478,7 +474,7 @@ enable_bbr() {
centos | almalinux | rocky | oracle) centos | almalinux | rocky | oracle)
yum -y update && yum -y install ca-certificates yum -y update && yum -y install ca-certificates
;; ;;
fedora | amzn) fedora)
dnf -y update && dnf -y install ca-certificates dnf -y update && dnf -y install ca-certificates
;; ;;
arch | manjaro | parch) arch | manjaro | parch)
@@ -818,7 +814,7 @@ ssl_cert_issue() {
centos | almalinux | rocky | oracle) centos | almalinux | rocky | oracle)
yum -y update && yum -y install socat yum -y update && yum -y install socat
;; ;;
fedora | amzn) fedora)
dnf -y update && dnf -y install socat dnf -y update && dnf -y install socat
;; ;;
arch | manjaro | parch) arch | manjaro | parch)
@@ -982,6 +978,33 @@ ssl_cert_issue_CF() {
fi fi
} }
warp_cloudflare() {
echo -e "${green}\t1.${plain} Install WARP socks5 proxy"
echo -e "${green}\t2.${plain} Account Type (free, plus, team)"
echo -e "${green}\t3.${plain} Turn on/off WireProxy"
echo -e "${green}\t4.${plain} Uninstall WARP"
echo -e "${green}\t0.${plain} Back to Main Menu"
read -p "Choose an option: " choice
case "$choice" in
0)
show_menu
;;
1)
bash <(curl -sSL https://raw.githubusercontent.com/hamid-gh98/x-ui-scripts/main/install_warp_proxy.sh)
;;
2)
warp a
;;
3)
warp y
;;
4)
warp u
;;
*) echo "Invalid choice" ;;
esac
}
run_speedtest() { run_speedtest() {
# Check if Speedtest is already installed # Check if Speedtest is already installed
if ! command -v speedtest &>/dev/null; then if ! command -v speedtest &>/dev/null; then
@@ -1169,7 +1192,7 @@ install_iplimit() {
yum update -y && yum install epel-release -y yum update -y && yum install epel-release -y
yum -y install fail2ban yum -y install fail2ban
;; ;;
fedora | amzn) fedora)
dnf -y update && dnf -y install fail2ban dnf -y update && dnf -y install fail2ban
;; ;;
arch | manjaro | parch) arch | manjaro | parch)
@@ -1250,7 +1273,7 @@ remove_iplimit() {
yum remove fail2ban -y yum remove fail2ban -y
yum autoremove -y yum autoremove -y
;; ;;
fedora | amzn) fedora)
dnf remove fail2ban -y dnf remove fail2ban -y
dnf autoremove -y dnf autoremove -y
;; ;;
@@ -1326,14 +1349,15 @@ show_menu() {
${green}18.${plain} SSL Certificate Management ${green}18.${plain} SSL Certificate Management
${green}19.${plain} Cloudflare SSL Certificate ${green}19.${plain} Cloudflare SSL Certificate
${green}20.${plain} IP Limit Management ${green}20.${plain} IP Limit Management
${green}21.${plain} Firewall Management ${green}21.${plain} WARP Management
${green}22.${plain} Firewall Management
———————————————— ————————————————
${green}22.${plain} Enable BBR ${green}23.${plain} Enable BBR
${green}23.${plain} Update Geo Files ${green}24.${plain} Update Geo Files
${green}24.${plain} Speedtest by Ookla ${green}25.${plain} Speedtest by Ookla
" "
show_status show_status
echo && read -p "Please enter your selection [0-24]: " num echo && read -p "Please enter your selection [0-25]: " num
case "${num}" in case "${num}" in
0) 0)
@@ -1400,19 +1424,22 @@ show_menu() {
iplimit_main iplimit_main
;; ;;
21) 21)
firewall_menu warp_cloudflare
;; ;;
22) 22)
bbr_menu firewall_menu
;; ;;
23) 23)
update_geo bbr_menu
;; ;;
24) 24)
update_geo
;;
25)
run_speedtest run_speedtest
;; ;;
*) *)
LOGE "Please enter the correct number [0-24]" LOGE "Please enter the correct number [0-25]"
;; ;;
esac esac
} }

View File

@@ -14,7 +14,6 @@ type InboundConfig struct {
StreamSettings json_util.RawMessage `json:"streamSettings"` StreamSettings json_util.RawMessage `json:"streamSettings"`
Tag string `json:"tag"` Tag string `json:"tag"`
Sniffing json_util.RawMessage `json:"sniffing"` Sniffing json_util.RawMessage `json:"sniffing"`
Allocate json_util.RawMessage `json:"allocate"`
} }
func (c *InboundConfig) Equals(other *InboundConfig) bool { func (c *InboundConfig) Equals(other *InboundConfig) bool {
@@ -39,8 +38,5 @@ func (c *InboundConfig) Equals(other *InboundConfig) bool {
if !bytes.Equal(c.Sniffing, other.Sniffing) { if !bytes.Equal(c.Sniffing, other.Sniffing) {
return false return false
} }
if !bytes.Equal(c.Allocate, other.Allocate) {
return false
}
return true return true
} }