Add zapret2 section action support
This commit is contained in:
@@ -2,6 +2,13 @@ name: Differential ShellCheck
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
base:
|
||||||
|
description: Base revision for manual differential scan
|
||||||
|
required: true
|
||||||
|
head:
|
||||||
|
description: Head revision for manual differential scan
|
||||||
|
required: true
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@@ -27,6 +34,7 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
shellcheck:
|
shellcheck:
|
||||||
name: Differential ShellCheck
|
name: Differential ShellCheck
|
||||||
|
if: ${{ github.event_name != 'push' || github.event.forced != true }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -42,6 +50,9 @@ jobs:
|
|||||||
- name: Differential ShellCheck
|
- name: Differential ShellCheck
|
||||||
uses: redhat-plumbers-in-action/differential-shellcheck@v5.5.5
|
uses: redhat-plumbers-in-action/differential-shellcheck@v5.5.5
|
||||||
with:
|
with:
|
||||||
|
triggering-event: ${{ github.event_name == 'workflow_dispatch' && 'manual' || github.event_name }}
|
||||||
|
base: ${{ github.event.inputs.base }}
|
||||||
|
head: ${{ github.event.inputs.head }}
|
||||||
severity: error
|
severity: error
|
||||||
include-path: |
|
include-path: |
|
||||||
podkop/files/usr/bin/podkop
|
podkop/files/usr/bin/podkop
|
||||||
|
|||||||
@@ -32,14 +32,13 @@ sh <(wget -O - https://raw.githubusercontent.com/ushan0v/podkop-plus/main/instal
|
|||||||
### Что нового в этом форке
|
### Что нового в этом форке
|
||||||
|
|
||||||
- Добавлена поддержка подписок.
|
- Добавлена поддержка подписок.
|
||||||
- Интеграция Zapret и ByeDPI как отдельного действия.
|
- Интеграция Zapret, Zapret2 и ByeDPI как отдельных действий секции.
|
||||||
- Поддержка sing-box extended и транспорта XHTTP.
|
- Поддержка sing-box extended и транспорта XHTTP.
|
||||||
- Обновленный LuCI-интерфейс и расширенное управление секциями.
|
- Обновленный LuCI-интерфейс и расширенное управление секциями.
|
||||||
- Новые условия маршрутизации.
|
- Новые условия маршрутизации.
|
||||||
- Режим сервера с возможностю поднять собственный VPN/Proxy для подключения внешних устройств.
|
- Режим сервера с возможностю поднять собственный VPN/Proxy для подключения внешних устройств.
|
||||||
|
- Менеджер обновлений и установки компонентов.
|
||||||
- Встроенный мониторинг соединений.
|
- Встроенный мониторинг соединений.
|
||||||
- Менеджер обновлений.
|
|
||||||
- Переход на нативный для OpenWrt `ucode`
|
|
||||||
|
|
||||||
### Подписки
|
### Подписки
|
||||||
|
|
||||||
@@ -100,11 +99,11 @@ Podkop Plus позволяет поднять собственный VPN/Proxy
|
|||||||
|
|
||||||
### Интеграция Zapret
|
### Интеграция Zapret
|
||||||
|
|
||||||
Zapret доступен как действие отдельной секции. Используется [remittor/zapret-openwrt](https://github.com/remittor/zapret-openwrt/releases). Интеграция не конфликтует с отдельным полноценным пакетом zapret (`luci-app-zapret`).
|
Zapret доступен как действие отдельной секции. Используется [bol-van/zapret](https://github.com/bol-van/zapret) в OpenWrt-пакете `zapret` из релизов [remittor/zapret-openwrt](https://github.com/remittor/zapret-openwrt/releases).
|
||||||
|
|
||||||
> Вы можете найти адаптированные и проверенные стратегии обхода для Podkop Plus в специальном репозитории: [ushan0v/podkop-plus-zapret-strategies](https://github.com/ushan0v/podkop-plus-zapret-strategies).
|
> Вы можете найти адаптированные и проверенные стратегии zapret для Podkop Plus в специальном репозитории: [ushan0v/podkop-plus-zapret-strategies](https://github.com/ushan0v/podkop-plus-zapret-strategies).
|
||||||
|
|
||||||
Реализация: `sing-box` отбирает трафик секции и отправляет его в `direct` outbound с отдельным `routing_mark` -> `zapret` принимает помеченные пакеты из очереди и применяет выбранную стратегию DPI-обхода.
|
Реализация: `sing-box` отбирает трафик секции и отправляет его в `direct` outbound с отдельным `routing_mark` -> `zapret` принимает помеченные пакеты из очереди (`4000-4255`) и применяет выбранную стратегию DPI-обхода.
|
||||||
|
|
||||||
Для стратегии `zapret` намеренно запрещены:
|
Для стратегии `zapret` намеренно запрещены:
|
||||||
|
|
||||||
@@ -113,11 +112,29 @@ Zapret доступен как действие отдельной секции.
|
|||||||
- ручное управление очередью и fwmark: **`--qnum`**, **`--dpi-desync-fwmark`**;
|
- ручное управление очередью и fwmark: **`--qnum`**, **`--dpi-desync-fwmark`**;
|
||||||
- режимы, которые ломают lifecycle процесса: **`--daemon`**;
|
- режимы, которые ломают lifecycle процесса: **`--daemon`**;
|
||||||
- режимы, которые не должны быть итоговой стратегией запуска: **`--dry-run`**, **`--version`**;
|
- режимы, которые не должны быть итоговой стратегией запуска: **`--dry-run`**, **`--version`**;
|
||||||
- внешние конфиги вида **`@file`** или **`$file`**, которые обходят встроенную валидацию и управление очередями.
|
- внешние файлы аргументов вида **`@file`** или **`$file`**, которые обходят встроенную валидацию и управление очередями.
|
||||||
|
|
||||||
|
### Интеграция Zapret2
|
||||||
|
|
||||||
|
Zapret2 доступен как отдельное действие секции `zapret2`. Используется [bol-van/zapret2](https://github.com/bol-van/zapret2) в OpenWrt-пакете `zapret2` из релизов [remittor/zapret-openwrt](https://github.com/remittor/zapret-openwrt/releases).
|
||||||
|
|
||||||
|
Реализация: `sing-box` отбирает трафик секции и отправляет его в `direct` outbound с отдельным `routing_mark` -> `zapret2` принимает помеченные пакеты из очереди (`4300-4555`) и применяет выбранную стратегию DPI-обхода.
|
||||||
|
|
||||||
|
`NFQWS2 Strategy` принимает параметры `nfqws2` без `--qnum` и без базовых Lua-инициализаций: Podkop Plus добавляет очередь, `--fwmark` и стандартные `zapret2` Lua-модули самостоятельно. Свои `--blob` и `--lua-init` допустимы для расширенных стратегий.
|
||||||
|
|
||||||
|
Для стратегии `zapret2` намеренно запрещены:
|
||||||
|
|
||||||
|
- шаблоны и hostlist placeholders: **`<HOSTLIST>`**, **`<HOSTLIST_NOAUTO>`**;
|
||||||
|
- hostname/IP selectors внутри самой стратегии: **`--hostlist*`**, **`--hostlist-auto*`**, **`--ipset*`**;
|
||||||
|
- ручное управление очередью и fwmark: **`--qnum`**, **`--fwmark`**, **`--dpi-desync-fwmark`**;
|
||||||
|
- режимы, несовместимые с управляемой NFQUEUE-архитектурой: **`--fuzz`**, **`--intercept=0`**;
|
||||||
|
- режимы, которые ломают lifecycle процесса: **`--daemon`**;
|
||||||
|
- режимы, которые не должны быть итоговой стратегией запуска: **`--dry-run`**, **`--version`**;
|
||||||
|
- внешние файлы аргументов вида **`@file`** или **`$file`**, которые обходят встроенную валидацию и управление очередями.
|
||||||
|
|
||||||
### Интеграция ByeDPI
|
### Интеграция ByeDPI
|
||||||
|
|
||||||
ByeDPI доступен как действие отдельной секции. Используется [DPITrickster/ByeDPI-OpenWrt](https://github.com/DPITrickster/ByeDPI-OpenWrt/releases). Процесс работает под управлением Podkop Plus.
|
ByeDPI доступен как действие отдельной секции. Используется [DPITrickster/ByeDPI-OpenWrt](https://github.com/DPITrickster/ByeDPI-OpenWrt/releases).
|
||||||
|
|
||||||
Реализация: `sing-box` отбирает трафик секции и отправляет его в локальный SOCKS5 outbound -> `ciadpi` принимает соединение на `127.0.0.1:1080+` и применяет выбранную стратегию DPI-обхода.
|
Реализация: `sing-box` отбирает трафик секции и отправляет его в локальный SOCKS5 outbound -> `ciadpi` принимает соединение на `127.0.0.1:1080+` и применяет выбранную стратегию DPI-обхода.
|
||||||
|
|
||||||
|
|||||||
+578
-327
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP PLUS\n"
|
"Project-Id-Version: PODKOP PLUS\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-06-02 17:11+0300\n"
|
"POT-Creation-Date: 2026-06-02 18:22+0300\n"
|
||||||
"PO-Revision-Date: 2026-06-02 17:11+0300\n"
|
"PO-Revision-Date: 2026-06-02 18:22+0300\n"
|
||||||
"Last-Translator: ushan0v\n"
|
"Last-Translator: ushan0v\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@@ -299,6 +299,9 @@ msgstr "Отключить QUIC"
|
|||||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||||
msgstr "Отключить QUIC протокол для улучшения совместимости или исправления видео стриминга"
|
msgstr "Отключить QUIC протокол для улучшения совместимости или исправления видео стриминга"
|
||||||
|
|
||||||
|
msgid "Disabling interception is incompatible with action=zapret2 because Podkop Plus sends matched traffic through NFQUEUE."
|
||||||
|
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Podkop Plus отправляет совпавший трафик через NFQUEUE."
|
||||||
|
|
||||||
msgid "DNS on router"
|
msgid "DNS on router"
|
||||||
msgstr "DNS на роутере"
|
msgstr "DNS на роутере"
|
||||||
|
|
||||||
@@ -443,6 +446,9 @@ msgstr "Открыть эту секцию как локальный HTTP+SOCKS
|
|||||||
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
||||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Podkop Plus."
|
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Podkop Plus."
|
||||||
|
|
||||||
|
msgid "External nfqws2 config files bypass Podkop Plus queue management and explicit validation."
|
||||||
|
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Podkop Plus."
|
||||||
|
|
||||||
msgid "Failed to close connection"
|
msgid "Failed to close connection"
|
||||||
msgstr "Не удалось закрыть подключение"
|
msgstr "Не удалось закрыть подключение"
|
||||||
|
|
||||||
@@ -485,6 +491,9 @@ msgstr "Proxy protocol для фронтинга"
|
|||||||
msgid "Fully Routed IPs"
|
msgid "Fully Routed IPs"
|
||||||
msgstr "Полностью маршрутизированные IP-адреса"
|
msgstr "Полностью маршрутизированные IP-адреса"
|
||||||
|
|
||||||
|
msgid "Fuzzing is not supported here because Podkop Plus needs deterministic runtime validation."
|
||||||
|
msgstr "Fuzzing здесь не поддерживается, потому что Podkop Plus нужна предсказуемая runtime-валидация."
|
||||||
|
|
||||||
msgid "Generated inbound"
|
msgid "Generated inbound"
|
||||||
msgstr "Созданный inbound"
|
msgstr "Созданный inbound"
|
||||||
|
|
||||||
@@ -608,6 +617,9 @@ msgstr "Неверный IP-адрес"
|
|||||||
msgid "Invalid JSON format"
|
msgid "Invalid JSON format"
|
||||||
msgstr "Неверный формат JSON"
|
msgstr "Неверный формат JSON"
|
||||||
|
|
||||||
|
msgid "Invalid NFQWS2 strategy"
|
||||||
|
msgstr "Некорректная стратегия NFQWS2"
|
||||||
|
|
||||||
msgid "Invalid path format. Path must start with \"/\" and contain valid characters"
|
msgid "Invalid path format. Path must start with \"/\" and contain valid characters"
|
||||||
msgstr "Неверный формат пути. Путь должен начинаться с \"/\" и содержать допустимые символы"
|
msgstr "Неверный формат пути. Путь должен начинаться с \"/\" и содержать допустимые символы"
|
||||||
|
|
||||||
@@ -803,6 +815,12 @@ msgstr "Стратегия NFQWS"
|
|||||||
msgid "NFQWS strategy cannot be empty"
|
msgid "NFQWS strategy cannot be empty"
|
||||||
msgstr "Стратегия NFQWS не может быть пустой"
|
msgstr "Стратегия NFQWS не может быть пустой"
|
||||||
|
|
||||||
|
msgid "NFQWS2 Strategy"
|
||||||
|
msgstr "Стратегия NFQWS2"
|
||||||
|
|
||||||
|
msgid "NFQWS2 strategy cannot be empty"
|
||||||
|
msgstr "Стратегия NFQWS2 не может быть пустой"
|
||||||
|
|
||||||
msgid "No active connections"
|
msgid "No active connections"
|
||||||
msgstr "Нет активных подключений"
|
msgstr "Нет активных подключений"
|
||||||
|
|
||||||
@@ -827,6 +845,9 @@ msgstr "Нет правил, использующих ByeDPI"
|
|||||||
msgid "No rules use Zapret"
|
msgid "No rules use Zapret"
|
||||||
msgstr "Нет правил, использующих Zapret"
|
msgstr "Нет правил, использующих Zapret"
|
||||||
|
|
||||||
|
msgid "No rules use Zapret2"
|
||||||
|
msgstr "Нет правил, использующих Zapret2"
|
||||||
|
|
||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "Нет"
|
msgstr "Нет"
|
||||||
|
|
||||||
@@ -884,6 +905,9 @@ msgstr "Параметр \"%s\" содержит некорректное зна
|
|||||||
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws."
|
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws."
|
||||||
msgstr "Необязательное значение здесь нужно передавать только через '='; отдельный токен nfqws проигнорирует."
|
msgstr "Необязательное значение здесь нужно передавать только через '='; отдельный токен nfqws проигнорирует."
|
||||||
|
|
||||||
|
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws2."
|
||||||
|
msgstr "Необязательные значения здесь должны задаваться через '='; отдельный токен будет проигнорирован nfqws2."
|
||||||
|
|
||||||
msgid "Outbound JSON"
|
msgid "Outbound JSON"
|
||||||
msgstr "JSON outbound"
|
msgstr "JSON outbound"
|
||||||
|
|
||||||
@@ -938,6 +962,9 @@ msgstr "Podkop Plus сам управляет жизненным циклом ci
|
|||||||
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||||
msgstr "Podkop Plus сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
msgstr "Podkop Plus сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||||
|
|
||||||
|
msgid "Podkop Plus manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||||
|
msgstr "Podkop Plus сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||||
|
|
||||||
msgid "Podkop Plus rules"
|
msgid "Podkop Plus rules"
|
||||||
msgstr "Правила Podkop Plus"
|
msgstr "Правила Podkop Plus"
|
||||||
|
|
||||||
@@ -968,6 +995,15 @@ msgstr "NFQWS Podkop Plus не запущен"
|
|||||||
msgid "Podkop Plus-managed nfqws runtime is ready"
|
msgid "Podkop Plus-managed nfqws runtime is ready"
|
||||||
msgstr "NFQWS Podkop Plus готов"
|
msgstr "NFQWS Podkop Plus готов"
|
||||||
|
|
||||||
|
msgid "Podkop Plus-managed nfqws2 runtime is not ready"
|
||||||
|
msgstr "NFQWS2 Podkop Plus не готов"
|
||||||
|
|
||||||
|
msgid "Podkop Plus-managed nfqws2 runtime is not running"
|
||||||
|
msgstr "NFQWS2 Podkop Plus не запущен"
|
||||||
|
|
||||||
|
msgid "Podkop Plus-managed nfqws2 runtime is ready"
|
||||||
|
msgstr "NFQWS2 Podkop Plus готов"
|
||||||
|
|
||||||
msgid "Port cannot be empty"
|
msgid "Port cannot be empty"
|
||||||
msgstr "Порт не может быть пустым"
|
msgstr "Порт не может быть пустым"
|
||||||
|
|
||||||
@@ -1052,9 +1088,15 @@ msgstr "Определять страны серверов через country.is
|
|||||||
msgid "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
msgid "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
msgstr "Выбор ресурсов по hostname внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
msgstr "Выбор ресурсов по hostname внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
||||||
|
|
||||||
|
msgid "Resource selection by hostname inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
|
msgstr "Выбор ресурсов по hostname внутри nfqws2 здесь не поддерживается; sing-box выбирает ресурсы до NFQUEUE."
|
||||||
|
|
||||||
msgid "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
msgid "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
||||||
|
|
||||||
|
msgid "Resource selection by IP or CIDR inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
|
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws2 здесь не поддерживается; sing-box выбирает ресурсы до NFQUEUE."
|
||||||
|
|
||||||
msgid "Restart Podkop Plus"
|
msgid "Restart Podkop Plus"
|
||||||
msgstr "Перезапустить Podkop Plus"
|
msgstr "Перезапустить Podkop Plus"
|
||||||
|
|
||||||
@@ -1277,6 +1319,18 @@ msgstr "Отдельная служба Zapret активна"
|
|||||||
msgid "Standalone Zapret service is inactive"
|
msgid "Standalone Zapret service is inactive"
|
||||||
msgstr "Отдельная служба Zapret неактивна"
|
msgstr "Отдельная служба Zapret неактивна"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 autostart is enabled"
|
||||||
|
msgstr "Автозапуск отдельной службы Zapret2 включён"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 is active together with Podkop Plus Zapret2 rules"
|
||||||
|
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Podkop Plus"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 service is active"
|
||||||
|
msgstr "Отдельная служба Zapret2 активна"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 service is inactive"
|
||||||
|
msgstr "Отдельная служба Zapret2 неактивна"
|
||||||
|
|
||||||
msgid "Start Podkop Plus"
|
msgid "Start Podkop Plus"
|
||||||
msgstr "Запустить Podkop Plus"
|
msgstr "Запустить Podkop Plus"
|
||||||
|
|
||||||
@@ -1346,6 +1400,9 @@ msgstr "Есть правила, использующие ByeDPI"
|
|||||||
msgid "There are rules using Zapret"
|
msgid "There are rules using Zapret"
|
||||||
msgstr "Есть правила использующие Zapret"
|
msgstr "Есть правила использующие Zapret"
|
||||||
|
|
||||||
|
msgid "There are rules using Zapret2"
|
||||||
|
msgstr "Есть правила, использующие Zapret2"
|
||||||
|
|
||||||
msgid "This field is required"
|
msgid "This field is required"
|
||||||
msgstr "Заполните это поле"
|
msgstr "Заполните это поле"
|
||||||
|
|
||||||
@@ -1358,6 +1415,12 @@ msgstr "Это поле должно запускать рабочую стра
|
|||||||
msgid "This field must start a working nfqws strategy; --version exits immediately and is not allowed here."
|
msgid "This field must start a working nfqws strategy; --version exits immediately and is not allowed here."
|
||||||
msgstr "Это поле должно запускать рабочую стратегию nfqws; --version сразу завершает процесс и здесь запрещён."
|
msgstr "Это поле должно запускать рабочую стратегию nfqws; --version сразу завершает процесс и здесь запрещён."
|
||||||
|
|
||||||
|
msgid "This field must start a working nfqws2 strategy; --dry-run exits immediately and is not allowed here."
|
||||||
|
msgstr "Это поле должно запускать рабочую стратегию nfqws2; --dry-run сразу завершает работу и здесь запрещён."
|
||||||
|
|
||||||
|
msgid "This field must start a working nfqws2 strategy; --version exits immediately and is not allowed here."
|
||||||
|
msgstr "Это поле должно запускать рабочую стратегию nfqws2; --version сразу завершает работу и здесь запрещён."
|
||||||
|
|
||||||
msgid "This flag does not accept a value."
|
msgid "This flag does not accept a value."
|
||||||
msgstr "Этот флаг не принимает значение."
|
msgstr "Этот флаг не принимает значение."
|
||||||
|
|
||||||
@@ -1418,6 +1481,9 @@ msgstr "Не удалось проверить стратегию ByeDPI чер
|
|||||||
msgid "Unable to validate the NFQWS strategy through the backend parser."
|
msgid "Unable to validate the NFQWS strategy through the backend parser."
|
||||||
msgstr "Не удалось проверить стратегию NFQWS через backend-парсер."
|
msgstr "Не удалось проверить стратегию NFQWS через backend-парсер."
|
||||||
|
|
||||||
|
msgid "Unable to validate the NFQWS2 strategy through the backend parser."
|
||||||
|
msgstr "Не удалось проверить стратегию NFQWS2 через backend-парсер."
|
||||||
|
|
||||||
msgid "Unexpected ByeDPI strategy argument: %s"
|
msgid "Unexpected ByeDPI strategy argument: %s"
|
||||||
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
||||||
|
|
||||||
@@ -1427,6 +1493,9 @@ msgstr "Обнаружен лишний ciadpi Podkop Plus"
|
|||||||
msgid "Unexpected Podkop Plus-managed nfqws runtime is running"
|
msgid "Unexpected Podkop Plus-managed nfqws runtime is running"
|
||||||
msgstr "Обнаружен лишний NFQWS Podkop Plus"
|
msgstr "Обнаружен лишний NFQWS Podkop Plus"
|
||||||
|
|
||||||
|
msgid "Unexpected Podkop Plus-managed nfqws2 runtime is running"
|
||||||
|
msgstr "Обнаружен лишний NFQWS2 Podkop Plus"
|
||||||
|
|
||||||
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
||||||
msgstr "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
msgstr "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
||||||
|
|
||||||
@@ -1448,6 +1517,9 @@ msgstr "Неизвестная ошибка"
|
|||||||
msgid "Unknown NFQWS flag."
|
msgid "Unknown NFQWS flag."
|
||||||
msgstr "Неизвестный флаг NFQWS."
|
msgstr "Неизвестный флаг NFQWS."
|
||||||
|
|
||||||
|
msgid "Unknown NFQWS2 flag."
|
||||||
|
msgstr "Неизвестный флаг NFQWS2."
|
||||||
|
|
||||||
msgid "Unsupported security mode for this protocol"
|
msgid "Unsupported security mode for this protocol"
|
||||||
msgstr "Этот протокол не поддерживает выбранный режим защиты"
|
msgstr "Этот протокол не поддерживает выбранный режим защиты"
|
||||||
|
|
||||||
@@ -1591,3 +1663,30 @@ msgstr "Бинарник провайдера Zapret доступен"
|
|||||||
|
|
||||||
msgid "Zapret provider binary is not available"
|
msgid "Zapret provider binary is not available"
|
||||||
msgstr "Бинарник провайдера Zapret недоступен"
|
msgstr "Бинарник провайдера Zapret недоступен"
|
||||||
|
|
||||||
|
msgid "Zapret2 hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS2 strategies."
|
||||||
|
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Podkop Plus не разворачивает их для per-rule стратегий NFQWS2."
|
||||||
|
|
||||||
|
msgid "Zapret2 package is installed"
|
||||||
|
msgstr "Пакет Zapret2 установлен"
|
||||||
|
|
||||||
|
msgid "Zapret2 package is not installed"
|
||||||
|
msgstr "Пакет Zapret2 не установлен"
|
||||||
|
|
||||||
|
msgid "Zapret2 provider binary is available"
|
||||||
|
msgstr "Бинарник провайдера Zapret2 доступен"
|
||||||
|
|
||||||
|
msgid "Zapret2 provider binary is not available"
|
||||||
|
msgstr "Бинарник провайдера Zapret2 недоступен"
|
||||||
|
|
||||||
|
msgid "Zapret2 route rules are configured"
|
||||||
|
msgstr "Правила маршрутизации Zapret2 настроены"
|
||||||
|
|
||||||
|
msgid "Zapret2 route rules are not configured"
|
||||||
|
msgstr "Правила маршрутизации Zapret2 не настроены"
|
||||||
|
|
||||||
|
msgid "Zapret2 sing-box outbound is configured"
|
||||||
|
msgstr "sing-box outbound для Zapret2 настроен"
|
||||||
|
|
||||||
|
msgid "Zapret2 sing-box outbound is not configured"
|
||||||
|
msgstr "sing-box outbound для Zapret2 не настроен"
|
||||||
|
|||||||
@@ -134,6 +134,10 @@ export const PodkopShellMethods = {
|
|||||||
callBaseMethod<Podkop.ZapretCheckResult>(
|
callBaseMethod<Podkop.ZapretCheckResult>(
|
||||||
Podkop.AvailableMethods.CHECK_ZAPRET_RUNTIME,
|
Podkop.AvailableMethods.CHECK_ZAPRET_RUNTIME,
|
||||||
),
|
),
|
||||||
|
checkZapret2Runtime: async () =>
|
||||||
|
callBaseMethod<Podkop.Zapret2CheckResult>(
|
||||||
|
Podkop.AvailableMethods.CHECK_ZAPRET2_RUNTIME,
|
||||||
|
),
|
||||||
checkByedpiRuntime: async () =>
|
checkByedpiRuntime: async () =>
|
||||||
callBaseMethod<Podkop.ByedpiCheckResult>(
|
callBaseMethod<Podkop.ByedpiCheckResult>(
|
||||||
Podkop.AvailableMethods.CHECK_BYEDPI_RUNTIME,
|
Podkop.AvailableMethods.CHECK_BYEDPI_RUNTIME,
|
||||||
@@ -180,6 +184,10 @@ export const PodkopShellMethods = {
|
|||||||
callBaseMethod<Podkop.GetZapretStatus>(
|
callBaseMethod<Podkop.GetZapretStatus>(
|
||||||
Podkop.AvailableMethods.GET_ZAPRET_STATUS,
|
Podkop.AvailableMethods.GET_ZAPRET_STATUS,
|
||||||
),
|
),
|
||||||
|
getZapret2Status: async () =>
|
||||||
|
callBaseMethod<Podkop.GetZapret2Status>(
|
||||||
|
Podkop.AvailableMethods.GET_ZAPRET2_STATUS,
|
||||||
|
),
|
||||||
getByedpiStatus: async () =>
|
getByedpiStatus: async () =>
|
||||||
callBaseMethod<Podkop.GetByedpiStatus>(
|
callBaseMethod<Podkop.GetByedpiStatus>(
|
||||||
Podkop.AvailableMethods.GET_BYEDPI_STATUS,
|
Podkop.AvailableMethods.GET_BYEDPI_STATUS,
|
||||||
|
|||||||
@@ -196,6 +196,8 @@ export interface StoreType {
|
|||||||
sing_box_extended: number;
|
sing_box_extended: number;
|
||||||
zapret_version: string;
|
zapret_version: string;
|
||||||
zapret_installed: number;
|
zapret_installed: number;
|
||||||
|
zapret2_version: string;
|
||||||
|
zapret2_installed: number;
|
||||||
byedpi_version: string;
|
byedpi_version: string;
|
||||||
byedpi_installed: number;
|
byedpi_installed: number;
|
||||||
server_inbounds_enabled_count: number;
|
server_inbounds_enabled_count: number;
|
||||||
@@ -212,6 +214,9 @@ export interface StoreType {
|
|||||||
zapretCheck: { loading: boolean };
|
zapretCheck: { loading: boolean };
|
||||||
zapretInstall: { loading: boolean };
|
zapretInstall: { loading: boolean };
|
||||||
zapretRemove: { loading: boolean };
|
zapretRemove: { loading: boolean };
|
||||||
|
zapret2Check: { loading: boolean };
|
||||||
|
zapret2Install: { loading: boolean };
|
||||||
|
zapret2Remove: { loading: boolean };
|
||||||
byedpiCheck: { loading: boolean };
|
byedpiCheck: { loading: boolean };
|
||||||
byedpiInstall: { loading: boolean };
|
byedpiInstall: { loading: boolean };
|
||||||
byedpiRemove: { loading: boolean };
|
byedpiRemove: { loading: boolean };
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ const UNKNOWN_SYSTEM_INFO: StoreType['diagnosticsSystemInfo'] = {
|
|||||||
sing_box_extended: 0,
|
sing_box_extended: 0,
|
||||||
zapret_version: _('unknown'),
|
zapret_version: _('unknown'),
|
||||||
zapret_installed: 0,
|
zapret_installed: 0,
|
||||||
|
zapret2_version: _('unknown'),
|
||||||
|
zapret2_installed: 0,
|
||||||
byedpi_version: _('unknown'),
|
byedpi_version: _('unknown'),
|
||||||
byedpi_installed: 0,
|
byedpi_installed: 0,
|
||||||
server_inbounds_enabled_count: -1,
|
server_inbounds_enabled_count: -1,
|
||||||
@@ -94,6 +96,7 @@ export async function ensureSystemInfo({
|
|||||||
loaded: false,
|
loaded: false,
|
||||||
providerInfoLoaded: latestSystemInfo.providerInfoLoaded,
|
providerInfoLoaded: latestSystemInfo.providerInfoLoaded,
|
||||||
zapret_installed: latestSystemInfo.zapret_installed,
|
zapret_installed: latestSystemInfo.zapret_installed,
|
||||||
|
zapret2_installed: latestSystemInfo.zapret2_installed,
|
||||||
byedpi_installed: latestSystemInfo.byedpi_installed,
|
byedpi_installed: latestSystemInfo.byedpi_installed,
|
||||||
server_inbounds_enabled_count:
|
server_inbounds_enabled_count:
|
||||||
latestSystemInfo.server_inbounds_enabled_count,
|
latestSystemInfo.server_inbounds_enabled_count,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export enum DIAGNOSTICS_CHECKS {
|
|||||||
SINGBOX = 'SINGBOX',
|
SINGBOX = 'SINGBOX',
|
||||||
NFT = 'NFT',
|
NFT = 'NFT',
|
||||||
ZAPRET = 'ZAPRET',
|
ZAPRET = 'ZAPRET',
|
||||||
|
ZAPRET2 = 'ZAPRET2',
|
||||||
BYEDPI = 'BYEDPI',
|
BYEDPI = 'BYEDPI',
|
||||||
FAKEIP = 'FAKEIP',
|
FAKEIP = 'FAKEIP',
|
||||||
OUTBOUNDS = 'OUTBOUNDS',
|
OUTBOUNDS = 'OUTBOUNDS',
|
||||||
@@ -36,17 +37,22 @@ export const DIAGNOSTICS_CHECKS_MAP: Record<
|
|||||||
code: DIAGNOSTICS_CHECKS.ZAPRET,
|
code: DIAGNOSTICS_CHECKS.ZAPRET,
|
||||||
},
|
},
|
||||||
[DIAGNOSTICS_CHECKS.BYEDPI]: {
|
[DIAGNOSTICS_CHECKS.BYEDPI]: {
|
||||||
order: 6,
|
order: 7,
|
||||||
title: getCheckTitle('ByeDPI'),
|
title: getCheckTitle('ByeDPI'),
|
||||||
code: DIAGNOSTICS_CHECKS.BYEDPI,
|
code: DIAGNOSTICS_CHECKS.BYEDPI,
|
||||||
},
|
},
|
||||||
|
[DIAGNOSTICS_CHECKS.ZAPRET2]: {
|
||||||
|
order: 6,
|
||||||
|
title: getCheckTitle('Zapret2'),
|
||||||
|
code: DIAGNOSTICS_CHECKS.ZAPRET2,
|
||||||
|
},
|
||||||
[DIAGNOSTICS_CHECKS.OUTBOUNDS]: {
|
[DIAGNOSTICS_CHECKS.OUTBOUNDS]: {
|
||||||
order: 7,
|
order: 8,
|
||||||
title: getCheckTitle('Outbounds'),
|
title: getCheckTitle('Outbounds'),
|
||||||
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
|
code: DIAGNOSTICS_CHECKS.OUTBOUNDS,
|
||||||
},
|
},
|
||||||
[DIAGNOSTICS_CHECKS.FAKEIP]: {
|
[DIAGNOSTICS_CHECKS.FAKEIP]: {
|
||||||
order: 8,
|
order: 9,
|
||||||
title: getCheckTitle('FakeIP'),
|
title: getCheckTitle('FakeIP'),
|
||||||
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
code: DIAGNOSTICS_CHECKS.FAKEIP,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
|
||||||
|
import { PodkopShellMethods } from '../../../methods';
|
||||||
|
import { updateCheckStore } from './updateCheckStore';
|
||||||
|
import { IDiagnosticsChecksItem } from '../../../services';
|
||||||
|
|
||||||
|
type CheckState = 'success' | 'warning' | 'error';
|
||||||
|
|
||||||
|
export async function runZapret2Check() {
|
||||||
|
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.ZAPRET2;
|
||||||
|
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _('Checking, please wait'),
|
||||||
|
state: 'loading',
|
||||||
|
items: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const zapret2Status = await PodkopShellMethods.getZapret2Status();
|
||||||
|
|
||||||
|
if (!zapret2Status.success) {
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _('Cannot receive checks result'),
|
||||||
|
state: 'error',
|
||||||
|
items: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
throw new Error('Zapret2 checks failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = zapret2Status.data;
|
||||||
|
const providerAvailable = Boolean(data.provider_available ?? data.installed);
|
||||||
|
const packageInstalled = Boolean(data.package_installed);
|
||||||
|
const hasZapret2Rules = Number(data.enabled_rule_count || 0) > 0;
|
||||||
|
const ready = Boolean(data.ready);
|
||||||
|
const queueOverlap = Boolean(data.queue_overlap);
|
||||||
|
const expectedProcesses = Number(data.expected_process_count || 0);
|
||||||
|
const runningProcesses = Number(data.running_process_count || 0);
|
||||||
|
const supervisorProcesses = Number(data.supervisor_process_count || 0);
|
||||||
|
const podkopRuntimeReady =
|
||||||
|
!hasZapret2Rules ||
|
||||||
|
(runningProcesses === expectedProcesses &&
|
||||||
|
supervisorProcesses === expectedProcesses);
|
||||||
|
const unexpectedRuntime =
|
||||||
|
!hasZapret2Rules && (runningProcesses > 0 || supervisorProcesses > 0);
|
||||||
|
const outboundsConfigured = Boolean(data.outbounds_configured);
|
||||||
|
const routesConfigured = Boolean(data.routes_configured);
|
||||||
|
const standaloneServiceEnabled = Boolean(data.standalone_service_enabled);
|
||||||
|
const standaloneServiceRunning = Boolean(data.standalone_service_running);
|
||||||
|
const standaloneConflict = hasZapret2Rules && standaloneServiceRunning;
|
||||||
|
const standaloneAutostartRisk =
|
||||||
|
hasZapret2Rules && standaloneServiceEnabled && !standaloneServiceRunning;
|
||||||
|
|
||||||
|
let state: CheckState = 'success';
|
||||||
|
let description = _('Checks passed');
|
||||||
|
|
||||||
|
if (hasZapret2Rules && !providerAvailable) {
|
||||||
|
state = 'error';
|
||||||
|
description = _('Checks failed');
|
||||||
|
} else if (hasZapret2Rules && !ready) {
|
||||||
|
state = 'error';
|
||||||
|
description = _('Checks failed');
|
||||||
|
} else if (queueOverlap) {
|
||||||
|
state = 'error';
|
||||||
|
description = _('Checks failed');
|
||||||
|
} else if (standaloneConflict) {
|
||||||
|
state = 'error';
|
||||||
|
description = _('Checks failed');
|
||||||
|
} else if (standaloneAutostartRisk || !packageInstalled) {
|
||||||
|
state = 'warning';
|
||||||
|
description = _('Issues detected');
|
||||||
|
}
|
||||||
|
|
||||||
|
const items: Array<IDiagnosticsChecksItem> = [
|
||||||
|
{
|
||||||
|
state: providerAvailable
|
||||||
|
? 'success'
|
||||||
|
: hasZapret2Rules
|
||||||
|
? 'error'
|
||||||
|
: 'warning',
|
||||||
|
key: providerAvailable
|
||||||
|
? _('Zapret2 provider binary is available')
|
||||||
|
: _('Zapret2 provider binary is not available'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: packageInstalled
|
||||||
|
? 'success'
|
||||||
|
: hasZapret2Rules
|
||||||
|
? 'error'
|
||||||
|
: 'warning',
|
||||||
|
key: packageInstalled
|
||||||
|
? _('Zapret2 package is installed')
|
||||||
|
: _('Zapret2 package is not installed'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: hasZapret2Rules && !providerAvailable ? 'error' : 'success',
|
||||||
|
key: hasZapret2Rules
|
||||||
|
? _('There are rules using Zapret2')
|
||||||
|
: _('No rules use Zapret2'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: unexpectedRuntime || !podkopRuntimeReady ? 'error' : 'success',
|
||||||
|
key: hasZapret2Rules
|
||||||
|
? podkopRuntimeReady
|
||||||
|
? _('Podkop Plus-managed nfqws2 runtime is ready')
|
||||||
|
: _('Podkop Plus-managed nfqws2 runtime is not ready')
|
||||||
|
: unexpectedRuntime
|
||||||
|
? _('Unexpected Podkop Plus-managed nfqws2 runtime is running')
|
||||||
|
: _('Podkop Plus-managed nfqws2 runtime is not running'),
|
||||||
|
value: hasZapret2Rules ? `${runningProcesses}/${expectedProcesses}` : '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: queueOverlap ? 'error' : 'success',
|
||||||
|
key: queueOverlap
|
||||||
|
? _('NFQUEUE range overlaps with another rule')
|
||||||
|
: _('NFQUEUE range is available'),
|
||||||
|
value: `${Number(data.queue_base || 0)}-${Number(data.queue_range_end || 0)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: !hasZapret2Rules || outboundsConfigured ? 'success' : 'error',
|
||||||
|
key: outboundsConfigured
|
||||||
|
? _('Zapret2 sing-box outbound is configured')
|
||||||
|
: _('Zapret2 sing-box outbound is not configured'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: !hasZapret2Rules || routesConfigured ? 'success' : 'error',
|
||||||
|
key: routesConfigured
|
||||||
|
? _('Zapret2 route rules are configured')
|
||||||
|
: _('Zapret2 route rules are not configured'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: standaloneConflict
|
||||||
|
? 'error'
|
||||||
|
: standaloneAutostartRisk
|
||||||
|
? 'warning'
|
||||||
|
: 'success',
|
||||||
|
key: standaloneServiceRunning
|
||||||
|
? hasZapret2Rules
|
||||||
|
? _(
|
||||||
|
'Standalone Zapret2 is active together with Podkop Plus Zapret2 rules',
|
||||||
|
)
|
||||||
|
: _('Standalone Zapret2 service is active')
|
||||||
|
: standaloneAutostartRisk
|
||||||
|
? _('Standalone Zapret2 autostart is enabled')
|
||||||
|
: _('Standalone Zapret2 service is inactive'),
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
state,
|
||||||
|
items,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import { IDiagnosticsChecksStoreItem, StoreType } from '../../services';
|
|||||||
|
|
||||||
export interface DiagnosticsProviderOptions {
|
export interface DiagnosticsProviderOptions {
|
||||||
includeZapret?: boolean;
|
includeZapret?: boolean;
|
||||||
|
includeZapret2?: boolean;
|
||||||
includeByedpi?: boolean;
|
includeByedpi?: boolean;
|
||||||
includeInbounds?: boolean;
|
includeInbounds?: boolean;
|
||||||
}
|
}
|
||||||
@@ -42,6 +43,10 @@ export function getDiagnosticsChecks(
|
|||||||
checks.push(DIAGNOSTICS_CHECKS.ZAPRET);
|
checks.push(DIAGNOSTICS_CHECKS.ZAPRET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.includeZapret2) {
|
||||||
|
checks.push(DIAGNOSTICS_CHECKS.ZAPRET2);
|
||||||
|
}
|
||||||
|
|
||||||
if (options.includeByedpi) {
|
if (options.includeByedpi) {
|
||||||
checks.push(DIAGNOSTICS_CHECKS.BYEDPI);
|
checks.push(DIAGNOSTICS_CHECKS.BYEDPI);
|
||||||
}
|
}
|
||||||
@@ -79,6 +84,8 @@ export const initialDiagnosticStore: Pick<
|
|||||||
sing_box_extended: 0,
|
sing_box_extended: 0,
|
||||||
zapret_version: 'loading',
|
zapret_version: 'loading',
|
||||||
zapret_installed: 0,
|
zapret_installed: 0,
|
||||||
|
zapret2_version: 'loading',
|
||||||
|
zapret2_installed: 0,
|
||||||
byedpi_version: 'loading',
|
byedpi_version: 'loading',
|
||||||
byedpi_installed: 0,
|
byedpi_installed: 0,
|
||||||
server_inbounds_enabled_count: -1,
|
server_inbounds_enabled_count: -1,
|
||||||
@@ -123,6 +130,9 @@ export const initialDiagnosticStore: Pick<
|
|||||||
zapretCheck: { loading: false },
|
zapretCheck: { loading: false },
|
||||||
zapretInstall: { loading: false },
|
zapretInstall: { loading: false },
|
||||||
zapretRemove: { loading: false },
|
zapretRemove: { loading: false },
|
||||||
|
zapret2Check: { loading: false },
|
||||||
|
zapret2Install: { loading: false },
|
||||||
|
zapret2Remove: { loading: false },
|
||||||
byedpiCheck: { loading: false },
|
byedpiCheck: { loading: false },
|
||||||
byedpiInstall: { loading: false },
|
byedpiInstall: { loading: false },
|
||||||
byedpiRemove: { loading: false },
|
byedpiRemove: { loading: false },
|
||||||
@@ -131,6 +141,7 @@ export const initialDiagnosticStore: Pick<
|
|||||||
podkop: { status: null, latest_version: '', release_url: '' },
|
podkop: { status: null, latest_version: '', release_url: '' },
|
||||||
sing_box: { status: null, latest_version: '', release_url: '' },
|
sing_box: { status: null, latest_version: '', release_url: '' },
|
||||||
zapret: { status: null, latest_version: '', release_url: '' },
|
zapret: { status: null, latest_version: '', release_url: '' },
|
||||||
|
zapret2: { status: null, latest_version: '', release_url: '' },
|
||||||
byedpi: { status: null, latest_version: '', release_url: '' },
|
byedpi: { status: null, latest_version: '', release_url: '' },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { runInboundsCheck } from './checks/runInboundsCheck';
|
|||||||
import { runNftCheck } from './checks/runNftCheck';
|
import { runNftCheck } from './checks/runNftCheck';
|
||||||
import { runFakeIPCheck } from './checks/runFakeIPCheck';
|
import { runFakeIPCheck } from './checks/runFakeIPCheck';
|
||||||
import { runZapretCheck } from './checks/runZapretCheck';
|
import { runZapretCheck } from './checks/runZapretCheck';
|
||||||
|
import { runZapret2Check } from './checks/runZapret2Check';
|
||||||
import { runByedpiCheck } from './checks/runByedpiCheck';
|
import { runByedpiCheck } from './checks/runByedpiCheck';
|
||||||
import {
|
import {
|
||||||
DiagnosticsProviderOptions,
|
DiagnosticsProviderOptions,
|
||||||
@@ -47,11 +48,15 @@ function sleep(ms: number) {
|
|||||||
function getDiagnosticsProviderOptions(
|
function getDiagnosticsProviderOptions(
|
||||||
systemInfo: Pick<
|
systemInfo: Pick<
|
||||||
StoreType['diagnosticsSystemInfo'],
|
StoreType['diagnosticsSystemInfo'],
|
||||||
'zapret_installed' | 'byedpi_installed' | 'server_inbounds_enabled_count'
|
| 'zapret_installed'
|
||||||
|
| 'zapret2_installed'
|
||||||
|
| 'byedpi_installed'
|
||||||
|
| 'server_inbounds_enabled_count'
|
||||||
> = store.get().diagnosticsSystemInfo,
|
> = store.get().diagnosticsSystemInfo,
|
||||||
): DiagnosticsProviderOptions {
|
): DiagnosticsProviderOptions {
|
||||||
return {
|
return {
|
||||||
includeZapret: Boolean(systemInfo.zapret_installed),
|
includeZapret: Boolean(systemInfo.zapret_installed),
|
||||||
|
includeZapret2: Boolean(systemInfo.zapret2_installed),
|
||||||
includeByedpi: Boolean(systemInfo.byedpi_installed),
|
includeByedpi: Boolean(systemInfo.byedpi_installed),
|
||||||
includeInbounds: systemInfo.server_inbounds_enabled_count !== 0,
|
includeInbounds: systemInfo.server_inbounds_enabled_count !== 0,
|
||||||
};
|
};
|
||||||
@@ -220,11 +225,13 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
const requestId = ++latestProviderInfoRequestId;
|
const requestId = ++latestProviderInfoRequestId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [zapretRuntime, byedpiRuntime, inboundsConfig] = await Promise.all([
|
const [zapretRuntime, zapret2Runtime, byedpiRuntime, inboundsConfig] =
|
||||||
PodkopShellMethods.checkZapretRuntime(),
|
await Promise.all([
|
||||||
PodkopShellMethods.checkByedpiRuntime(),
|
PodkopShellMethods.checkZapretRuntime(),
|
||||||
PodkopShellMethods.checkInboundsConfig(),
|
PodkopShellMethods.checkZapret2Runtime(),
|
||||||
]);
|
PodkopShellMethods.checkByedpiRuntime(),
|
||||||
|
PodkopShellMethods.checkInboundsConfig(),
|
||||||
|
]);
|
||||||
|
|
||||||
if (requestId !== latestProviderInfoRequestId) {
|
if (requestId !== latestProviderInfoRequestId) {
|
||||||
return;
|
return;
|
||||||
@@ -237,6 +244,9 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
zapret_installed: zapretRuntime.success
|
zapret_installed: zapretRuntime.success
|
||||||
? zapretRuntime.data.zapret_installed
|
? zapretRuntime.data.zapret_installed
|
||||||
: currentSystemInfo.zapret_installed,
|
: currentSystemInfo.zapret_installed,
|
||||||
|
zapret2_installed: zapret2Runtime.success
|
||||||
|
? zapret2Runtime.data.zapret2_installed
|
||||||
|
: currentSystemInfo.zapret2_installed,
|
||||||
byedpi_installed: byedpiRuntime.success
|
byedpi_installed: byedpiRuntime.success
|
||||||
? byedpiRuntime.data.byedpi_installed
|
? byedpiRuntime.data.byedpi_installed
|
||||||
: currentSystemInfo.byedpi_installed,
|
: currentSystemInfo.byedpi_installed,
|
||||||
@@ -249,6 +259,14 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
logger.error('[DIAGNOSTIC]', 'fetchZapretRuntime failed', zapretRuntime);
|
logger.error('[DIAGNOSTIC]', 'fetchZapretRuntime failed', zapretRuntime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!zapret2Runtime.success) {
|
||||||
|
logger.error(
|
||||||
|
'[DIAGNOSTIC]',
|
||||||
|
'fetchZapret2Runtime failed',
|
||||||
|
zapret2Runtime,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!byedpiRuntime.success) {
|
if (!byedpiRuntime.success) {
|
||||||
logger.error('[DIAGNOSTIC]', 'fetchByedpiRuntime failed', byedpiRuntime);
|
logger.error('[DIAGNOSTIC]', 'fetchByedpiRuntime failed', byedpiRuntime);
|
||||||
}
|
}
|
||||||
@@ -265,6 +283,10 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
nextSystemInfo.zapret_version = 'not installed';
|
nextSystemInfo.zapret_version = 'not installed';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nextSystemInfo.zapret2_installed) {
|
||||||
|
nextSystemInfo.zapret2_version = 'not installed';
|
||||||
|
}
|
||||||
|
|
||||||
if (!nextSystemInfo.byedpi_installed) {
|
if (!nextSystemInfo.byedpi_installed) {
|
||||||
nextSystemInfo.byedpi_version = 'not installed';
|
nextSystemInfo.byedpi_version = 'not installed';
|
||||||
}
|
}
|
||||||
@@ -632,6 +654,13 @@ function renderDiagnosticSystemInfoWidget() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (diagnosticsSystemInfo.zapret2_installed) {
|
||||||
|
items.push({
|
||||||
|
key: 'Zapret2',
|
||||||
|
value: diagnosticsSystemInfo.zapret2_version,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (diagnosticsSystemInfo.byedpi_installed) {
|
if (diagnosticsSystemInfo.byedpi_installed) {
|
||||||
items.push({
|
items.push({
|
||||||
key: 'ByeDPI',
|
key: 'ByeDPI',
|
||||||
@@ -702,6 +731,7 @@ async function runChecks() {
|
|||||||
...(providerOptions.includeInbounds ? [runInboundsCheck] : []),
|
...(providerOptions.includeInbounds ? [runInboundsCheck] : []),
|
||||||
runNftCheck,
|
runNftCheck,
|
||||||
...(providerOptions.includeZapret ? [runZapretCheck] : []),
|
...(providerOptions.includeZapret ? [runZapretCheck] : []),
|
||||||
|
...(providerOptions.includeZapret2 ? [runZapret2Check] : []),
|
||||||
...(providerOptions.includeByedpi ? [runByedpiCheck] : []),
|
...(providerOptions.includeByedpi ? [runByedpiCheck] : []),
|
||||||
runSectionsCheck,
|
runSectionsCheck,
|
||||||
runFakeIPCheck,
|
runFakeIPCheck,
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import { DIAGNOSTICS_CHECKS } from '../checks/contstants';
|
||||||
|
import { getDiagnosticsChecks } from '../diagnostic.store';
|
||||||
|
|
||||||
|
describe('diagnostic store provider checks', () => {
|
||||||
|
it('adds Zapret2 as a separate provider check between Zapret and ByeDPI', () => {
|
||||||
|
const checks = getDiagnosticsChecks('Pending', {
|
||||||
|
includeZapret: true,
|
||||||
|
includeZapret2: true,
|
||||||
|
includeByedpi: true,
|
||||||
|
includeInbounds: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(checks.map((check) => check.code)).toEqual([
|
||||||
|
DIAGNOSTICS_CHECKS.DNS,
|
||||||
|
DIAGNOSTICS_CHECKS.SINGBOX,
|
||||||
|
DIAGNOSTICS_CHECKS.NFT,
|
||||||
|
DIAGNOSTICS_CHECKS.ZAPRET,
|
||||||
|
DIAGNOSTICS_CHECKS.ZAPRET2,
|
||||||
|
DIAGNOSTICS_CHECKS.BYEDPI,
|
||||||
|
DIAGNOSTICS_CHECKS.OUTBOUNDS,
|
||||||
|
DIAGNOSTICS_CHECKS.FAKEIP,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('keeps Zapret2 hidden when the provider is not available', () => {
|
||||||
|
const checks = getDiagnosticsChecks('Pending', {
|
||||||
|
includeZapret: true,
|
||||||
|
includeZapret2: false,
|
||||||
|
includeByedpi: true,
|
||||||
|
includeInbounds: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(checks.map((check) => check.code)).not.toContain(
|
||||||
|
DIAGNOSTICS_CHECKS.ZAPRET2,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -14,8 +14,7 @@ import { ensureSystemInfo } from '../../services/systemInfo.service';
|
|||||||
import { Podkop } from '../../types';
|
import { Podkop } from '../../types';
|
||||||
|
|
||||||
type UpdatesActionKey = keyof StoreType['updatesActions'];
|
type UpdatesActionKey = keyof StoreType['updatesActions'];
|
||||||
type UpdateStatus =
|
type UpdateStatus = StoreType['updatesChecks'][Podkop.ComponentName]['status'];
|
||||||
StoreType['updatesChecks'][Podkop.ComponentName]['status'];
|
|
||||||
|
|
||||||
interface ComponentActionButton {
|
interface ComponentActionButton {
|
||||||
key: UpdatesActionKey;
|
key: UpdatesActionKey;
|
||||||
@@ -138,7 +137,9 @@ function getExpectedLatestVersionForAction(button: ComponentActionButton) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return store.get().updatesChecks[button.component].latest_version || undefined;
|
return (
|
||||||
|
store.get().updatesChecks[button.component].latest_version || undefined
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCheckToastMessage(status: UpdateStatus) {
|
function getCheckToastMessage(status: UpdateStatus) {
|
||||||
@@ -168,6 +169,7 @@ function notifyActionProvidersAvailabilityChanged(
|
|||||||
new CustomEvent(PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
new CustomEvent(PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||||
detail: {
|
detail: {
|
||||||
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
||||||
|
zapret2Installed: Boolean(systemInfo.zapret2_installed),
|
||||||
byedpiInstalled: Boolean(systemInfo.byedpi_installed),
|
byedpiInstalled: Boolean(systemInfo.byedpi_installed),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -214,6 +216,18 @@ function patchSystemInfoAfterMutation(result: Podkop.ComponentActionResult) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.component === 'zapret2') {
|
||||||
|
nextSystemInfo.providerInfoLoaded = true;
|
||||||
|
|
||||||
|
if (result.action === 'remove') {
|
||||||
|
nextSystemInfo.zapret2_installed = 0;
|
||||||
|
nextSystemInfo.zapret2_version = 'not installed';
|
||||||
|
} else {
|
||||||
|
nextSystemInfo.zapret2_installed = 1;
|
||||||
|
nextSystemInfo.zapret2_version = version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result.component === 'byedpi') {
|
if (result.component === 'byedpi') {
|
||||||
nextSystemInfo.providerInfoLoaded = true;
|
nextSystemInfo.providerInfoLoaded = true;
|
||||||
|
|
||||||
@@ -230,7 +244,11 @@ function patchSystemInfoAfterMutation(result: Podkop.ComponentActionResult) {
|
|||||||
diagnosticsSystemInfo: nextSystemInfo,
|
diagnosticsSystemInfo: nextSystemInfo,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.component === 'zapret' || result.component === 'byedpi') {
|
if (
|
||||||
|
result.component === 'zapret' ||
|
||||||
|
result.component === 'zapret2' ||
|
||||||
|
result.component === 'byedpi'
|
||||||
|
) {
|
||||||
notifyActionProvidersAvailabilityChanged(nextSystemInfo);
|
notifyActionProvidersAvailabilityChanged(nextSystemInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,6 +350,7 @@ function getComponentCards(): ComponentCard[] {
|
|||||||
const systemInfo = store.get().diagnosticsSystemInfo;
|
const systemInfo = store.get().diagnosticsSystemInfo;
|
||||||
const systemInfoLoading = isSystemInfoLoading();
|
const systemInfoLoading = isSystemInfoLoading();
|
||||||
const zapretInstalled = Boolean(systemInfo.zapret_installed);
|
const zapretInstalled = Boolean(systemInfo.zapret_installed);
|
||||||
|
const zapret2Installed = Boolean(systemInfo.zapret2_installed);
|
||||||
const byedpiInstalled = Boolean(systemInfo.byedpi_installed);
|
const byedpiInstalled = Boolean(systemInfo.byedpi_installed);
|
||||||
const singBoxInstallAction: ComponentActionButton =
|
const singBoxInstallAction: ComponentActionButton =
|
||||||
systemInfo.sing_box_extended
|
systemInfo.sing_box_extended
|
||||||
@@ -368,11 +387,7 @@ function getComponentCards(): ComponentCard[] {
|
|||||||
releaseUrl: getGitHubReleaseUrl('sing_box'),
|
releaseUrl: getGitHubReleaseUrl('sing_box'),
|
||||||
tag: getCheckTag('sing_box'),
|
tag: getCheckTag('sing_box'),
|
||||||
actions: [
|
actions: [
|
||||||
getPrimaryUpdateAction(
|
getPrimaryUpdateAction('sing_box', 'singBoxCheck', 'singBoxInstall'),
|
||||||
'sing_box',
|
|
||||||
'singBoxCheck',
|
|
||||||
'singBoxInstall',
|
|
||||||
),
|
|
||||||
singBoxInstallAction,
|
singBoxInstallAction,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -406,6 +421,36 @@ function getComponentCards(): ComponentCard[] {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Zapret2',
|
||||||
|
version: systemInfoLoading
|
||||||
|
? 'loading'
|
||||||
|
: zapret2Installed
|
||||||
|
? systemInfo.zapret2_version
|
||||||
|
: _('Not installed'),
|
||||||
|
releaseUrl: getGitHubReleaseUrl('zapret2'),
|
||||||
|
tag: zapret2Installed ? getCheckTag('zapret2') : undefined,
|
||||||
|
actions: zapret2Installed
|
||||||
|
? [
|
||||||
|
getPrimaryUpdateAction('zapret2', 'zapret2Check', 'zapret2Install'),
|
||||||
|
{
|
||||||
|
key: 'zapret2Remove',
|
||||||
|
text: _('Remove'),
|
||||||
|
icon: renderXIcon24,
|
||||||
|
component: 'zapret2',
|
||||||
|
action: 'remove',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
key: 'zapret2Install',
|
||||||
|
text: _('Install'),
|
||||||
|
icon: renderRotateCcwIcon24,
|
||||||
|
component: 'zapret2',
|
||||||
|
action: 'install',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'ByeDPI',
|
title: 'ByeDPI',
|
||||||
version: systemInfoLoading
|
version: systemInfoLoading
|
||||||
@@ -503,11 +548,7 @@ function renderComponentCard(card: ComponentCard) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return E('div', { class: 'pdk_updates-page__component' }, [
|
return E('div', { class: 'pdk_updates-page__component' }, [
|
||||||
E(
|
E('div', { class: 'pdk_updates-page__component__header' }, headerChildren),
|
||||||
'div',
|
|
||||||
{ class: 'pdk_updates-page__component__header' },
|
|
||||||
headerChildren,
|
|
||||||
),
|
|
||||||
E('div', { class: 'pdk_updates-page__component__version' }, [
|
E('div', { class: 'pdk_updates-page__component__version' }, [
|
||||||
E(
|
E(
|
||||||
'span',
|
'span',
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export namespace Podkop {
|
|||||||
CHECK_FAKEIP = 'check_fakeip',
|
CHECK_FAKEIP = 'check_fakeip',
|
||||||
CHECK_NFT_RULES = 'check_nft_rules',
|
CHECK_NFT_RULES = 'check_nft_rules',
|
||||||
CHECK_ZAPRET_RUNTIME = 'check_zapret_runtime',
|
CHECK_ZAPRET_RUNTIME = 'check_zapret_runtime',
|
||||||
|
CHECK_ZAPRET2_RUNTIME = 'check_zapret2_runtime',
|
||||||
CHECK_BYEDPI_RUNTIME = 'check_byedpi_runtime',
|
CHECK_BYEDPI_RUNTIME = 'check_byedpi_runtime',
|
||||||
CHECK_INBOUNDS_CONFIG = 'check_inbounds_config',
|
CHECK_INBOUNDS_CONFIG = 'check_inbounds_config',
|
||||||
GET_STATUS = 'get_status',
|
GET_STATUS = 'get_status',
|
||||||
@@ -67,6 +68,7 @@ export namespace Podkop {
|
|||||||
CHECK_INBOUNDS = 'check_inbounds',
|
CHECK_INBOUNDS = 'check_inbounds',
|
||||||
GET_SING_BOX_STATUS = 'get_sing_box_status',
|
GET_SING_BOX_STATUS = 'get_sing_box_status',
|
||||||
GET_ZAPRET_STATUS = 'get_zapret_status',
|
GET_ZAPRET_STATUS = 'get_zapret_status',
|
||||||
|
GET_ZAPRET2_STATUS = 'get_zapret2_status',
|
||||||
GET_BYEDPI_STATUS = 'get_byedpi_status',
|
GET_BYEDPI_STATUS = 'get_byedpi_status',
|
||||||
CLASH_API = 'clash_api',
|
CLASH_API = 'clash_api',
|
||||||
RESTART = 'restart',
|
RESTART = 'restart',
|
||||||
@@ -153,6 +155,7 @@ export namespace Podkop {
|
|||||||
| 'direct'
|
| 'direct'
|
||||||
| 'block'
|
| 'block'
|
||||||
| 'zapret'
|
| 'zapret'
|
||||||
|
| 'zapret2'
|
||||||
| 'byedpi';
|
| 'byedpi';
|
||||||
type LegacyConnectionType = 'proxy' | 'vpn' | 'block' | 'exclusion';
|
type LegacyConnectionType = 'proxy' | 'vpn' | 'block' | 'exclusion';
|
||||||
type ProxyConfigType =
|
type ProxyConfigType =
|
||||||
@@ -179,6 +182,7 @@ export namespace Podkop {
|
|||||||
update_interval?: string;
|
update_interval?: string;
|
||||||
proxy_string?: string;
|
proxy_string?: string;
|
||||||
nfqws_opt?: string;
|
nfqws_opt?: string;
|
||||||
|
nfqws2_opt?: string;
|
||||||
byedpi_cmd_opts?: string;
|
byedpi_cmd_opts?: string;
|
||||||
cmd_opts?: string;
|
cmd_opts?: string;
|
||||||
selector_proxy_links?: string[];
|
selector_proxy_links?: string[];
|
||||||
@@ -326,6 +330,8 @@ export namespace Podkop {
|
|||||||
sing_box_extended: 0 | 1;
|
sing_box_extended: 0 | 1;
|
||||||
zapret_version: string;
|
zapret_version: string;
|
||||||
zapret_installed: 0 | 1;
|
zapret_installed: 0 | 1;
|
||||||
|
zapret2_version: string;
|
||||||
|
zapret2_installed: 0 | 1;
|
||||||
byedpi_version: string;
|
byedpi_version: string;
|
||||||
byedpi_installed: 0 | 1;
|
byedpi_installed: 0 | 1;
|
||||||
openwrt_version: string;
|
openwrt_version: string;
|
||||||
@@ -340,11 +346,17 @@ export namespace Podkop {
|
|||||||
export interface GetUiCapabilities {
|
export interface GetUiCapabilities {
|
||||||
sing_box_extended: 0 | 1;
|
sing_box_extended: 0 | 1;
|
||||||
zapret_installed: 0 | 1;
|
zapret_installed: 0 | 1;
|
||||||
|
zapret2_installed: 0 | 1;
|
||||||
byedpi_installed: 0 | 1;
|
byedpi_installed: 0 | 1;
|
||||||
server_inbounds_enabled_count: number;
|
server_inbounds_enabled_count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ComponentName = 'podkop' | 'sing_box' | 'zapret' | 'byedpi';
|
export type ComponentName =
|
||||||
|
| 'podkop'
|
||||||
|
| 'sing_box'
|
||||||
|
| 'zapret'
|
||||||
|
| 'zapret2'
|
||||||
|
| 'byedpi';
|
||||||
|
|
||||||
export type ComponentAction =
|
export type ComponentAction =
|
||||||
| 'check_update'
|
| 'check_update'
|
||||||
@@ -422,6 +434,40 @@ export namespace Podkop {
|
|||||||
zapret_provider_path: string;
|
zapret_provider_path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetZapret2Status {
|
||||||
|
installed: 0 | 1;
|
||||||
|
package_installed: 0 | 1;
|
||||||
|
provider_available: 0 | 1;
|
||||||
|
provider_path: string;
|
||||||
|
files_available: 0 | 1;
|
||||||
|
ipset_available: 0 | 1;
|
||||||
|
version: string;
|
||||||
|
configured: 0 | 1;
|
||||||
|
enabled_rule_count: number;
|
||||||
|
expected_process_count: number;
|
||||||
|
running_process_count: number;
|
||||||
|
supervisor_process_count: number;
|
||||||
|
standalone_service_enabled: 0 | 1;
|
||||||
|
standalone_service_running: 0 | 1;
|
||||||
|
standalone_config_present: 0 | 1;
|
||||||
|
standalone_conflict: 0 | 1;
|
||||||
|
luci_app_installed: 0 | 1;
|
||||||
|
queue_base: number;
|
||||||
|
queue_range_end: number;
|
||||||
|
queue_overlap: 0 | 1;
|
||||||
|
ready: 0 | 1;
|
||||||
|
conflict: 0 | 1;
|
||||||
|
outbounds_configured: 0 | 1;
|
||||||
|
routes_configured: 0 | 1;
|
||||||
|
status_message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Zapret2CheckResult {
|
||||||
|
zapret2_installed: 0 | 1;
|
||||||
|
zapret2_package_installed: 0 | 1;
|
||||||
|
zapret2_provider_path: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface GetByedpiStatus {
|
export interface GetByedpiStatus {
|
||||||
installed: 0 | 1;
|
installed: 0 | 1;
|
||||||
package_installed: 0 | 1;
|
package_installed: 0 | 1;
|
||||||
|
|||||||
@@ -549,6 +549,12 @@ function validateHysteria2Url(url) {
|
|||||||
message: _("Invalid HY2 URL: sni cannot be empty")
|
message: _("Invalid HY2 URL: sni cannot be empty")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (paramsKeys.includes("mport") && (!params.mport || !params.mport.split(",").every(isValidPortEntry))) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Invalid HY2 URL: invalid port number")
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return { valid: true, message: _("Valid") };
|
return { valid: true, message: _("Valid") };
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
@@ -2074,6 +2080,7 @@ var Podkop;
|
|||||||
AvailableMethods2["CHECK_FAKEIP"] = "check_fakeip";
|
AvailableMethods2["CHECK_FAKEIP"] = "check_fakeip";
|
||||||
AvailableMethods2["CHECK_NFT_RULES"] = "check_nft_rules";
|
AvailableMethods2["CHECK_NFT_RULES"] = "check_nft_rules";
|
||||||
AvailableMethods2["CHECK_ZAPRET_RUNTIME"] = "check_zapret_runtime";
|
AvailableMethods2["CHECK_ZAPRET_RUNTIME"] = "check_zapret_runtime";
|
||||||
|
AvailableMethods2["CHECK_ZAPRET2_RUNTIME"] = "check_zapret2_runtime";
|
||||||
AvailableMethods2["CHECK_BYEDPI_RUNTIME"] = "check_byedpi_runtime";
|
AvailableMethods2["CHECK_BYEDPI_RUNTIME"] = "check_byedpi_runtime";
|
||||||
AvailableMethods2["CHECK_INBOUNDS_CONFIG"] = "check_inbounds_config";
|
AvailableMethods2["CHECK_INBOUNDS_CONFIG"] = "check_inbounds_config";
|
||||||
AvailableMethods2["GET_STATUS"] = "get_status";
|
AvailableMethods2["GET_STATUS"] = "get_status";
|
||||||
@@ -2085,6 +2092,7 @@ var Podkop;
|
|||||||
AvailableMethods2["CHECK_INBOUNDS"] = "check_inbounds";
|
AvailableMethods2["CHECK_INBOUNDS"] = "check_inbounds";
|
||||||
AvailableMethods2["GET_SING_BOX_STATUS"] = "get_sing_box_status";
|
AvailableMethods2["GET_SING_BOX_STATUS"] = "get_sing_box_status";
|
||||||
AvailableMethods2["GET_ZAPRET_STATUS"] = "get_zapret_status";
|
AvailableMethods2["GET_ZAPRET_STATUS"] = "get_zapret_status";
|
||||||
|
AvailableMethods2["GET_ZAPRET2_STATUS"] = "get_zapret2_status";
|
||||||
AvailableMethods2["GET_BYEDPI_STATUS"] = "get_byedpi_status";
|
AvailableMethods2["GET_BYEDPI_STATUS"] = "get_byedpi_status";
|
||||||
AvailableMethods2["CLASH_API"] = "clash_api";
|
AvailableMethods2["CLASH_API"] = "clash_api";
|
||||||
AvailableMethods2["RESTART"] = "restart";
|
AvailableMethods2["RESTART"] = "restart";
|
||||||
@@ -2216,6 +2224,9 @@ var PodkopShellMethods = {
|
|||||||
checkZapretRuntime: async () => callBaseMethod(
|
checkZapretRuntime: async () => callBaseMethod(
|
||||||
Podkop.AvailableMethods.CHECK_ZAPRET_RUNTIME
|
Podkop.AvailableMethods.CHECK_ZAPRET_RUNTIME
|
||||||
),
|
),
|
||||||
|
checkZapret2Runtime: async () => callBaseMethod(
|
||||||
|
Podkop.AvailableMethods.CHECK_ZAPRET2_RUNTIME
|
||||||
|
),
|
||||||
checkByedpiRuntime: async () => callBaseMethod(
|
checkByedpiRuntime: async () => callBaseMethod(
|
||||||
Podkop.AvailableMethods.CHECK_BYEDPI_RUNTIME
|
Podkop.AvailableMethods.CHECK_BYEDPI_RUNTIME
|
||||||
),
|
),
|
||||||
@@ -2251,6 +2262,9 @@ var PodkopShellMethods = {
|
|||||||
getZapretStatus: async () => callBaseMethod(
|
getZapretStatus: async () => callBaseMethod(
|
||||||
Podkop.AvailableMethods.GET_ZAPRET_STATUS
|
Podkop.AvailableMethods.GET_ZAPRET_STATUS
|
||||||
),
|
),
|
||||||
|
getZapret2Status: async () => callBaseMethod(
|
||||||
|
Podkop.AvailableMethods.GET_ZAPRET2_STATUS
|
||||||
|
),
|
||||||
getByedpiStatus: async () => callBaseMethod(
|
getByedpiStatus: async () => callBaseMethod(
|
||||||
Podkop.AvailableMethods.GET_BYEDPI_STATUS
|
Podkop.AvailableMethods.GET_BYEDPI_STATUS
|
||||||
),
|
),
|
||||||
@@ -3020,17 +3034,22 @@ var DIAGNOSTICS_CHECKS_MAP = {
|
|||||||
code: "ZAPRET" /* ZAPRET */
|
code: "ZAPRET" /* ZAPRET */
|
||||||
},
|
},
|
||||||
["BYEDPI" /* BYEDPI */]: {
|
["BYEDPI" /* BYEDPI */]: {
|
||||||
order: 6,
|
order: 7,
|
||||||
title: getCheckTitle("ByeDPI"),
|
title: getCheckTitle("ByeDPI"),
|
||||||
code: "BYEDPI" /* BYEDPI */
|
code: "BYEDPI" /* BYEDPI */
|
||||||
},
|
},
|
||||||
|
["ZAPRET2" /* ZAPRET2 */]: {
|
||||||
|
order: 6,
|
||||||
|
title: getCheckTitle("Zapret2"),
|
||||||
|
code: "ZAPRET2" /* ZAPRET2 */
|
||||||
|
},
|
||||||
["OUTBOUNDS" /* OUTBOUNDS */]: {
|
["OUTBOUNDS" /* OUTBOUNDS */]: {
|
||||||
order: 7,
|
order: 8,
|
||||||
title: getCheckTitle("Outbounds"),
|
title: getCheckTitle("Outbounds"),
|
||||||
code: "OUTBOUNDS" /* OUTBOUNDS */
|
code: "OUTBOUNDS" /* OUTBOUNDS */
|
||||||
},
|
},
|
||||||
["FAKEIP" /* FAKEIP */]: {
|
["FAKEIP" /* FAKEIP */]: {
|
||||||
order: 8,
|
order: 9,
|
||||||
title: getCheckTitle("FakeIP"),
|
title: getCheckTitle("FakeIP"),
|
||||||
code: "FAKEIP" /* FAKEIP */
|
code: "FAKEIP" /* FAKEIP */
|
||||||
},
|
},
|
||||||
@@ -3062,6 +3081,9 @@ function getDiagnosticsChecks(description, options = {}) {
|
|||||||
if (options.includeZapret) {
|
if (options.includeZapret) {
|
||||||
checks.push("ZAPRET" /* ZAPRET */);
|
checks.push("ZAPRET" /* ZAPRET */);
|
||||||
}
|
}
|
||||||
|
if (options.includeZapret2) {
|
||||||
|
checks.push("ZAPRET2" /* ZAPRET2 */);
|
||||||
|
}
|
||||||
if (options.includeByedpi) {
|
if (options.includeByedpi) {
|
||||||
checks.push("BYEDPI" /* BYEDPI */);
|
checks.push("BYEDPI" /* BYEDPI */);
|
||||||
}
|
}
|
||||||
@@ -3085,6 +3107,8 @@ var initialDiagnosticStore = {
|
|||||||
sing_box_extended: 0,
|
sing_box_extended: 0,
|
||||||
zapret_version: "loading",
|
zapret_version: "loading",
|
||||||
zapret_installed: 0,
|
zapret_installed: 0,
|
||||||
|
zapret2_version: "loading",
|
||||||
|
zapret2_installed: 0,
|
||||||
byedpi_version: "loading",
|
byedpi_version: "loading",
|
||||||
byedpi_installed: 0,
|
byedpi_installed: 0,
|
||||||
server_inbounds_enabled_count: -1,
|
server_inbounds_enabled_count: -1,
|
||||||
@@ -3129,6 +3153,9 @@ var initialDiagnosticStore = {
|
|||||||
zapretCheck: { loading: false },
|
zapretCheck: { loading: false },
|
||||||
zapretInstall: { loading: false },
|
zapretInstall: { loading: false },
|
||||||
zapretRemove: { loading: false },
|
zapretRemove: { loading: false },
|
||||||
|
zapret2Check: { loading: false },
|
||||||
|
zapret2Install: { loading: false },
|
||||||
|
zapret2Remove: { loading: false },
|
||||||
byedpiCheck: { loading: false },
|
byedpiCheck: { loading: false },
|
||||||
byedpiInstall: { loading: false },
|
byedpiInstall: { loading: false },
|
||||||
byedpiRemove: { loading: false }
|
byedpiRemove: { loading: false }
|
||||||
@@ -3137,6 +3164,7 @@ var initialDiagnosticStore = {
|
|||||||
podkop: { status: null, latest_version: "", release_url: "" },
|
podkop: { status: null, latest_version: "", release_url: "" },
|
||||||
sing_box: { status: null, latest_version: "", release_url: "" },
|
sing_box: { status: null, latest_version: "", release_url: "" },
|
||||||
zapret: { status: null, latest_version: "", release_url: "" },
|
zapret: { status: null, latest_version: "", release_url: "" },
|
||||||
|
zapret2: { status: null, latest_version: "", release_url: "" },
|
||||||
byedpi: { status: null, latest_version: "", release_url: "" }
|
byedpi: { status: null, latest_version: "", release_url: "" }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5264,6 +5292,118 @@ async function runZapretCheck() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src/podkop/tabs/diagnostic/checks/runZapret2Check.ts
|
||||||
|
async function runZapret2Check() {
|
||||||
|
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.ZAPRET2;
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _("Checking, please wait"),
|
||||||
|
state: "loading",
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
const zapret2Status = await PodkopShellMethods.getZapret2Status();
|
||||||
|
if (!zapret2Status.success) {
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description: _("Cannot receive checks result"),
|
||||||
|
state: "error",
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
throw new Error("Zapret2 checks failed");
|
||||||
|
}
|
||||||
|
const data = zapret2Status.data;
|
||||||
|
const providerAvailable = Boolean(data.provider_available ?? data.installed);
|
||||||
|
const packageInstalled = Boolean(data.package_installed);
|
||||||
|
const hasZapret2Rules = Number(data.enabled_rule_count || 0) > 0;
|
||||||
|
const ready = Boolean(data.ready);
|
||||||
|
const queueOverlap = Boolean(data.queue_overlap);
|
||||||
|
const expectedProcesses = Number(data.expected_process_count || 0);
|
||||||
|
const runningProcesses = Number(data.running_process_count || 0);
|
||||||
|
const supervisorProcesses = Number(data.supervisor_process_count || 0);
|
||||||
|
const podkopRuntimeReady = !hasZapret2Rules || runningProcesses === expectedProcesses && supervisorProcesses === expectedProcesses;
|
||||||
|
const unexpectedRuntime = !hasZapret2Rules && (runningProcesses > 0 || supervisorProcesses > 0);
|
||||||
|
const outboundsConfigured = Boolean(data.outbounds_configured);
|
||||||
|
const routesConfigured = Boolean(data.routes_configured);
|
||||||
|
const standaloneServiceEnabled = Boolean(data.standalone_service_enabled);
|
||||||
|
const standaloneServiceRunning = Boolean(data.standalone_service_running);
|
||||||
|
const standaloneConflict = hasZapret2Rules && standaloneServiceRunning;
|
||||||
|
const standaloneAutostartRisk = hasZapret2Rules && standaloneServiceEnabled && !standaloneServiceRunning;
|
||||||
|
let state = "success";
|
||||||
|
let description = _("Checks passed");
|
||||||
|
if (hasZapret2Rules && !providerAvailable) {
|
||||||
|
state = "error";
|
||||||
|
description = _("Checks failed");
|
||||||
|
} else if (hasZapret2Rules && !ready) {
|
||||||
|
state = "error";
|
||||||
|
description = _("Checks failed");
|
||||||
|
} else if (queueOverlap) {
|
||||||
|
state = "error";
|
||||||
|
description = _("Checks failed");
|
||||||
|
} else if (standaloneConflict) {
|
||||||
|
state = "error";
|
||||||
|
description = _("Checks failed");
|
||||||
|
} else if (standaloneAutostartRisk || !packageInstalled) {
|
||||||
|
state = "warning";
|
||||||
|
description = _("Issues detected");
|
||||||
|
}
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
state: providerAvailable ? "success" : hasZapret2Rules ? "error" : "warning",
|
||||||
|
key: providerAvailable ? _("Zapret2 provider binary is available") : _("Zapret2 provider binary is not available"),
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: packageInstalled ? "success" : hasZapret2Rules ? "error" : "warning",
|
||||||
|
key: packageInstalled ? _("Zapret2 package is installed") : _("Zapret2 package is not installed"),
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: hasZapret2Rules && !providerAvailable ? "error" : "success",
|
||||||
|
key: hasZapret2Rules ? _("There are rules using Zapret2") : _("No rules use Zapret2"),
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: unexpectedRuntime || !podkopRuntimeReady ? "error" : "success",
|
||||||
|
key: hasZapret2Rules ? podkopRuntimeReady ? _("Podkop Plus-managed nfqws2 runtime is ready") : _("Podkop Plus-managed nfqws2 runtime is not ready") : unexpectedRuntime ? _("Unexpected Podkop Plus-managed nfqws2 runtime is running") : _("Podkop Plus-managed nfqws2 runtime is not running"),
|
||||||
|
value: hasZapret2Rules ? `${runningProcesses}/${expectedProcesses}` : ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: queueOverlap ? "error" : "success",
|
||||||
|
key: queueOverlap ? _("NFQUEUE range overlaps with another rule") : _("NFQUEUE range is available"),
|
||||||
|
value: `${Number(data.queue_base || 0)}-${Number(data.queue_range_end || 0)}`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: !hasZapret2Rules || outboundsConfigured ? "success" : "error",
|
||||||
|
key: outboundsConfigured ? _("Zapret2 sing-box outbound is configured") : _("Zapret2 sing-box outbound is not configured"),
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: !hasZapret2Rules || routesConfigured ? "success" : "error",
|
||||||
|
key: routesConfigured ? _("Zapret2 route rules are configured") : _("Zapret2 route rules are not configured"),
|
||||||
|
value: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: standaloneConflict ? "error" : standaloneAutostartRisk ? "warning" : "success",
|
||||||
|
key: standaloneServiceRunning ? hasZapret2Rules ? _(
|
||||||
|
"Standalone Zapret2 is active together with Podkop Plus Zapret2 rules"
|
||||||
|
) : _("Standalone Zapret2 service is active") : standaloneAutostartRisk ? _("Standalone Zapret2 autostart is enabled") : _("Standalone Zapret2 service is inactive"),
|
||||||
|
value: ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
updateCheckStore({
|
||||||
|
order,
|
||||||
|
code,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
state,
|
||||||
|
items
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// src/podkop/tabs/diagnostic/checks/runByedpiCheck.ts
|
// src/podkop/tabs/diagnostic/checks/runByedpiCheck.ts
|
||||||
async function runByedpiCheck() {
|
async function runByedpiCheck() {
|
||||||
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.BYEDPI;
|
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.BYEDPI;
|
||||||
@@ -5387,6 +5527,8 @@ var UNKNOWN_SYSTEM_INFO = {
|
|||||||
sing_box_extended: 0,
|
sing_box_extended: 0,
|
||||||
zapret_version: _("unknown"),
|
zapret_version: _("unknown"),
|
||||||
zapret_installed: 0,
|
zapret_installed: 0,
|
||||||
|
zapret2_version: _("unknown"),
|
||||||
|
zapret2_installed: 0,
|
||||||
byedpi_version: _("unknown"),
|
byedpi_version: _("unknown"),
|
||||||
byedpi_installed: 0,
|
byedpi_installed: 0,
|
||||||
server_inbounds_enabled_count: -1,
|
server_inbounds_enabled_count: -1,
|
||||||
@@ -5450,6 +5592,7 @@ async function ensureSystemInfo({
|
|||||||
loaded: false,
|
loaded: false,
|
||||||
providerInfoLoaded: latestSystemInfo.providerInfoLoaded,
|
providerInfoLoaded: latestSystemInfo.providerInfoLoaded,
|
||||||
zapret_installed: latestSystemInfo.zapret_installed,
|
zapret_installed: latestSystemInfo.zapret_installed,
|
||||||
|
zapret2_installed: latestSystemInfo.zapret2_installed,
|
||||||
byedpi_installed: latestSystemInfo.byedpi_installed,
|
byedpi_installed: latestSystemInfo.byedpi_installed,
|
||||||
server_inbounds_enabled_count: latestSystemInfo.server_inbounds_enabled_count
|
server_inbounds_enabled_count: latestSystemInfo.server_inbounds_enabled_count
|
||||||
};
|
};
|
||||||
@@ -6268,6 +6411,7 @@ function sleep2(ms) {
|
|||||||
function getDiagnosticsProviderOptions(systemInfo = store.get().diagnosticsSystemInfo) {
|
function getDiagnosticsProviderOptions(systemInfo = store.get().diagnosticsSystemInfo) {
|
||||||
return {
|
return {
|
||||||
includeZapret: Boolean(systemInfo.zapret_installed),
|
includeZapret: Boolean(systemInfo.zapret_installed),
|
||||||
|
includeZapret2: Boolean(systemInfo.zapret2_installed),
|
||||||
includeByedpi: Boolean(systemInfo.byedpi_installed),
|
includeByedpi: Boolean(systemInfo.byedpi_installed),
|
||||||
includeInbounds: systemInfo.server_inbounds_enabled_count !== 0
|
includeInbounds: systemInfo.server_inbounds_enabled_count !== 0
|
||||||
};
|
};
|
||||||
@@ -6391,8 +6535,9 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
} = {}) {
|
} = {}) {
|
||||||
const requestId = ++latestProviderInfoRequestId;
|
const requestId = ++latestProviderInfoRequestId;
|
||||||
try {
|
try {
|
||||||
const [zapretRuntime, byedpiRuntime, inboundsConfig] = await Promise.all([
|
const [zapretRuntime, zapret2Runtime, byedpiRuntime, inboundsConfig] = await Promise.all([
|
||||||
PodkopShellMethods.checkZapretRuntime(),
|
PodkopShellMethods.checkZapretRuntime(),
|
||||||
|
PodkopShellMethods.checkZapret2Runtime(),
|
||||||
PodkopShellMethods.checkByedpiRuntime(),
|
PodkopShellMethods.checkByedpiRuntime(),
|
||||||
PodkopShellMethods.checkInboundsConfig()
|
PodkopShellMethods.checkInboundsConfig()
|
||||||
]);
|
]);
|
||||||
@@ -6404,12 +6549,20 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
...currentSystemInfo,
|
...currentSystemInfo,
|
||||||
providerInfoLoaded: true,
|
providerInfoLoaded: true,
|
||||||
zapret_installed: zapretRuntime.success ? zapretRuntime.data.zapret_installed : currentSystemInfo.zapret_installed,
|
zapret_installed: zapretRuntime.success ? zapretRuntime.data.zapret_installed : currentSystemInfo.zapret_installed,
|
||||||
|
zapret2_installed: zapret2Runtime.success ? zapret2Runtime.data.zapret2_installed : currentSystemInfo.zapret2_installed,
|
||||||
byedpi_installed: byedpiRuntime.success ? byedpiRuntime.data.byedpi_installed : currentSystemInfo.byedpi_installed,
|
byedpi_installed: byedpiRuntime.success ? byedpiRuntime.data.byedpi_installed : currentSystemInfo.byedpi_installed,
|
||||||
server_inbounds_enabled_count: inboundsConfig.success ? inboundsConfig.data.enabled_count : -1
|
server_inbounds_enabled_count: inboundsConfig.success ? inboundsConfig.data.enabled_count : -1
|
||||||
};
|
};
|
||||||
if (!zapretRuntime.success) {
|
if (!zapretRuntime.success) {
|
||||||
logger.error("[DIAGNOSTIC]", "fetchZapretRuntime failed", zapretRuntime);
|
logger.error("[DIAGNOSTIC]", "fetchZapretRuntime failed", zapretRuntime);
|
||||||
}
|
}
|
||||||
|
if (!zapret2Runtime.success) {
|
||||||
|
logger.error(
|
||||||
|
"[DIAGNOSTIC]",
|
||||||
|
"fetchZapret2Runtime failed",
|
||||||
|
zapret2Runtime
|
||||||
|
);
|
||||||
|
}
|
||||||
if (!byedpiRuntime.success) {
|
if (!byedpiRuntime.success) {
|
||||||
logger.error("[DIAGNOSTIC]", "fetchByedpiRuntime failed", byedpiRuntime);
|
logger.error("[DIAGNOSTIC]", "fetchByedpiRuntime failed", byedpiRuntime);
|
||||||
}
|
}
|
||||||
@@ -6423,6 +6576,9 @@ async function fetchDiagnosticsProviderInfo({
|
|||||||
if (!nextSystemInfo.zapret_installed) {
|
if (!nextSystemInfo.zapret_installed) {
|
||||||
nextSystemInfo.zapret_version = "not installed";
|
nextSystemInfo.zapret_version = "not installed";
|
||||||
}
|
}
|
||||||
|
if (!nextSystemInfo.zapret2_installed) {
|
||||||
|
nextSystemInfo.zapret2_version = "not installed";
|
||||||
|
}
|
||||||
if (!nextSystemInfo.byedpi_installed) {
|
if (!nextSystemInfo.byedpi_installed) {
|
||||||
nextSystemInfo.byedpi_version = "not installed";
|
nextSystemInfo.byedpi_version = "not installed";
|
||||||
}
|
}
|
||||||
@@ -6727,6 +6883,12 @@ function renderDiagnosticSystemInfoWidget() {
|
|||||||
value: diagnosticsSystemInfo.zapret_version
|
value: diagnosticsSystemInfo.zapret_version
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (diagnosticsSystemInfo.zapret2_installed) {
|
||||||
|
items.push({
|
||||||
|
key: "Zapret2",
|
||||||
|
value: diagnosticsSystemInfo.zapret2_version
|
||||||
|
});
|
||||||
|
}
|
||||||
if (diagnosticsSystemInfo.byedpi_installed) {
|
if (diagnosticsSystemInfo.byedpi_installed) {
|
||||||
items.push({
|
items.push({
|
||||||
key: "ByeDPI",
|
key: "ByeDPI",
|
||||||
@@ -6781,6 +6943,7 @@ async function runChecks() {
|
|||||||
...providerOptions.includeInbounds ? [runInboundsCheck] : [],
|
...providerOptions.includeInbounds ? [runInboundsCheck] : [],
|
||||||
runNftCheck,
|
runNftCheck,
|
||||||
...providerOptions.includeZapret ? [runZapretCheck] : [],
|
...providerOptions.includeZapret ? [runZapretCheck] : [],
|
||||||
|
...providerOptions.includeZapret2 ? [runZapret2Check] : [],
|
||||||
...providerOptions.includeByedpi ? [runByedpiCheck] : [],
|
...providerOptions.includeByedpi ? [runByedpiCheck] : [],
|
||||||
runSectionsCheck,
|
runSectionsCheck,
|
||||||
runFakeIPCheck
|
runFakeIPCheck
|
||||||
@@ -8914,6 +9077,7 @@ function notifyActionProvidersAvailabilityChanged(systemInfo) {
|
|||||||
new CustomEvent(PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
new CustomEvent(PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||||
detail: {
|
detail: {
|
||||||
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
||||||
|
zapret2Installed: Boolean(systemInfo.zapret2_installed),
|
||||||
byedpiInstalled: Boolean(systemInfo.byedpi_installed)
|
byedpiInstalled: Boolean(systemInfo.byedpi_installed)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -8950,6 +9114,16 @@ function patchSystemInfoAfterMutation(result) {
|
|||||||
nextSystemInfo.zapret_version = version;
|
nextSystemInfo.zapret_version = version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result.component === "zapret2") {
|
||||||
|
nextSystemInfo.providerInfoLoaded = true;
|
||||||
|
if (result.action === "remove") {
|
||||||
|
nextSystemInfo.zapret2_installed = 0;
|
||||||
|
nextSystemInfo.zapret2_version = "not installed";
|
||||||
|
} else {
|
||||||
|
nextSystemInfo.zapret2_installed = 1;
|
||||||
|
nextSystemInfo.zapret2_version = version;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (result.component === "byedpi") {
|
if (result.component === "byedpi") {
|
||||||
nextSystemInfo.providerInfoLoaded = true;
|
nextSystemInfo.providerInfoLoaded = true;
|
||||||
if (result.action === "remove") {
|
if (result.action === "remove") {
|
||||||
@@ -8963,7 +9137,7 @@ function patchSystemInfoAfterMutation(result) {
|
|||||||
store.set({
|
store.set({
|
||||||
diagnosticsSystemInfo: nextSystemInfo
|
diagnosticsSystemInfo: nextSystemInfo
|
||||||
});
|
});
|
||||||
if (result.component === "zapret" || result.component === "byedpi") {
|
if (result.component === "zapret" || result.component === "zapret2" || result.component === "byedpi") {
|
||||||
notifyActionProvidersAvailabilityChanged(nextSystemInfo);
|
notifyActionProvidersAvailabilityChanged(nextSystemInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9044,6 +9218,7 @@ function getComponentCards() {
|
|||||||
const systemInfo = store.get().diagnosticsSystemInfo;
|
const systemInfo = store.get().diagnosticsSystemInfo;
|
||||||
const systemInfoLoading = isSystemInfoLoading();
|
const systemInfoLoading = isSystemInfoLoading();
|
||||||
const zapretInstalled = Boolean(systemInfo.zapret_installed);
|
const zapretInstalled = Boolean(systemInfo.zapret_installed);
|
||||||
|
const zapret2Installed = Boolean(systemInfo.zapret2_installed);
|
||||||
const byedpiInstalled = Boolean(systemInfo.byedpi_installed);
|
const byedpiInstalled = Boolean(systemInfo.byedpi_installed);
|
||||||
const singBoxInstallAction = systemInfo.sing_box_extended ? {
|
const singBoxInstallAction = systemInfo.sing_box_extended ? {
|
||||||
key: "singBoxInstallStable",
|
key: "singBoxInstallStable",
|
||||||
@@ -9074,11 +9249,7 @@ function getComponentCards() {
|
|||||||
releaseUrl: getGitHubReleaseUrl("sing_box"),
|
releaseUrl: getGitHubReleaseUrl("sing_box"),
|
||||||
tag: getCheckTag("sing_box"),
|
tag: getCheckTag("sing_box"),
|
||||||
actions: [
|
actions: [
|
||||||
getPrimaryUpdateAction(
|
getPrimaryUpdateAction("sing_box", "singBoxCheck", "singBoxInstall"),
|
||||||
"sing_box",
|
|
||||||
"singBoxCheck",
|
|
||||||
"singBoxInstall"
|
|
||||||
),
|
|
||||||
singBoxInstallAction
|
singBoxInstallAction
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -9106,6 +9277,30 @@ function getComponentCards() {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Zapret2",
|
||||||
|
version: systemInfoLoading ? "loading" : zapret2Installed ? systemInfo.zapret2_version : _("Not installed"),
|
||||||
|
releaseUrl: getGitHubReleaseUrl("zapret2"),
|
||||||
|
tag: zapret2Installed ? getCheckTag("zapret2") : void 0,
|
||||||
|
actions: zapret2Installed ? [
|
||||||
|
getPrimaryUpdateAction("zapret2", "zapret2Check", "zapret2Install"),
|
||||||
|
{
|
||||||
|
key: "zapret2Remove",
|
||||||
|
text: _("Remove"),
|
||||||
|
icon: renderXIcon24,
|
||||||
|
component: "zapret2",
|
||||||
|
action: "remove"
|
||||||
|
}
|
||||||
|
] : [
|
||||||
|
{
|
||||||
|
key: "zapret2Install",
|
||||||
|
text: _("Install"),
|
||||||
|
icon: renderRotateCcwIcon24,
|
||||||
|
component: "zapret2",
|
||||||
|
action: "install"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "ByeDPI",
|
title: "ByeDPI",
|
||||||
version: systemInfoLoading ? "loading" : byedpiInstalled ? systemInfo.byedpi_version : _("Not installed"),
|
version: systemInfoLoading ? "loading" : byedpiInstalled ? systemInfo.byedpi_version : _("Not installed"),
|
||||||
@@ -9184,11 +9379,7 @@ function renderComponentCard(card) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return E("div", { class: "pdk_updates-page__component" }, [
|
return E("div", { class: "pdk_updates-page__component" }, [
|
||||||
E(
|
E("div", { class: "pdk_updates-page__component__header" }, headerChildren),
|
||||||
"div",
|
|
||||||
{ class: "pdk_updates-page__component__header" },
|
|
||||||
headerChildren
|
|
||||||
),
|
|
||||||
E("div", { class: "pdk_updates-page__component__version" }, [
|
E("div", { class: "pdk_updates-page__component__version" }, [
|
||||||
E(
|
E(
|
||||||
"span",
|
"span",
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ const EntryPoint = {
|
|||||||
loaded: false,
|
loaded: false,
|
||||||
singBoxExtended: false,
|
singBoxExtended: false,
|
||||||
zapretInstalled: false,
|
zapretInstalled: false,
|
||||||
|
zapret2Installed: false,
|
||||||
byedpiInstalled: false,
|
byedpiInstalled: false,
|
||||||
serverInboundsEnabledCount: -1,
|
serverInboundsEnabledCount: -1,
|
||||||
};
|
};
|
||||||
@@ -121,6 +122,7 @@ const EntryPoint = {
|
|||||||
new CustomEvent(main.PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
new CustomEvent(main.PODKOP_ACTION_PROVIDERS_AVAILABILITY_EVENT, {
|
||||||
detail: {
|
detail: {
|
||||||
zapretInstalled: uiCapabilities.zapretInstalled,
|
zapretInstalled: uiCapabilities.zapretInstalled,
|
||||||
|
zapret2Installed: uiCapabilities.zapret2Installed,
|
||||||
byedpiInstalled: uiCapabilities.byedpiInstalled,
|
byedpiInstalled: uiCapabilities.byedpiInstalled,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -135,12 +137,16 @@ const EntryPoint = {
|
|||||||
providerInfoLoaded: true,
|
providerInfoLoaded: true,
|
||||||
sing_box_extended: uiCapabilities.singBoxExtended ? 1 : 0,
|
sing_box_extended: uiCapabilities.singBoxExtended ? 1 : 0,
|
||||||
zapret_installed: uiCapabilities.zapretInstalled ? 1 : 0,
|
zapret_installed: uiCapabilities.zapretInstalled ? 1 : 0,
|
||||||
|
zapret2_installed: uiCapabilities.zapret2Installed ? 1 : 0,
|
||||||
byedpi_installed: uiCapabilities.byedpiInstalled ? 1 : 0,
|
byedpi_installed: uiCapabilities.byedpiInstalled ? 1 : 0,
|
||||||
server_inbounds_enabled_count:
|
server_inbounds_enabled_count:
|
||||||
uiCapabilities.serverInboundsEnabledCount,
|
uiCapabilities.serverInboundsEnabledCount,
|
||||||
zapret_version: uiCapabilities.zapretInstalled
|
zapret_version: uiCapabilities.zapretInstalled
|
||||||
? currentSystemInfo.zapret_version
|
? currentSystemInfo.zapret_version
|
||||||
: "not installed",
|
: "not installed",
|
||||||
|
zapret2_version: uiCapabilities.zapret2Installed
|
||||||
|
? currentSystemInfo.zapret2_version
|
||||||
|
: "not installed",
|
||||||
byedpi_version: uiCapabilities.byedpiInstalled
|
byedpi_version: uiCapabilities.byedpiInstalled
|
||||||
? currentSystemInfo.byedpi_version
|
? currentSystemInfo.byedpi_version
|
||||||
: "not installed",
|
: "not installed",
|
||||||
@@ -157,6 +163,9 @@ const EntryPoint = {
|
|||||||
uiCapabilities.zapretInstalled = Boolean(
|
uiCapabilities.zapretInstalled = Boolean(
|
||||||
Number(data?.zapret_installed) === 1,
|
Number(data?.zapret_installed) === 1,
|
||||||
);
|
);
|
||||||
|
uiCapabilities.zapret2Installed = Boolean(
|
||||||
|
Number(data?.zapret2_installed) === 1,
|
||||||
|
);
|
||||||
uiCapabilities.byedpiInstalled = Boolean(
|
uiCapabilities.byedpiInstalled = Boolean(
|
||||||
Number(data?.byedpi_installed) === 1,
|
Number(data?.byedpi_installed) === 1,
|
||||||
);
|
);
|
||||||
@@ -179,12 +188,14 @@ const EntryPoint = {
|
|||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
main.PodkopShellMethods.getServerCapabilities(),
|
main.PodkopShellMethods.getServerCapabilities(),
|
||||||
main.PodkopShellMethods.checkZapretRuntime(),
|
main.PodkopShellMethods.checkZapretRuntime(),
|
||||||
|
main.PodkopShellMethods.checkZapret2Runtime(),
|
||||||
main.PodkopShellMethods.checkByedpiRuntime(),
|
main.PodkopShellMethods.checkByedpiRuntime(),
|
||||||
main.PodkopShellMethods.checkInboundsConfig(),
|
main.PodkopShellMethods.checkInboundsConfig(),
|
||||||
]).then(
|
]).then(
|
||||||
([
|
([
|
||||||
serverCapabilitiesResult,
|
serverCapabilitiesResult,
|
||||||
zapretRuntimeResult,
|
zapretRuntimeResult,
|
||||||
|
zapret2RuntimeResult,
|
||||||
byedpiRuntimeResult,
|
byedpiRuntimeResult,
|
||||||
inboundsConfigResult,
|
inboundsConfigResult,
|
||||||
]) => {
|
]) => {
|
||||||
@@ -196,6 +207,10 @@ const EntryPoint = {
|
|||||||
zapretRuntimeResult.status === "fulfilled"
|
zapretRuntimeResult.status === "fulfilled"
|
||||||
? zapretRuntimeResult.value
|
? zapretRuntimeResult.value
|
||||||
: null;
|
: null;
|
||||||
|
const zapret2Runtime =
|
||||||
|
zapret2RuntimeResult.status === "fulfilled"
|
||||||
|
? zapret2RuntimeResult.value
|
||||||
|
: null;
|
||||||
const byedpiRuntime =
|
const byedpiRuntime =
|
||||||
byedpiRuntimeResult.status === "fulfilled"
|
byedpiRuntimeResult.status === "fulfilled"
|
||||||
? byedpiRuntimeResult.value
|
? byedpiRuntimeResult.value
|
||||||
@@ -216,6 +231,11 @@ const EntryPoint = {
|
|||||||
Number(zapretRuntime.data?.zapret_installed) === 1
|
Number(zapretRuntime.data?.zapret_installed) === 1
|
||||||
? 1
|
? 1
|
||||||
: 0,
|
: 0,
|
||||||
|
zapret2_installed:
|
||||||
|
zapret2Runtime?.success &&
|
||||||
|
Number(zapret2Runtime.data?.zapret2_installed) === 1
|
||||||
|
? 1
|
||||||
|
: 0,
|
||||||
byedpi_installed:
|
byedpi_installed:
|
||||||
byedpiRuntime?.success &&
|
byedpiRuntime?.success &&
|
||||||
Number(byedpiRuntime.data?.byedpi_installed) === 1
|
Number(byedpiRuntime.data?.byedpi_installed) === 1
|
||||||
|
|||||||
@@ -49,12 +49,17 @@ const ZAPRET_LEGACY_DEFAULT_NFQWS_OPT =
|
|||||||
const ZAPRET_DEFAULT_NFQWS_OPT =
|
const ZAPRET_DEFAULT_NFQWS_OPT =
|
||||||
"--filter-tcp=80 --dpi-desync=fake,fakedsplit --dpi-desync-autottl=2 --dpi-desync-fooling=badsum --new --filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-repeats=11 --dpi-desync-fooling=badsum --dpi-desync-fake-tls-mod=rnd,dupsid,sni=www.google.com --new --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin";
|
"--filter-tcp=80 --dpi-desync=fake,fakedsplit --dpi-desync-autottl=2 --dpi-desync-fooling=badsum --new --filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-repeats=11 --dpi-desync-fooling=badsum --dpi-desync-fake-tls-mod=rnd,dupsid,sni=www.google.com --new --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin";
|
||||||
|
|
||||||
|
const ZAPRET2_DEFAULT_NFQWS2_OPT =
|
||||||
|
"--filter-tcp=80 --filter-l7=http --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 --new --filter-tcp=443 --filter-l7=tls --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld --new --filter-udp=443 --filter-l7=quic --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6";
|
||||||
|
|
||||||
const BYEDPI_DEFAULT_CMD_OPTS = "-o 2 --auto=t,r,a,s -d 2";
|
const BYEDPI_DEFAULT_CMD_OPTS = "-o 2 --auto=t,r,a,s -d 2";
|
||||||
const ANNOTATED_TEXTAREA_STYLE_ID = "pdk-annotated-textarea-styles";
|
const ANNOTATED_TEXTAREA_STYLE_ID = "pdk-annotated-textarea-styles";
|
||||||
const NFQWS_REMOTE_VALIDATION_DEBOUNCE_MS = 500;
|
const NFQWS_REMOTE_VALIDATION_DEBOUNCE_MS = 500;
|
||||||
const NFQWS_VALIDATION_COMMAND = "/usr/bin/podkop-plus";
|
const NFQWS_VALIDATION_COMMAND = "/usr/bin/podkop-plus";
|
||||||
const nfqwsRemoteValidationCache = new Map();
|
const nfqwsRemoteValidationCache = new Map();
|
||||||
const nfqwsRemoteValidationInflight = new Map();
|
const nfqwsRemoteValidationInflight = new Map();
|
||||||
|
const nfqws2RemoteValidationCache = new Map();
|
||||||
|
const nfqws2RemoteValidationInflight = new Map();
|
||||||
const byedpiRemoteValidationCache = new Map();
|
const byedpiRemoteValidationCache = new Map();
|
||||||
const byedpiRemoteValidationInflight = new Map();
|
const byedpiRemoteValidationInflight = new Map();
|
||||||
const BYEDPI_LONG_VALUE_OPTIONS = new Set([
|
const BYEDPI_LONG_VALUE_OPTIONS = new Set([
|
||||||
@@ -245,9 +250,70 @@ const NFQWS_REQUIRED_ARG_OPTIONS = new Set([
|
|||||||
"--wssize-cutoff",
|
"--wssize-cutoff",
|
||||||
"--wssize-forced-cutoff",
|
"--wssize-forced-cutoff",
|
||||||
]);
|
]);
|
||||||
|
const NFQWS2_OPTIONAL_ARG_OPTIONS = new Set([
|
||||||
|
"--chdir",
|
||||||
|
"--comment",
|
||||||
|
"--ctrack-disable",
|
||||||
|
"--debug",
|
||||||
|
"--hostlist-auto-retrans-reset",
|
||||||
|
"--intercept",
|
||||||
|
"--ipcache-hostname",
|
||||||
|
"--new",
|
||||||
|
"--payload-disable",
|
||||||
|
"--reasm-disable",
|
||||||
|
"--server",
|
||||||
|
"--template",
|
||||||
|
"--writeable",
|
||||||
|
]);
|
||||||
|
const NFQWS2_NO_ARG_OPTIONS = new Set([
|
||||||
|
"--bind-fix4",
|
||||||
|
"--bind-fix6",
|
||||||
|
"--daemon",
|
||||||
|
"--dry-run",
|
||||||
|
"--skip",
|
||||||
|
"--version",
|
||||||
|
]);
|
||||||
|
const NFQWS2_REQUIRED_ARG_OPTIONS = new Set([
|
||||||
|
"--blob",
|
||||||
|
"--cookie",
|
||||||
|
"--ctrack-timeouts",
|
||||||
|
"--filter-l3",
|
||||||
|
"--filter-l7",
|
||||||
|
"--filter-tcp",
|
||||||
|
"--filter-udp",
|
||||||
|
"--fwmark",
|
||||||
|
"--fuzz",
|
||||||
|
"--hostlist",
|
||||||
|
"--hostlist-auto",
|
||||||
|
"--hostlist-auto-debug",
|
||||||
|
"--hostlist-auto-fail-threshold",
|
||||||
|
"--hostlist-auto-fail-time",
|
||||||
|
"--hostlist-auto-retrans-threshold",
|
||||||
|
"--hostlist-domains",
|
||||||
|
"--hostlist-exclude",
|
||||||
|
"--hostlist-exclude-domains",
|
||||||
|
"--import",
|
||||||
|
"--in-range",
|
||||||
|
"--ipcache-lifetime",
|
||||||
|
"--ipset",
|
||||||
|
"--ipset-exclude",
|
||||||
|
"--ipset-exclude-ip",
|
||||||
|
"--ipset-ip",
|
||||||
|
"--lua-gc",
|
||||||
|
"--lua-init",
|
||||||
|
"--lua-desync",
|
||||||
|
"--name",
|
||||||
|
"--out-range",
|
||||||
|
"--payload",
|
||||||
|
"--pidfile",
|
||||||
|
"--qnum",
|
||||||
|
"--uid",
|
||||||
|
"--user",
|
||||||
|
]);
|
||||||
const actionProvidersAvailabilityState = {
|
const actionProvidersAvailabilityState = {
|
||||||
loaded: false,
|
loaded: false,
|
||||||
zapretInstalled: false,
|
zapretInstalled: false,
|
||||||
|
zapret2Installed: false,
|
||||||
byedpiInstalled: false,
|
byedpiInstalled: false,
|
||||||
};
|
};
|
||||||
let actionProvidersAvailabilityPromise = null;
|
let actionProvidersAvailabilityPromise = null;
|
||||||
@@ -275,6 +341,12 @@ function updateActionProvidersAvailabilityState(nextState) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof nextState.zapret2Installed !== "undefined") {
|
||||||
|
actionProvidersAvailabilityState.zapret2Installed = Boolean(
|
||||||
|
nextState.zapret2Installed,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof nextState.byedpiInstalled !== "undefined") {
|
if (typeof nextState.byedpiInstalled !== "undefined") {
|
||||||
actionProvidersAvailabilityState.byedpiInstalled = Boolean(
|
actionProvidersAvailabilityState.byedpiInstalled = Boolean(
|
||||||
nextState.byedpiInstalled,
|
nextState.byedpiInstalled,
|
||||||
@@ -291,6 +363,7 @@ function updateActionProvidersAvailabilityFromSystemInfo(systemInfo) {
|
|||||||
|
|
||||||
updateActionProvidersAvailabilityState({
|
updateActionProvidersAvailabilityState({
|
||||||
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
zapretInstalled: Boolean(systemInfo.zapret_installed),
|
||||||
|
zapret2Installed: Boolean(systemInfo.zapret2_installed),
|
||||||
byedpiInstalled: Boolean(systemInfo.byedpi_installed),
|
byedpiInstalled: Boolean(systemInfo.byedpi_installed),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -468,6 +541,7 @@ function ensureActionProvidersAvailabilityLoaded() {
|
|||||||
.then((capabilities) => {
|
.then((capabilities) => {
|
||||||
updateActionProvidersAvailabilityState({
|
updateActionProvidersAvailabilityState({
|
||||||
zapretInstalled: Boolean(capabilities?.zapretInstalled),
|
zapretInstalled: Boolean(capabilities?.zapretInstalled),
|
||||||
|
zapret2Installed: Boolean(capabilities?.zapret2Installed),
|
||||||
byedpiInstalled: Boolean(capabilities?.byedpiInstalled),
|
byedpiInstalled: Boolean(capabilities?.byedpiInstalled),
|
||||||
});
|
});
|
||||||
return actionProvidersAvailabilityState;
|
return actionProvidersAvailabilityState;
|
||||||
@@ -486,13 +560,18 @@ function ensureActionProvidersAvailabilityLoaded() {
|
|||||||
|
|
||||||
actionProvidersAvailabilityPromise = Promise.allSettled([
|
actionProvidersAvailabilityPromise = Promise.allSettled([
|
||||||
main.PodkopShellMethods.checkZapretRuntime(),
|
main.PodkopShellMethods.checkZapretRuntime(),
|
||||||
|
main.PodkopShellMethods.checkZapret2Runtime(),
|
||||||
main.PodkopShellMethods.checkByedpiRuntime(),
|
main.PodkopShellMethods.checkByedpiRuntime(),
|
||||||
])
|
])
|
||||||
.then(([zapretResult, byedpiResult]) => {
|
.then(([zapretResult, zapret2Result, byedpiResult]) => {
|
||||||
const zapret =
|
const zapret =
|
||||||
zapretResult && zapretResult.status === "fulfilled"
|
zapretResult && zapretResult.status === "fulfilled"
|
||||||
? zapretResult.value
|
? zapretResult.value
|
||||||
: null;
|
: null;
|
||||||
|
const zapret2 =
|
||||||
|
zapret2Result && zapret2Result.status === "fulfilled"
|
||||||
|
? zapret2Result.value
|
||||||
|
: null;
|
||||||
const byedpi =
|
const byedpi =
|
||||||
byedpiResult && byedpiResult.status === "fulfilled"
|
byedpiResult && byedpiResult.status === "fulfilled"
|
||||||
? byedpiResult.value
|
? byedpiResult.value
|
||||||
@@ -500,22 +579,23 @@ function ensureActionProvidersAvailabilityLoaded() {
|
|||||||
|
|
||||||
actionProvidersAvailabilityState.loaded = true;
|
actionProvidersAvailabilityState.loaded = true;
|
||||||
actionProvidersAvailabilityState.zapretInstalled = Boolean(
|
actionProvidersAvailabilityState.zapretInstalled = Boolean(
|
||||||
zapret &&
|
zapret && zapret.success && zapret.data && zapret.data.zapret_installed,
|
||||||
zapret.success &&
|
);
|
||||||
zapret.data &&
|
actionProvidersAvailabilityState.zapret2Installed = Boolean(
|
||||||
zapret.data.zapret_installed,
|
zapret2 &&
|
||||||
|
zapret2.success &&
|
||||||
|
zapret2.data &&
|
||||||
|
zapret2.data.zapret2_installed,
|
||||||
);
|
);
|
||||||
actionProvidersAvailabilityState.byedpiInstalled = Boolean(
|
actionProvidersAvailabilityState.byedpiInstalled = Boolean(
|
||||||
byedpi &&
|
byedpi && byedpi.success && byedpi.data && byedpi.data.byedpi_installed,
|
||||||
byedpi.success &&
|
|
||||||
byedpi.data &&
|
|
||||||
byedpi.data.byedpi_installed,
|
|
||||||
);
|
);
|
||||||
return actionProvidersAvailabilityState;
|
return actionProvidersAvailabilityState;
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
actionProvidersAvailabilityState.loaded = true;
|
actionProvidersAvailabilityState.loaded = true;
|
||||||
actionProvidersAvailabilityState.zapretInstalled = false;
|
actionProvidersAvailabilityState.zapretInstalled = false;
|
||||||
|
actionProvidersAvailabilityState.zapret2Installed = false;
|
||||||
actionProvidersAvailabilityState.byedpiInstalled = false;
|
actionProvidersAvailabilityState.byedpiInstalled = false;
|
||||||
return actionProvidersAvailabilityState;
|
return actionProvidersAvailabilityState;
|
||||||
})
|
})
|
||||||
@@ -530,6 +610,10 @@ function isZapretInstalledForUi() {
|
|||||||
return actionProvidersAvailabilityState.zapretInstalled;
|
return actionProvidersAvailabilityState.zapretInstalled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isZapret2InstalledForUi() {
|
||||||
|
return actionProvidersAvailabilityState.zapret2Installed;
|
||||||
|
}
|
||||||
|
|
||||||
function isByedpiInstalledForUi() {
|
function isByedpiInstalledForUi() {
|
||||||
return actionProvidersAvailabilityState.byedpiInstalled;
|
return actionProvidersAvailabilityState.byedpiInstalled;
|
||||||
}
|
}
|
||||||
@@ -553,6 +637,8 @@ function getActionOptionLabel(action) {
|
|||||||
return "VPN";
|
return "VPN";
|
||||||
case "zapret":
|
case "zapret":
|
||||||
return "Zapret";
|
return "Zapret";
|
||||||
|
case "zapret2":
|
||||||
|
return "Zapret2";
|
||||||
case "byedpi":
|
case "byedpi":
|
||||||
return "ByeDPI";
|
return "ByeDPI";
|
||||||
case "outbound":
|
case "outbound":
|
||||||
@@ -570,6 +656,10 @@ function getRuleActionDisplayValue(section_id) {
|
|||||||
return "Zapret";
|
return "Zapret";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action === "zapret2") {
|
||||||
|
return "Zapret2";
|
||||||
|
}
|
||||||
|
|
||||||
if (action === "byedpi") {
|
if (action === "byedpi") {
|
||||||
return "ByeDPI";
|
return "ByeDPI";
|
||||||
}
|
}
|
||||||
@@ -592,6 +682,9 @@ function populateActionOptionValues(option) {
|
|||||||
if (isZapretInstalledForUi()) {
|
if (isZapretInstalledForUi()) {
|
||||||
option.value("zapret", getActionOptionLabel("zapret"));
|
option.value("zapret", getActionOptionLabel("zapret"));
|
||||||
}
|
}
|
||||||
|
if (isZapret2InstalledForUi()) {
|
||||||
|
option.value("zapret2", getActionOptionLabel("zapret2"));
|
||||||
|
}
|
||||||
if (isByedpiInstalledForUi()) {
|
if (isByedpiInstalledForUi()) {
|
||||||
option.value("byedpi", getActionOptionLabel("byedpi"));
|
option.value("byedpi", getActionOptionLabel("byedpi"));
|
||||||
}
|
}
|
||||||
@@ -1237,6 +1330,54 @@ function attachNfqwsRemoteValidation(option, section_id, textarea) {
|
|||||||
scheduleValidation(0);
|
scheduleValidation(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function attachNfqws2RemoteValidation(option, section_id, textarea) {
|
||||||
|
if (!textarea || textarea.__podkopNfqws2RemoteValidationAttached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea.__podkopNfqws2RemoteValidationAttached = true;
|
||||||
|
textarea.__podkopNfqws2RemoteValidationRequestId = 0;
|
||||||
|
textarea.__podkopNfqws2RemoteValidationTimer = null;
|
||||||
|
|
||||||
|
const runValidation = () => {
|
||||||
|
const value = textarea.value;
|
||||||
|
const localAnalysis = buildNfqws2LocalAnalysis(value);
|
||||||
|
if (!localAnalysis.valid) {
|
||||||
|
refreshAnnotatedTextareaValidation(option, section_id, textarea);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestId =
|
||||||
|
(textarea.__podkopNfqws2RemoteValidationRequestId || 0) + 1;
|
||||||
|
textarea.__podkopNfqws2RemoteValidationRequestId = requestId;
|
||||||
|
|
||||||
|
validateNfqws2StrategyRemotely(value).then(() => {
|
||||||
|
if (textarea.__podkopNfqws2RemoteValidationRequestId !== requestId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshAnnotatedTextareaValidation(option, section_id, textarea);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const scheduleValidation = (delay = NFQWS_REMOTE_VALIDATION_DEBOUNCE_MS) => {
|
||||||
|
if (textarea.__podkopNfqws2RemoteValidationTimer) {
|
||||||
|
window.clearTimeout(textarea.__podkopNfqws2RemoteValidationTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea.__podkopNfqws2RemoteValidationTimer = window.setTimeout(() => {
|
||||||
|
textarea.__podkopNfqws2RemoteValidationTimer = null;
|
||||||
|
runValidation();
|
||||||
|
}, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
textarea.addEventListener("input", () => scheduleValidation());
|
||||||
|
textarea.addEventListener("change", () => scheduleValidation(0));
|
||||||
|
textarea.addEventListener("blur", () => scheduleValidation(0));
|
||||||
|
|
||||||
|
scheduleValidation(0);
|
||||||
|
}
|
||||||
|
|
||||||
function parseCommentAwareListTokens(value) {
|
function parseCommentAwareListTokens(value) {
|
||||||
const text = value ? `${value}` : "";
|
const text = value ? `${value}` : "";
|
||||||
const tokens = [];
|
const tokens = [];
|
||||||
@@ -1392,6 +1533,22 @@ function getNfqwsOptionArgumentMode(option) {
|
|||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNfqws2OptionArgumentMode(option) {
|
||||||
|
if (NFQWS2_REQUIRED_ARG_OPTIONS.has(option)) {
|
||||||
|
return "required";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NFQWS2_OPTIONAL_ARG_OPTIONS.has(option)) {
|
||||||
|
return "optional";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NFQWS2_NO_ARG_OPTIONS.has(option)) {
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeNfqwsStrategyWhitespace(value) {
|
function normalizeNfqwsStrategyWhitespace(value) {
|
||||||
return value ? `${value}`.replace(/\s+/g, " ").trim() : "";
|
return value ? `${value}`.replace(/\s+/g, " ").trim() : "";
|
||||||
}
|
}
|
||||||
@@ -1863,6 +2020,414 @@ function analyzeNfqwsStrategy(value) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeNfqws2StrategyValue(value) {
|
||||||
|
const normalized = normalizeNfqwsStrategyWhitespace(value);
|
||||||
|
return normalized.length ? normalized : ZAPRET2_DEFAULT_NFQWS2_OPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCachedNfqws2RemoteValidation(value) {
|
||||||
|
const normalized = normalizeNfqws2StrategyValue(value);
|
||||||
|
return normalized.length
|
||||||
|
? nfqws2RemoteValidationCache.get(normalized) || null
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cacheNfqws2RemoteValidation(value, result) {
|
||||||
|
const normalized = normalizeNfqws2StrategyValue(value);
|
||||||
|
if (!normalized.length) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cached = {
|
||||||
|
valid: result && result.valid === true,
|
||||||
|
message: result && result.message ? `${result.message}` : "",
|
||||||
|
needle: result && result.needle ? `${result.needle}` : "",
|
||||||
|
needles:
|
||||||
|
result && Array.isArray(result.needles)
|
||||||
|
? result.needles.filter(Boolean).map((item) => `${item}`)
|
||||||
|
: result && result.needle
|
||||||
|
? [`${result.needle}`]
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
nfqws2RemoteValidationCache.set(normalized, cached);
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildNfqws2RemoteValidationFallback(error) {
|
||||||
|
const message =
|
||||||
|
error && error.message
|
||||||
|
? `${error.message}`
|
||||||
|
: _("Unable to validate the NFQWS2 strategy through the backend parser.");
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("Backend validation failed: %s").format(message),
|
||||||
|
needle: "",
|
||||||
|
needles: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateNfqws2StrategyRemotely(value) {
|
||||||
|
const normalized = normalizeNfqws2StrategyValue(value);
|
||||||
|
|
||||||
|
if (!normalized.length) {
|
||||||
|
return Promise.resolve({
|
||||||
|
valid: true,
|
||||||
|
message: "",
|
||||||
|
needle: "",
|
||||||
|
needles: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfqws2RemoteValidationCache.has(normalized)) {
|
||||||
|
return Promise.resolve(nfqws2RemoteValidationCache.get(normalized));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nfqws2RemoteValidationInflight.has(normalized)) {
|
||||||
|
return nfqws2RemoteValidationInflight.get(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
const validationTask = fs
|
||||||
|
.exec(NFQWS_VALIDATION_COMMAND, [
|
||||||
|
"validate_nfqws2_strategy_json",
|
||||||
|
normalized,
|
||||||
|
])
|
||||||
|
.then((result) => {
|
||||||
|
const payload = JSON.parse(
|
||||||
|
(result && result.stdout ? result.stdout : "{}").trim() || "{}",
|
||||||
|
);
|
||||||
|
return cacheNfqws2RemoteValidation(normalized, {
|
||||||
|
valid: payload.valid === true,
|
||||||
|
message: payload.message || "",
|
||||||
|
needle: payload.needle || "",
|
||||||
|
needles: Array.isArray(payload.needles)
|
||||||
|
? payload.needles.filter(Boolean)
|
||||||
|
: payload.needle
|
||||||
|
? [payload.needle]
|
||||||
|
: [],
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) =>
|
||||||
|
cacheNfqws2RemoteValidation(
|
||||||
|
normalized,
|
||||||
|
buildNfqws2RemoteValidationFallback(error),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.finally(() => {
|
||||||
|
nfqws2RemoteValidationInflight.delete(normalized);
|
||||||
|
});
|
||||||
|
|
||||||
|
nfqws2RemoteValidationInflight.set(normalized, validationTask);
|
||||||
|
return validationTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNfqws2ForbiddenTokenInfo(token, index, nextToken) {
|
||||||
|
const configFileMessage = _(
|
||||||
|
"External nfqws2 config files bypass Podkop Plus queue management and explicit validation.",
|
||||||
|
);
|
||||||
|
const hostSelectionMessage = _(
|
||||||
|
"Resource selection by hostname inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE.",
|
||||||
|
);
|
||||||
|
const ipSelectionMessage = _(
|
||||||
|
"Resource selection by IP or CIDR inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE.",
|
||||||
|
);
|
||||||
|
const placeholderMessage = _(
|
||||||
|
"Zapret2 hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS2 strategies.",
|
||||||
|
);
|
||||||
|
const queueMessage = _(
|
||||||
|
"The NFQUEUE number is assigned by Podkop Plus for each rule and must not be overridden here.",
|
||||||
|
);
|
||||||
|
const fwmarkMessage = _(
|
||||||
|
"The desync fwmark is managed by Podkop Plus for loop prevention and must not be overridden here.",
|
||||||
|
);
|
||||||
|
const fuzzMessage = _(
|
||||||
|
"Fuzzing is not supported here because Podkop Plus needs deterministic runtime validation.",
|
||||||
|
);
|
||||||
|
const interceptMessage = _(
|
||||||
|
"Disabling interception is incompatible with action=zapret2 because Podkop Plus sends matched traffic through NFQUEUE.",
|
||||||
|
);
|
||||||
|
const daemonMessage = _(
|
||||||
|
"Podkop Plus manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here.",
|
||||||
|
);
|
||||||
|
const dryRunMessage = _(
|
||||||
|
"This field must start a working nfqws2 strategy; --dry-run exits immediately and is not allowed here.",
|
||||||
|
);
|
||||||
|
const versionMessage = _(
|
||||||
|
"This field must start a working nfqws2 strategy; --version exits immediately and is not allowed here.",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (index === 0 && (token.startsWith("@") || token.startsWith("$"))) {
|
||||||
|
return {
|
||||||
|
reason: configFileMessage,
|
||||||
|
captureNextValue: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "<HOSTLIST>" || token === "<HOSTLIST_NOAUTO>") {
|
||||||
|
return {
|
||||||
|
reason: placeholderMessage,
|
||||||
|
captureNextValue: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
token === "--hostlist" ||
|
||||||
|
token.startsWith("--hostlist=") ||
|
||||||
|
token === "--hostlist-domains" ||
|
||||||
|
token.startsWith("--hostlist-domains=") ||
|
||||||
|
token === "--hostlist-exclude" ||
|
||||||
|
token.startsWith("--hostlist-exclude=") ||
|
||||||
|
token === "--hostlist-exclude-domains" ||
|
||||||
|
token.startsWith("--hostlist-exclude-domains=") ||
|
||||||
|
token === "--hostlist-auto" ||
|
||||||
|
token.startsWith("--hostlist-auto=") ||
|
||||||
|
token === "--hostlist-auto-fail-threshold" ||
|
||||||
|
token.startsWith("--hostlist-auto-fail-threshold=") ||
|
||||||
|
token === "--hostlist-auto-fail-time" ||
|
||||||
|
token.startsWith("--hostlist-auto-fail-time=") ||
|
||||||
|
token === "--hostlist-auto-retrans-threshold" ||
|
||||||
|
token.startsWith("--hostlist-auto-retrans-threshold=") ||
|
||||||
|
token === "--hostlist-auto-debug" ||
|
||||||
|
token.startsWith("--hostlist-auto-debug=") ||
|
||||||
|
token === "--hostlist-auto-retrans-reset" ||
|
||||||
|
token.startsWith("--hostlist-auto-retrans-reset=")
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
reason: hostSelectionMessage,
|
||||||
|
captureNextValue: !token.includes("="),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
token === "--ipset" ||
|
||||||
|
token.startsWith("--ipset=") ||
|
||||||
|
token === "--ipset-ip" ||
|
||||||
|
token.startsWith("--ipset-ip=") ||
|
||||||
|
token === "--ipset-exclude" ||
|
||||||
|
token.startsWith("--ipset-exclude=") ||
|
||||||
|
token === "--ipset-exclude-ip" ||
|
||||||
|
token.startsWith("--ipset-exclude-ip=")
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
reason: ipSelectionMessage,
|
||||||
|
captureNextValue: !token.includes("="),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "--qnum" || token.startsWith("--qnum=")) {
|
||||||
|
return {
|
||||||
|
reason: queueMessage,
|
||||||
|
captureNextValue: !token.includes("="),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
token === "--fwmark" ||
|
||||||
|
token.startsWith("--fwmark=") ||
|
||||||
|
token === "--dpi-desync-fwmark" ||
|
||||||
|
token.startsWith("--dpi-desync-fwmark=")
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
reason: fwmarkMessage,
|
||||||
|
captureNextValue: !token.includes("="),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "--fuzz" || token.startsWith("--fuzz=")) {
|
||||||
|
return {
|
||||||
|
reason: fuzzMessage,
|
||||||
|
captureNextValue: !token.includes("="),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
token === "--intercept=0" ||
|
||||||
|
token === "--intercept=false" ||
|
||||||
|
token === "--intercept=no" ||
|
||||||
|
(token === "--intercept" && nextToken && nextToken.value === "0")
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
reason: interceptMessage,
|
||||||
|
captureNextValue: token === "--intercept",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "--daemon") {
|
||||||
|
return {
|
||||||
|
reason: daemonMessage,
|
||||||
|
captureNextValue: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "--dry-run") {
|
||||||
|
return {
|
||||||
|
reason: dryRunMessage,
|
||||||
|
captureNextValue: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token === "--version") {
|
||||||
|
return {
|
||||||
|
reason: versionMessage,
|
||||||
|
captureNextValue: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildNfqws2LocalAnalysis(value) {
|
||||||
|
const text = value ? `${value}` : "";
|
||||||
|
if (!text.trim().length) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: _("NFQWS2 strategy cannot be empty"),
|
||||||
|
annotations: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const tokens = parseNfqwsRuntimeTokens(text);
|
||||||
|
const annotationMap = new Map();
|
||||||
|
const errors = [];
|
||||||
|
|
||||||
|
for (let index = 0; index < tokens.length; ) {
|
||||||
|
const token = tokens[index];
|
||||||
|
const bareToken = token.value.includes("=")
|
||||||
|
? token.value.slice(0, token.value.indexOf("="))
|
||||||
|
: token.value;
|
||||||
|
const nextToken = tokens[index + 1] || null;
|
||||||
|
|
||||||
|
const forbidden = getNfqws2ForbiddenTokenInfo(
|
||||||
|
token.value,
|
||||||
|
index,
|
||||||
|
nextToken,
|
||||||
|
);
|
||||||
|
if (forbidden) {
|
||||||
|
addAnnotationIssue(annotationMap, token, forbidden.reason);
|
||||||
|
|
||||||
|
let displayToken = token.value;
|
||||||
|
|
||||||
|
if (
|
||||||
|
forbidden.captureNextValue &&
|
||||||
|
nextToken &&
|
||||||
|
!nextToken.value.startsWith("--")
|
||||||
|
) {
|
||||||
|
addAnnotationIssue(annotationMap, nextToken, forbidden.reason);
|
||||||
|
displayToken = `${displayToken} ${nextToken.value}`;
|
||||||
|
index += 2;
|
||||||
|
} else {
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
errors.push(`${displayToken}: ${forbidden.reason}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token.value.startsWith("--")) {
|
||||||
|
const reason = _(
|
||||||
|
"Unexpected standalone token. Use explicit flags such as --name or --name=value.",
|
||||||
|
);
|
||||||
|
addAnnotationIssue(annotationMap, token, reason);
|
||||||
|
errors.push(`${token.value}: ${reason}`);
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mode = getNfqws2OptionArgumentMode(bareToken);
|
||||||
|
if (mode === "unknown") {
|
||||||
|
const reason = _("Unknown NFQWS2 flag.");
|
||||||
|
addAnnotationIssue(annotationMap, token, reason);
|
||||||
|
errors.push(`${token.value}: ${reason}`);
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === "none") {
|
||||||
|
if (token.value.includes("=")) {
|
||||||
|
const reason = _("This flag does not accept a value.");
|
||||||
|
addAnnotationIssue(annotationMap, token, reason);
|
||||||
|
errors.push(`${token.value}: ${reason}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode === "optional") {
|
||||||
|
if (
|
||||||
|
nextToken &&
|
||||||
|
!token.value.includes("=") &&
|
||||||
|
!nextToken.value.startsWith("--")
|
||||||
|
) {
|
||||||
|
const reason = _(
|
||||||
|
"Optional values must be attached with '=' here; a separate token would be ignored by nfqws2.",
|
||||||
|
);
|
||||||
|
addAnnotationIssue(annotationMap, token, reason);
|
||||||
|
addAnnotationIssue(annotationMap, nextToken, reason);
|
||||||
|
errors.push(`${token.value} ${nextToken.value}: ${reason}`);
|
||||||
|
index += 2;
|
||||||
|
} else {
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!token.value.includes("=")) {
|
||||||
|
if (!nextToken || nextToken.value.startsWith("--")) {
|
||||||
|
const reason = _("This option requires a value.");
|
||||||
|
addAnnotationIssue(annotationMap, token, reason);
|
||||||
|
errors.push(`${token.value}: ${reason}`);
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errors.length) {
|
||||||
|
return { valid: true, message: "", annotations: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: [getValidationHeaderText(), ...errors].join("\n"),
|
||||||
|
annotations: finalizeAnnotations(annotationMap),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function analyzeNfqws2Strategy(value) {
|
||||||
|
const localAnalysis = buildNfqws2LocalAnalysis(value);
|
||||||
|
if (!localAnalysis.valid) {
|
||||||
|
return localAnalysis;
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteValidation = getCachedNfqws2RemoteValidation(value);
|
||||||
|
if (!remoteValidation || remoteValidation.valid) {
|
||||||
|
return localAnalysis;
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = value ? `${value}` : "";
|
||||||
|
const tokens = parseNfqwsRuntimeTokens(text);
|
||||||
|
const annotationMap = new Map();
|
||||||
|
|
||||||
|
localAnalysis.annotations.forEach((annotation) =>
|
||||||
|
addAnnotationIssue(annotationMap, annotation, annotation.message),
|
||||||
|
);
|
||||||
|
addNfqwsRemoteValidationAnnotations(annotationMap, tokens, remoteValidation);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
message: [getValidationHeaderText(), remoteValidation.message].join("\n"),
|
||||||
|
annotations: finalizeAnnotations(annotationMap),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeByedpiStrategyWhitespace(value) {
|
function normalizeByedpiStrategyWhitespace(value) {
|
||||||
return value ? `${value}`.replace(/\s+/g, " ").trim() : "";
|
return value ? `${value}`.replace(/\s+/g, " ").trim() : "";
|
||||||
}
|
}
|
||||||
@@ -2259,7 +2824,7 @@ function analyzeByedpiStrategy(value) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function configureTextareaOption(option, analyzer) {
|
function configureTextareaOption(option, analyzer, remoteValidationAttacher) {
|
||||||
const originalRenderWidget = option.renderWidget;
|
const originalRenderWidget = option.renderWidget;
|
||||||
|
|
||||||
option.renderWidget = function (section_id, option_index, cfgvalue) {
|
option.renderWidget = function (section_id, option_index, cfgvalue) {
|
||||||
@@ -2279,12 +2844,127 @@ function configureTextareaOption(option, analyzer) {
|
|||||||
if (typeof analyzer === "function") {
|
if (typeof analyzer === "function") {
|
||||||
attachAnnotatedTextarea(textarea, analyzer);
|
attachAnnotatedTextarea(textarea, analyzer);
|
||||||
}
|
}
|
||||||
|
if (typeof remoteValidationAttacher === "function") {
|
||||||
|
remoteValidationAttacher(this, section_id, textarea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getOptionTextarea(option, section_id) {
|
||||||
|
const field =
|
||||||
|
typeof option.map.findElement === "function"
|
||||||
|
? option.map.findElement("data-field", option.cbid(section_id))
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (field && typeof field.querySelector === "function") {
|
||||||
|
return field.querySelector("textarea");
|
||||||
|
}
|
||||||
|
|
||||||
|
const elem =
|
||||||
|
typeof option.getUIElement === "function"
|
||||||
|
? option.getUIElement(section_id)
|
||||||
|
: null;
|
||||||
|
const node = elem && elem.node ? elem.node : null;
|
||||||
|
|
||||||
|
if (node && node.nodeName === "TEXTAREA") {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node && typeof node.querySelector === "function"
|
||||||
|
? node.querySelector("textarea")
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rejectStrategyValidation(option, section_id, message) {
|
||||||
|
const title = option.stripTags(option.title).trim();
|
||||||
|
const error = message || option.getValidationError(section_id) || "";
|
||||||
|
|
||||||
|
return Promise.reject(
|
||||||
|
new TypeError(
|
||||||
|
`${_('Option "%s" contains an invalid input value.').format(title || option.option)} ${error}`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseStrategyWithRemoteValidation(section_id, config) {
|
||||||
|
const active = this.isActive(section_id);
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
if (typeof this.triggerValidation === "function") {
|
||||||
|
this.triggerValidation(section_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isValid(section_id)) {
|
||||||
|
return rejectStrategyValidation(
|
||||||
|
this,
|
||||||
|
section_id,
|
||||||
|
this.getValidationError(section_id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cval = this.cfgvalue(section_id);
|
||||||
|
const fval = this.formvalue(section_id);
|
||||||
|
const cvalString = cval == null ? "" : `${cval}`;
|
||||||
|
const fvalString = fval == null ? "" : `${fval}`;
|
||||||
|
const shouldWrite = this.forcewrite || cvalString !== fvalString;
|
||||||
|
|
||||||
|
if (!shouldWrite) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return config.remoteValidate(fvalString).then((result) => {
|
||||||
|
const textarea = getOptionTextarea(this, section_id);
|
||||||
|
|
||||||
|
if (textarea) {
|
||||||
|
refreshAnnotatedTextareaValidation(this, section_id, textarea);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof this.triggerValidation === "function") {
|
||||||
|
this.triggerValidation(section_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result || result.valid !== true) {
|
||||||
|
return rejectStrategyValidation(
|
||||||
|
this,
|
||||||
|
section_id,
|
||||||
|
result && result.message
|
||||||
|
? result.message
|
||||||
|
: config.invalidMessage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(this.write(section_id, fvalString));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.retain) {
|
||||||
|
return Promise.resolve(this.remove(section_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseNfqwsStrategyOnSave(section_id) {
|
||||||
|
return parseStrategyWithRemoteValidation.call(this, section_id, {
|
||||||
|
remoteValidate: validateNfqwsStrategyRemotely,
|
||||||
|
invalidMessage: _(
|
||||||
|
"Unable to validate the NFQWS strategy through the backend parser.",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseNfqws2StrategyOnSave(section_id) {
|
||||||
|
return parseStrategyWithRemoteValidation.call(this, section_id, {
|
||||||
|
remoteValidate: validateNfqws2StrategyRemotely,
|
||||||
|
invalidMessage: _(
|
||||||
|
"Unable to validate the NFQWS2 strategy through the backend parser.",
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function addDynamicConditionField(section, config) {
|
function addDynamicConditionField(section, config) {
|
||||||
const o = section.taboption(
|
const o = section.taboption(
|
||||||
"conditions",
|
"conditions",
|
||||||
@@ -2593,13 +3273,69 @@ function createSectionContent(section) {
|
|||||||
? ZAPRET_DEFAULT_NFQWS_OPT
|
? ZAPRET_DEFAULT_NFQWS_OPT
|
||||||
: normalized;
|
: normalized;
|
||||||
|
|
||||||
uci.set(UCI_PACKAGE, section_id, "nfqws_opt", nextValue);
|
return validateNfqwsStrategyRemotely(nextValue).then((result) => {
|
||||||
|
if (!result || result.valid !== true) {
|
||||||
|
throw new TypeError(
|
||||||
|
result && result.message
|
||||||
|
? result.message
|
||||||
|
: _(
|
||||||
|
"Unable to validate the NFQWS strategy through the backend parser.",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uci.set(UCI_PACKAGE, section_id, "nfqws_opt", nextValue);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
o.validate = function (_section_id, value) {
|
o.validate = function (_section_id, value) {
|
||||||
const analysis = analyzeNfqwsStrategy(value);
|
const analysis = analyzeNfqwsStrategy(value);
|
||||||
return analysis.valid ? true : analysis.message;
|
return analysis.valid ? true : analysis.message;
|
||||||
};
|
};
|
||||||
configureTextareaOption(o, analyzeNfqwsStrategy);
|
o.parse = parseNfqwsStrategyOnSave;
|
||||||
|
configureTextareaOption(o, analyzeNfqwsStrategy, attachNfqwsRemoteValidation);
|
||||||
|
|
||||||
|
o = section.taboption(
|
||||||
|
"settings",
|
||||||
|
form.TextValue,
|
||||||
|
"nfqws2_opt",
|
||||||
|
_("NFQWS2 Strategy"),
|
||||||
|
);
|
||||||
|
o.depends("action", "zapret2");
|
||||||
|
o.rows = 6;
|
||||||
|
o.wrap = "soft";
|
||||||
|
o.textarea = true;
|
||||||
|
o.modalonly = true;
|
||||||
|
o.load = function (section_id) {
|
||||||
|
return (
|
||||||
|
uci.get(UCI_PACKAGE, section_id, "nfqws2_opt") ||
|
||||||
|
ZAPRET2_DEFAULT_NFQWS2_OPT
|
||||||
|
);
|
||||||
|
};
|
||||||
|
o.write = function (section_id, value) {
|
||||||
|
const normalized = normalizeNfqws2StrategyValue(value);
|
||||||
|
|
||||||
|
return validateNfqws2StrategyRemotely(normalized).then((result) => {
|
||||||
|
if (!result || result.valid !== true) {
|
||||||
|
throw new TypeError(
|
||||||
|
result && result.message
|
||||||
|
? result.message
|
||||||
|
: _("Invalid NFQWS2 strategy"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uci.set(UCI_PACKAGE, section_id, "nfqws2_opt", normalized);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
o.validate = function (_section_id, value) {
|
||||||
|
const analysis = analyzeNfqws2Strategy(value);
|
||||||
|
return analysis.valid ? true : analysis.message;
|
||||||
|
};
|
||||||
|
o.parse = parseNfqws2StrategyOnSave;
|
||||||
|
configureTextareaOption(
|
||||||
|
o,
|
||||||
|
analyzeNfqws2Strategy,
|
||||||
|
attachNfqws2RemoteValidation,
|
||||||
|
);
|
||||||
|
|
||||||
o = section.taboption(
|
o = section.taboption(
|
||||||
"settings",
|
"settings",
|
||||||
@@ -3130,6 +3866,7 @@ function createSectionContent(section) {
|
|||||||
o.depends("action", "vpn");
|
o.depends("action", "vpn");
|
||||||
o.depends("action", "byedpi");
|
o.depends("action", "byedpi");
|
||||||
o.depends("action", "zapret");
|
o.depends("action", "zapret");
|
||||||
|
o.depends("action", "zapret2");
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
|
|
||||||
o = section.taboption(
|
o = section.taboption(
|
||||||
@@ -3145,6 +3882,7 @@ function createSectionContent(section) {
|
|||||||
o.depends({ action: "vpn", mixed_proxy_enabled: "1" });
|
o.depends({ action: "vpn", mixed_proxy_enabled: "1" });
|
||||||
o.depends({ action: "byedpi", mixed_proxy_enabled: "1" });
|
o.depends({ action: "byedpi", mixed_proxy_enabled: "1" });
|
||||||
o.depends({ action: "zapret", mixed_proxy_enabled: "1" });
|
o.depends({ action: "zapret", mixed_proxy_enabled: "1" });
|
||||||
|
o.depends({ action: "zapret2", mixed_proxy_enabled: "1" });
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
o.validate = function (_section_id, value) {
|
o.validate = function (_section_id, value) {
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
@@ -3173,6 +3911,7 @@ function createSectionContent(section) {
|
|||||||
o.depends({ action: "vpn", mixed_proxy_enabled: "1" });
|
o.depends({ action: "vpn", mixed_proxy_enabled: "1" });
|
||||||
o.depends({ action: "byedpi", mixed_proxy_enabled: "1" });
|
o.depends({ action: "byedpi", mixed_proxy_enabled: "1" });
|
||||||
o.depends({ action: "zapret", mixed_proxy_enabled: "1" });
|
o.depends({ action: "zapret", mixed_proxy_enabled: "1" });
|
||||||
|
o.depends({ action: "zapret2", mixed_proxy_enabled: "1" });
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
|
|
||||||
o = section.taboption(
|
o = section.taboption(
|
||||||
@@ -3207,6 +3946,11 @@ function createSectionContent(section) {
|
|||||||
mixed_proxy_enabled: "1",
|
mixed_proxy_enabled: "1",
|
||||||
mixed_proxy_auth_enabled: "1",
|
mixed_proxy_auth_enabled: "1",
|
||||||
});
|
});
|
||||||
|
o.depends({
|
||||||
|
action: "zapret2",
|
||||||
|
mixed_proxy_enabled: "1",
|
||||||
|
mixed_proxy_auth_enabled: "1",
|
||||||
|
});
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
o.validate = function (_section_id, value) {
|
o.validate = function (_section_id, value) {
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
@@ -3248,6 +3992,11 @@ function createSectionContent(section) {
|
|||||||
mixed_proxy_enabled: "1",
|
mixed_proxy_enabled: "1",
|
||||||
mixed_proxy_auth_enabled: "1",
|
mixed_proxy_auth_enabled: "1",
|
||||||
});
|
});
|
||||||
|
o.depends({
|
||||||
|
action: "zapret2",
|
||||||
|
mixed_proxy_enabled: "1",
|
||||||
|
mixed_proxy_auth_enabled: "1",
|
||||||
|
});
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
o.validate = function (_section_id, value) {
|
o.validate = function (_section_id, value) {
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ const ROUTING_SECTION_ACTIONS = [
|
|||||||
"vpn",
|
"vpn",
|
||||||
"byedpi",
|
"byedpi",
|
||||||
"zapret",
|
"zapret",
|
||||||
|
"zapret2",
|
||||||
"direct",
|
"direct",
|
||||||
"block",
|
"block",
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PODKOP PLUS\n"
|
"Project-Id-Version: PODKOP PLUS\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2026-06-02 17:11+0300\n"
|
"POT-Creation-Date: 2026-06-02 18:22+0300\n"
|
||||||
"PO-Revision-Date: 2026-06-02 17:11+0300\n"
|
"PO-Revision-Date: 2026-06-02 18:22+0300\n"
|
||||||
"Last-Translator: ushan0v\n"
|
"Last-Translator: ushan0v\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
"Language: ru\n"
|
"Language: ru\n"
|
||||||
@@ -299,6 +299,9 @@ msgstr "Отключить QUIC"
|
|||||||
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
msgid "Disable the QUIC protocol to improve compatibility or fix issues with video streaming"
|
||||||
msgstr "Отключить QUIC протокол для улучшения совместимости или исправления видео стриминга"
|
msgstr "Отключить QUIC протокол для улучшения совместимости или исправления видео стриминга"
|
||||||
|
|
||||||
|
msgid "Disabling interception is incompatible with action=zapret2 because Podkop Plus sends matched traffic through NFQUEUE."
|
||||||
|
msgstr "Отключение перехвата несовместимо с action=zapret2, потому что Podkop Plus отправляет совпавший трафик через NFQUEUE."
|
||||||
|
|
||||||
msgid "DNS on router"
|
msgid "DNS on router"
|
||||||
msgstr "DNS на роутере"
|
msgstr "DNS на роутере"
|
||||||
|
|
||||||
@@ -443,6 +446,9 @@ msgstr "Открыть эту секцию как локальный HTTP+SOCKS
|
|||||||
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
msgid "External nfqws config files bypass Podkop Plus queue management and explicit validation."
|
||||||
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Podkop Plus."
|
msgstr "Внешние конфиги nfqws обходят управление очередями и явную валидацию Podkop Plus."
|
||||||
|
|
||||||
|
msgid "External nfqws2 config files bypass Podkop Plus queue management and explicit validation."
|
||||||
|
msgstr "Внешние конфиги nfqws2 обходят управление очередями и явную валидацию Podkop Plus."
|
||||||
|
|
||||||
msgid "Failed to close connection"
|
msgid "Failed to close connection"
|
||||||
msgstr "Не удалось закрыть подключение"
|
msgstr "Не удалось закрыть подключение"
|
||||||
|
|
||||||
@@ -485,6 +491,9 @@ msgstr "Proxy protocol для фронтинга"
|
|||||||
msgid "Fully Routed IPs"
|
msgid "Fully Routed IPs"
|
||||||
msgstr "Полностью маршрутизированные IP-адреса"
|
msgstr "Полностью маршрутизированные IP-адреса"
|
||||||
|
|
||||||
|
msgid "Fuzzing is not supported here because Podkop Plus needs deterministic runtime validation."
|
||||||
|
msgstr "Fuzzing здесь не поддерживается, потому что Podkop Plus нужна предсказуемая runtime-валидация."
|
||||||
|
|
||||||
msgid "Generated inbound"
|
msgid "Generated inbound"
|
||||||
msgstr "Созданный inbound"
|
msgstr "Созданный inbound"
|
||||||
|
|
||||||
@@ -608,6 +617,9 @@ msgstr "Неверный IP-адрес"
|
|||||||
msgid "Invalid JSON format"
|
msgid "Invalid JSON format"
|
||||||
msgstr "Неверный формат JSON"
|
msgstr "Неверный формат JSON"
|
||||||
|
|
||||||
|
msgid "Invalid NFQWS2 strategy"
|
||||||
|
msgstr "Некорректная стратегия NFQWS2"
|
||||||
|
|
||||||
msgid "Invalid path format. Path must start with \"/\" and contain valid characters"
|
msgid "Invalid path format. Path must start with \"/\" and contain valid characters"
|
||||||
msgstr "Неверный формат пути. Путь должен начинаться с \"/\" и содержать допустимые символы"
|
msgstr "Неверный формат пути. Путь должен начинаться с \"/\" и содержать допустимые символы"
|
||||||
|
|
||||||
@@ -803,6 +815,12 @@ msgstr "Стратегия NFQWS"
|
|||||||
msgid "NFQWS strategy cannot be empty"
|
msgid "NFQWS strategy cannot be empty"
|
||||||
msgstr "Стратегия NFQWS не может быть пустой"
|
msgstr "Стратегия NFQWS не может быть пустой"
|
||||||
|
|
||||||
|
msgid "NFQWS2 Strategy"
|
||||||
|
msgstr "Стратегия NFQWS2"
|
||||||
|
|
||||||
|
msgid "NFQWS2 strategy cannot be empty"
|
||||||
|
msgstr "Стратегия NFQWS2 не может быть пустой"
|
||||||
|
|
||||||
msgid "No active connections"
|
msgid "No active connections"
|
||||||
msgstr "Нет активных подключений"
|
msgstr "Нет активных подключений"
|
||||||
|
|
||||||
@@ -827,6 +845,9 @@ msgstr "Нет правил, использующих ByeDPI"
|
|||||||
msgid "No rules use Zapret"
|
msgid "No rules use Zapret"
|
||||||
msgstr "Нет правил, использующих Zapret"
|
msgstr "Нет правил, использующих Zapret"
|
||||||
|
|
||||||
|
msgid "No rules use Zapret2"
|
||||||
|
msgstr "Нет правил, использующих Zapret2"
|
||||||
|
|
||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "Нет"
|
msgstr "Нет"
|
||||||
|
|
||||||
@@ -884,6 +905,9 @@ msgstr "Параметр \"%s\" содержит некорректное зна
|
|||||||
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws."
|
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws."
|
||||||
msgstr "Необязательное значение здесь нужно передавать только через '='; отдельный токен nfqws проигнорирует."
|
msgstr "Необязательное значение здесь нужно передавать только через '='; отдельный токен nfqws проигнорирует."
|
||||||
|
|
||||||
|
msgid "Optional values must be attached with '=' here; a separate token would be ignored by nfqws2."
|
||||||
|
msgstr "Необязательные значения здесь должны задаваться через '='; отдельный токен будет проигнорирован nfqws2."
|
||||||
|
|
||||||
msgid "Outbound JSON"
|
msgid "Outbound JSON"
|
||||||
msgstr "JSON outbound"
|
msgstr "JSON outbound"
|
||||||
|
|
||||||
@@ -938,6 +962,9 @@ msgstr "Podkop Plus сам управляет жизненным циклом ci
|
|||||||
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
msgid "Podkop Plus manages the nfqws process lifecycle itself, so daemon mode is not allowed here."
|
||||||
msgstr "Podkop Plus сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
msgstr "Podkop Plus сам управляет жизненным циклом nfqws, поэтому режим daemon здесь запрещён."
|
||||||
|
|
||||||
|
msgid "Podkop Plus manages the nfqws2 process lifecycle itself, so daemon mode is not allowed here."
|
||||||
|
msgstr "Podkop Plus сам управляет жизненным циклом nfqws2, поэтому режим daemon здесь запрещён."
|
||||||
|
|
||||||
msgid "Podkop Plus rules"
|
msgid "Podkop Plus rules"
|
||||||
msgstr "Правила Podkop Plus"
|
msgstr "Правила Podkop Plus"
|
||||||
|
|
||||||
@@ -968,6 +995,15 @@ msgstr "NFQWS Podkop Plus не запущен"
|
|||||||
msgid "Podkop Plus-managed nfqws runtime is ready"
|
msgid "Podkop Plus-managed nfqws runtime is ready"
|
||||||
msgstr "NFQWS Podkop Plus готов"
|
msgstr "NFQWS Podkop Plus готов"
|
||||||
|
|
||||||
|
msgid "Podkop Plus-managed nfqws2 runtime is not ready"
|
||||||
|
msgstr "NFQWS2 Podkop Plus не готов"
|
||||||
|
|
||||||
|
msgid "Podkop Plus-managed nfqws2 runtime is not running"
|
||||||
|
msgstr "NFQWS2 Podkop Plus не запущен"
|
||||||
|
|
||||||
|
msgid "Podkop Plus-managed nfqws2 runtime is ready"
|
||||||
|
msgstr "NFQWS2 Podkop Plus готов"
|
||||||
|
|
||||||
msgid "Port cannot be empty"
|
msgid "Port cannot be empty"
|
||||||
msgstr "Порт не может быть пустым"
|
msgstr "Порт не может быть пустым"
|
||||||
|
|
||||||
@@ -1052,9 +1088,15 @@ msgstr "Определять страны серверов через country.is
|
|||||||
msgid "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
msgid "Resource selection by hostname inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
msgstr "Выбор ресурсов по hostname внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
msgstr "Выбор ресурсов по hostname внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
||||||
|
|
||||||
|
msgid "Resource selection by hostname inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
|
msgstr "Выбор ресурсов по hostname внутри nfqws2 здесь не поддерживается; sing-box выбирает ресурсы до NFQUEUE."
|
||||||
|
|
||||||
msgid "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
msgid "Resource selection by IP or CIDR inside nfqws is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws здесь не поддерживается; ресурсы выбирает sing-box до NFQUEUE."
|
||||||
|
|
||||||
|
msgid "Resource selection by IP or CIDR inside nfqws2 is not supported here; sing-box selects resources before NFQUEUE."
|
||||||
|
msgstr "Выбор ресурсов по IP или CIDR внутри nfqws2 здесь не поддерживается; sing-box выбирает ресурсы до NFQUEUE."
|
||||||
|
|
||||||
msgid "Restart Podkop Plus"
|
msgid "Restart Podkop Plus"
|
||||||
msgstr "Перезапустить Podkop Plus"
|
msgstr "Перезапустить Podkop Plus"
|
||||||
|
|
||||||
@@ -1277,6 +1319,18 @@ msgstr "Отдельная служба Zapret активна"
|
|||||||
msgid "Standalone Zapret service is inactive"
|
msgid "Standalone Zapret service is inactive"
|
||||||
msgstr "Отдельная служба Zapret неактивна"
|
msgstr "Отдельная служба Zapret неактивна"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 autostart is enabled"
|
||||||
|
msgstr "Автозапуск отдельной службы Zapret2 включён"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 is active together with Podkop Plus Zapret2 rules"
|
||||||
|
msgstr "Отдельная служба Zapret2 активна вместе с правилами Zapret2 в Podkop Plus"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 service is active"
|
||||||
|
msgstr "Отдельная служба Zapret2 активна"
|
||||||
|
|
||||||
|
msgid "Standalone Zapret2 service is inactive"
|
||||||
|
msgstr "Отдельная служба Zapret2 неактивна"
|
||||||
|
|
||||||
msgid "Start Podkop Plus"
|
msgid "Start Podkop Plus"
|
||||||
msgstr "Запустить Podkop Plus"
|
msgstr "Запустить Podkop Plus"
|
||||||
|
|
||||||
@@ -1346,6 +1400,9 @@ msgstr "Есть правила, использующие ByeDPI"
|
|||||||
msgid "There are rules using Zapret"
|
msgid "There are rules using Zapret"
|
||||||
msgstr "Есть правила использующие Zapret"
|
msgstr "Есть правила использующие Zapret"
|
||||||
|
|
||||||
|
msgid "There are rules using Zapret2"
|
||||||
|
msgstr "Есть правила, использующие Zapret2"
|
||||||
|
|
||||||
msgid "This field is required"
|
msgid "This field is required"
|
||||||
msgstr "Заполните это поле"
|
msgstr "Заполните это поле"
|
||||||
|
|
||||||
@@ -1358,6 +1415,12 @@ msgstr "Это поле должно запускать рабочую стра
|
|||||||
msgid "This field must start a working nfqws strategy; --version exits immediately and is not allowed here."
|
msgid "This field must start a working nfqws strategy; --version exits immediately and is not allowed here."
|
||||||
msgstr "Это поле должно запускать рабочую стратегию nfqws; --version сразу завершает процесс и здесь запрещён."
|
msgstr "Это поле должно запускать рабочую стратегию nfqws; --version сразу завершает процесс и здесь запрещён."
|
||||||
|
|
||||||
|
msgid "This field must start a working nfqws2 strategy; --dry-run exits immediately and is not allowed here."
|
||||||
|
msgstr "Это поле должно запускать рабочую стратегию nfqws2; --dry-run сразу завершает работу и здесь запрещён."
|
||||||
|
|
||||||
|
msgid "This field must start a working nfqws2 strategy; --version exits immediately and is not allowed here."
|
||||||
|
msgstr "Это поле должно запускать рабочую стратегию nfqws2; --version сразу завершает работу и здесь запрещён."
|
||||||
|
|
||||||
msgid "This flag does not accept a value."
|
msgid "This flag does not accept a value."
|
||||||
msgstr "Этот флаг не принимает значение."
|
msgstr "Этот флаг не принимает значение."
|
||||||
|
|
||||||
@@ -1418,6 +1481,9 @@ msgstr "Не удалось проверить стратегию ByeDPI чер
|
|||||||
msgid "Unable to validate the NFQWS strategy through the backend parser."
|
msgid "Unable to validate the NFQWS strategy through the backend parser."
|
||||||
msgstr "Не удалось проверить стратегию NFQWS через backend-парсер."
|
msgstr "Не удалось проверить стратегию NFQWS через backend-парсер."
|
||||||
|
|
||||||
|
msgid "Unable to validate the NFQWS2 strategy through the backend parser."
|
||||||
|
msgstr "Не удалось проверить стратегию NFQWS2 через backend-парсер."
|
||||||
|
|
||||||
msgid "Unexpected ByeDPI strategy argument: %s"
|
msgid "Unexpected ByeDPI strategy argument: %s"
|
||||||
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
msgstr "Неожиданный аргумент стратегии ByeDPI: %s"
|
||||||
|
|
||||||
@@ -1427,6 +1493,9 @@ msgstr "Обнаружен лишний ciadpi Podkop Plus"
|
|||||||
msgid "Unexpected Podkop Plus-managed nfqws runtime is running"
|
msgid "Unexpected Podkop Plus-managed nfqws runtime is running"
|
||||||
msgstr "Обнаружен лишний NFQWS Podkop Plus"
|
msgstr "Обнаружен лишний NFQWS Podkop Plus"
|
||||||
|
|
||||||
|
msgid "Unexpected Podkop Plus-managed nfqws2 runtime is running"
|
||||||
|
msgstr "Обнаружен лишний NFQWS2 Podkop Plus"
|
||||||
|
|
||||||
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
msgid "Unexpected standalone token. Use explicit flags such as --name or --name=value."
|
||||||
msgstr "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
msgstr "Неожиданный отдельный токен. Используйте явные флаги вида --имя или --имя=значение."
|
||||||
|
|
||||||
@@ -1448,6 +1517,9 @@ msgstr "Неизвестная ошибка"
|
|||||||
msgid "Unknown NFQWS flag."
|
msgid "Unknown NFQWS flag."
|
||||||
msgstr "Неизвестный флаг NFQWS."
|
msgstr "Неизвестный флаг NFQWS."
|
||||||
|
|
||||||
|
msgid "Unknown NFQWS2 flag."
|
||||||
|
msgstr "Неизвестный флаг NFQWS2."
|
||||||
|
|
||||||
msgid "Unsupported security mode for this protocol"
|
msgid "Unsupported security mode for this protocol"
|
||||||
msgstr "Этот протокол не поддерживает выбранный режим защиты"
|
msgstr "Этот протокол не поддерживает выбранный режим защиты"
|
||||||
|
|
||||||
@@ -1591,3 +1663,30 @@ msgstr "Бинарник провайдера Zapret доступен"
|
|||||||
|
|
||||||
msgid "Zapret provider binary is not available"
|
msgid "Zapret provider binary is not available"
|
||||||
msgstr "Бинарник провайдера Zapret недоступен"
|
msgstr "Бинарник провайдера Zapret недоступен"
|
||||||
|
|
||||||
|
msgid "Zapret2 hostlist templates are not supported here because Podkop Plus does not expand them for per-rule NFQWS2 strategies."
|
||||||
|
msgstr "Шаблоны hostlist Zapret2 здесь не поддерживаются, потому что Podkop Plus не разворачивает их для per-rule стратегий NFQWS2."
|
||||||
|
|
||||||
|
msgid "Zapret2 package is installed"
|
||||||
|
msgstr "Пакет Zapret2 установлен"
|
||||||
|
|
||||||
|
msgid "Zapret2 package is not installed"
|
||||||
|
msgstr "Пакет Zapret2 не установлен"
|
||||||
|
|
||||||
|
msgid "Zapret2 provider binary is available"
|
||||||
|
msgstr "Бинарник провайдера Zapret2 доступен"
|
||||||
|
|
||||||
|
msgid "Zapret2 provider binary is not available"
|
||||||
|
msgstr "Бинарник провайдера Zapret2 недоступен"
|
||||||
|
|
||||||
|
msgid "Zapret2 route rules are configured"
|
||||||
|
msgstr "Правила маршрутизации Zapret2 настроены"
|
||||||
|
|
||||||
|
msgid "Zapret2 route rules are not configured"
|
||||||
|
msgstr "Правила маршрутизации Zapret2 не настроены"
|
||||||
|
|
||||||
|
msgid "Zapret2 sing-box outbound is configured"
|
||||||
|
msgstr "sing-box outbound для Zapret2 настроен"
|
||||||
|
|
||||||
|
msgid "Zapret2 sing-box outbound is not configured"
|
||||||
|
msgstr "sing-box outbound для Zapret2 не настроен"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+242
-19
@@ -124,7 +124,7 @@ podkop_fast_ui_capabilities_server_handler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
podkop_fast_get_ui_capabilities() {
|
podkop_fast_get_ui_capabilities() {
|
||||||
local sing_box_version sing_box_extended=0 zapret_installed=0 byedpi_installed=0
|
local sing_box_version sing_box_extended=0 zapret_installed=0 zapret2_installed=0 byedpi_installed=0
|
||||||
|
|
||||||
if command -v sing-box >/dev/null 2>&1; then
|
if command -v sing-box >/dev/null 2>&1; then
|
||||||
sing_box_version="$(sing-box version 2>/dev/null | head -1 | awk '{print $NF}')"
|
sing_box_version="$(sing-box version 2>/dev/null | head -1 | awk '{print $NF}')"
|
||||||
@@ -134,15 +134,17 @@ podkop_fast_get_ui_capabilities() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
[ -x "$ZAPRET_PROVIDER_NFQWS_BIN" ] && zapret_installed=1
|
[ -x "$ZAPRET_PROVIDER_NFQWS_BIN" ] && zapret_installed=1
|
||||||
|
[ -x "$ZAPRET2_PROVIDER_NFQWS2_BIN" ] && zapret2_installed=1
|
||||||
[ -x "$BYEDPI_BIN" ] && byedpi_installed=1
|
[ -x "$BYEDPI_BIN" ] && byedpi_installed=1
|
||||||
|
|
||||||
PODKOP_FAST_SERVER_INBOUNDS_ENABLED_COUNT=0
|
PODKOP_FAST_SERVER_INBOUNDS_ENABLED_COUNT=0
|
||||||
config_load "$PODKOP_CONFIG_NAME"
|
config_load "$PODKOP_CONFIG_NAME"
|
||||||
config_foreach podkop_fast_ui_capabilities_server_handler "server"
|
config_foreach podkop_fast_ui_capabilities_server_handler "server"
|
||||||
|
|
||||||
printf '{ "sing_box_extended": %s, "zapret_installed": %s, "byedpi_installed": %s, "server_inbounds_enabled_count": %s }\n' \
|
printf '{ "sing_box_extended": %s, "zapret_installed": %s, "zapret2_installed": %s, "byedpi_installed": %s, "server_inbounds_enabled_count": %s }\n' \
|
||||||
"$sing_box_extended" \
|
"$sing_box_extended" \
|
||||||
"$zapret_installed" \
|
"$zapret_installed" \
|
||||||
|
"$zapret2_installed" \
|
||||||
"$byedpi_installed" \
|
"$byedpi_installed" \
|
||||||
"${PODKOP_FAST_SERVER_INBOUNDS_ENABLED_COUNT:-0}"
|
"${PODKOP_FAST_SERVER_INBOUNDS_ENABLED_COUNT:-0}"
|
||||||
}
|
}
|
||||||
@@ -160,6 +162,7 @@ check_required_file "$PODKOP_LIB/helpers.sh"
|
|||||||
check_required_file "$PODKOP_LIB/json_utils.uc"
|
check_required_file "$PODKOP_LIB/json_utils.uc"
|
||||||
check_required_file "$PODKOP_LIB/provider_status.uc"
|
check_required_file "$PODKOP_LIB/provider_status.uc"
|
||||||
check_required_file "$PODKOP_LIB/zapret.sh"
|
check_required_file "$PODKOP_LIB/zapret.sh"
|
||||||
|
check_required_file "$PODKOP_LIB/zapret2.sh"
|
||||||
check_required_file "$PODKOP_LIB/byedpi.sh"
|
check_required_file "$PODKOP_LIB/byedpi.sh"
|
||||||
check_required_file "$PODKOP_LIB/sing_box_config_manager.sh"
|
check_required_file "$PODKOP_LIB/sing_box_config_manager.sh"
|
||||||
check_required_file "$PODKOP_LIB/sing_box_config_manager.uc"
|
check_required_file "$PODKOP_LIB/sing_box_config_manager.uc"
|
||||||
@@ -176,6 +179,7 @@ check_required_file "$PODKOP_LIB/updater.sh"
|
|||||||
. "$PODKOP_LIB/nft.sh"
|
. "$PODKOP_LIB/nft.sh"
|
||||||
. "$PODKOP_LIB/helpers.sh"
|
. "$PODKOP_LIB/helpers.sh"
|
||||||
. "$PODKOP_LIB/zapret.sh"
|
. "$PODKOP_LIB/zapret.sh"
|
||||||
|
. "$PODKOP_LIB/zapret2.sh"
|
||||||
. "$PODKOP_LIB/byedpi.sh"
|
. "$PODKOP_LIB/byedpi.sh"
|
||||||
. "$PODKOP_LIB/sing_box_config_manager.sh"
|
. "$PODKOP_LIB/sing_box_config_manager.sh"
|
||||||
. "$PODKOP_LIB/sing_box_config_facade.sh"
|
. "$PODKOP_LIB/sing_box_config_facade.sh"
|
||||||
@@ -214,6 +218,7 @@ PODKOP_SUBSCRIPTION_UPDATE_JOB_FINISHED_TTL_MINUTES=60
|
|||||||
PODKOP_SUBSCRIPTION_UPDATE_JOB_ORPHAN_OUTPUT_TTL_MINUTES=60
|
PODKOP_SUBSCRIPTION_UPDATE_JOB_ORPHAN_OUTPUT_TTL_MINUTES=60
|
||||||
PODKOP_NFT_POPULATE_ENABLED=1
|
PODKOP_NFT_POPULATE_ENABLED=1
|
||||||
PODKOP_ZAPRET_MISSING_WARNING_EMITTED=0
|
PODKOP_ZAPRET_MISSING_WARNING_EMITTED=0
|
||||||
|
PODKOP_ZAPRET2_MISSING_WARNING_EMITTED=0
|
||||||
PODKOP_BYEDPI_MISSING_WARNING_EMITTED=0
|
PODKOP_BYEDPI_MISSING_WARNING_EMITTED=0
|
||||||
PODKOP_URLTEST_NEW_ENABLED_SECTIONS=""
|
PODKOP_URLTEST_NEW_ENABLED_SECTIONS=""
|
||||||
PODKOP_URLTEST_SELECTOR_SWITCHES=""
|
PODKOP_URLTEST_SELECTOR_SWITCHES=""
|
||||||
@@ -1745,7 +1750,7 @@ append_sing_box_rule_signature() {
|
|||||||
|
|
||||||
signature_add "rule.$section.resolve_real_ip_for_routing" "1"
|
signature_add "rule.$section.resolve_real_ip_for_routing" "1"
|
||||||
;;
|
;;
|
||||||
zapret)
|
zapret | zapret2)
|
||||||
config_get_bool mixed_proxy_enabled "$section" "mixed_proxy_enabled" 0
|
config_get_bool mixed_proxy_enabled "$section" "mixed_proxy_enabled" 0
|
||||||
signature_add "rule.$section.mixed_proxy_enabled" "$mixed_proxy_enabled"
|
signature_add "rule.$section.mixed_proxy_enabled" "$mixed_proxy_enabled"
|
||||||
if [ "$mixed_proxy_enabled" -eq 1 ]; then
|
if [ "$mixed_proxy_enabled" -eq 1 ]; then
|
||||||
@@ -2105,6 +2110,63 @@ build_zapret_runtime_signature() {
|
|||||||
signature_finish
|
signature_finish
|
||||||
}
|
}
|
||||||
|
|
||||||
|
append_zapret2_queue_signature() {
|
||||||
|
local section="$1"
|
||||||
|
|
||||||
|
rule_is_enabled "$section" || return 0
|
||||||
|
[ "$(get_rule_action "$section")" = "zapret2" ] || return 0
|
||||||
|
|
||||||
|
signature_add "zapret2_queue.section" "$section"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_zapret2_queue_signature() {
|
||||||
|
signature_begin
|
||||||
|
config_foreach append_zapret2_queue_signature "section"
|
||||||
|
signature_finish
|
||||||
|
}
|
||||||
|
|
||||||
|
append_zapret2_runtime_signature() {
|
||||||
|
local section="$1"
|
||||||
|
local domain domain_suffix community_lists rule_set rule_set_with_subnets domain_ip_lists user_domain_list_type items
|
||||||
|
|
||||||
|
rule_is_enabled "$section" || return 0
|
||||||
|
[ "$(get_rule_action "$section")" = "zapret2" ] || return 0
|
||||||
|
|
||||||
|
domain="$(get_rule_condition_commas_string "$section" "domain" "domains")"
|
||||||
|
domain_suffix="$(get_rule_condition_commas_string "$section" "domain_suffix" "domains")"
|
||||||
|
config_get community_lists "$section" "community_lists"
|
||||||
|
config_get rule_set "$section" "rule_set"
|
||||||
|
config_get rule_set_with_subnets "$section" "rule_set_with_subnets"
|
||||||
|
config_get domain_ip_lists "$section" "domain_ip_lists"
|
||||||
|
config_get user_domain_list_type "$section" "user_domain_list_type" "disabled"
|
||||||
|
|
||||||
|
signature_add "zapret2.$section.nfqws2_opt" "$(get_rule_nfqws2_opt "$section")"
|
||||||
|
signature_add "zapret2.$section.domain" "$domain"
|
||||||
|
signature_add "zapret2.$section.domain_suffix" "$domain_suffix"
|
||||||
|
signature_add "zapret2.$section.community_lists" "$community_lists"
|
||||||
|
signature_add "zapret2.$section.rule_set" "$rule_set"
|
||||||
|
signature_add "zapret2.$section.rule_set_with_subnets" "$rule_set_with_subnets"
|
||||||
|
signature_add "zapret2.$section.domain_ip_lists" "$domain_ip_lists"
|
||||||
|
signature_add "zapret2.$section.user_domain_list_type" "$user_domain_list_type"
|
||||||
|
config_get items "$section" "local_domain_lists"
|
||||||
|
signature_add "zapret2.$section.local_domain_lists" "$items"
|
||||||
|
config_get items "$section" "remote_domain_lists"
|
||||||
|
signature_add "zapret2.$section.remote_domain_lists" "$items"
|
||||||
|
|
||||||
|
case "$user_domain_list_type" in
|
||||||
|
dynamic) config_get items "$section" "user_domains" ;;
|
||||||
|
text) config_get items "$section" "user_domains_text" ;;
|
||||||
|
*) items="" ;;
|
||||||
|
esac
|
||||||
|
signature_add "zapret2.$section.user_domains" "$items"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_zapret2_runtime_signature() {
|
||||||
|
signature_begin
|
||||||
|
config_foreach append_zapret2_runtime_signature "section"
|
||||||
|
signature_finish
|
||||||
|
}
|
||||||
|
|
||||||
append_byedpi_runtime_signature() {
|
append_byedpi_runtime_signature() {
|
||||||
local section="$1"
|
local section="$1"
|
||||||
local byedpi_index
|
local byedpi_index
|
||||||
@@ -2394,6 +2456,8 @@ capture_reload_state() {
|
|||||||
RELOAD_STATE_NFT_SIGNATURE="$(build_nft_signature)"
|
RELOAD_STATE_NFT_SIGNATURE="$(build_nft_signature)"
|
||||||
RELOAD_STATE_ZAPRET_QUEUE_SIGNATURE="$(build_zapret_queue_signature)"
|
RELOAD_STATE_ZAPRET_QUEUE_SIGNATURE="$(build_zapret_queue_signature)"
|
||||||
RELOAD_STATE_ZAPRET_RUNTIME_SIGNATURE="$(build_zapret_runtime_signature)"
|
RELOAD_STATE_ZAPRET_RUNTIME_SIGNATURE="$(build_zapret_runtime_signature)"
|
||||||
|
RELOAD_STATE_ZAPRET2_QUEUE_SIGNATURE="$(build_zapret2_queue_signature)"
|
||||||
|
RELOAD_STATE_ZAPRET2_RUNTIME_SIGNATURE="$(build_zapret2_runtime_signature)"
|
||||||
RELOAD_STATE_BYEDPI_RUNTIME_SIGNATURE="$(build_byedpi_runtime_signature)"
|
RELOAD_STATE_BYEDPI_RUNTIME_SIGNATURE="$(build_byedpi_runtime_signature)"
|
||||||
RELOAD_STATE_LIST_SIGNATURE="$(build_list_update_signature)"
|
RELOAD_STATE_LIST_SIGNATURE="$(build_list_update_signature)"
|
||||||
RELOAD_STATE_CRON_SIGNATURE="$(build_cron_signature)"
|
RELOAD_STATE_CRON_SIGNATURE="$(build_cron_signature)"
|
||||||
@@ -2411,6 +2475,8 @@ sing_box_signature=$RELOAD_STATE_SING_BOX_SIGNATURE
|
|||||||
nft_signature=$RELOAD_STATE_NFT_SIGNATURE
|
nft_signature=$RELOAD_STATE_NFT_SIGNATURE
|
||||||
zapret_queue_signature=$RELOAD_STATE_ZAPRET_QUEUE_SIGNATURE
|
zapret_queue_signature=$RELOAD_STATE_ZAPRET_QUEUE_SIGNATURE
|
||||||
zapret_runtime_signature=$RELOAD_STATE_ZAPRET_RUNTIME_SIGNATURE
|
zapret_runtime_signature=$RELOAD_STATE_ZAPRET_RUNTIME_SIGNATURE
|
||||||
|
zapret2_queue_signature=$RELOAD_STATE_ZAPRET2_QUEUE_SIGNATURE
|
||||||
|
zapret2_runtime_signature=$RELOAD_STATE_ZAPRET2_RUNTIME_SIGNATURE
|
||||||
byedpi_runtime_signature=$RELOAD_STATE_BYEDPI_RUNTIME_SIGNATURE
|
byedpi_runtime_signature=$RELOAD_STATE_BYEDPI_RUNTIME_SIGNATURE
|
||||||
list_signature=$RELOAD_STATE_LIST_SIGNATURE
|
list_signature=$RELOAD_STATE_LIST_SIGNATURE
|
||||||
cron_signature=$RELOAD_STATE_CRON_SIGNATURE
|
cron_signature=$RELOAD_STATE_CRON_SIGNATURE
|
||||||
@@ -3055,7 +3121,7 @@ migrate_0_7_17_8_rule() {
|
|||||||
migrate_0_7_17_8_delete_subscription_cache "$section"
|
migrate_0_7_17_8_delete_subscription_cache "$section"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
vpn | outbound | block | direct | zapret | byedpi)
|
vpn | outbound | block | direct | zapret | zapret2 | byedpi)
|
||||||
podkop_uci_delete_option "$section" "proxy_config_type"
|
podkop_uci_delete_option "$section" "proxy_config_type"
|
||||||
podkop_uci_delete_option "$section" "proxy_string"
|
podkop_uci_delete_option "$section" "proxy_string"
|
||||||
podkop_uci_delete_option "$section" "urltest_proxy_links"
|
podkop_uci_delete_option "$section" "urltest_proxy_links"
|
||||||
@@ -3172,6 +3238,7 @@ check_requirements() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
check_zapret_requirements
|
check_zapret_requirements
|
||||||
|
check_zapret2_requirements
|
||||||
check_byedpi_requirements
|
check_byedpi_requirements
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3192,6 +3259,16 @@ _check_outbound_node() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$action" = "zapret" ] && is_zapret_installed; then
|
||||||
|
section_exists=0
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$action" = "zapret2" ] && is_zapret2_installed; then
|
||||||
|
section_exists=0
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$selector_proxy_links" ] || [ -n "$subscription_urls" ] ||
|
if [ -n "$selector_proxy_links" ] || [ -n "$subscription_urls" ] ||
|
||||||
[ -n "$outbound_json" ] || [ -n "$interface" ]; then
|
[ -n "$outbound_json" ] || [ -n "$interface" ]; then
|
||||||
section_exists=0
|
section_exists=0
|
||||||
@@ -3266,6 +3343,7 @@ start_main() {
|
|||||||
apply_pending_urltest_selector_switches
|
apply_pending_urltest_selector_switches
|
||||||
run_deferred_subscription_bootstrap
|
run_deferred_subscription_bootstrap
|
||||||
start_zapret_runtime
|
start_zapret_runtime
|
||||||
|
start_zapret2_runtime
|
||||||
|
|
||||||
(close_inherited_service_lock_fd; list_update) &
|
(close_inherited_service_lock_fd; list_update) &
|
||||||
}
|
}
|
||||||
@@ -3291,6 +3369,7 @@ stop_main() {
|
|||||||
rm -f "$TMP_RULESET_FOLDER"/*
|
rm -f "$TMP_RULESET_FOLDER"/*
|
||||||
|
|
||||||
stop_zapret_runtime
|
stop_zapret_runtime
|
||||||
|
stop_zapret2_runtime
|
||||||
stop_byedpi_runtime
|
stop_byedpi_runtime
|
||||||
|
|
||||||
log "Flush nft"
|
log "Flush nft"
|
||||||
@@ -3419,10 +3498,10 @@ reload() {
|
|||||||
local status
|
local status
|
||||||
local force_runtime_reload=0
|
local force_runtime_reload=0
|
||||||
local previous_service_trigger_signature previous_dnsmasq_signature previous_sing_box_signature previous_nft_signature
|
local previous_service_trigger_signature previous_dnsmasq_signature previous_sing_box_signature previous_nft_signature
|
||||||
local previous_zapret_queue_signature previous_zapret_runtime_signature previous_byedpi_runtime_signature previous_list_signature previous_cron_signature
|
local previous_zapret_queue_signature previous_zapret_runtime_signature previous_zapret2_queue_signature previous_zapret2_runtime_signature previous_byedpi_runtime_signature previous_list_signature previous_cron_signature
|
||||||
local previous_urltest_enabled_sections previous_urltest_enabled_sections_known previous_dont_touch_dhcp needs_sing_box_reload needs_nft_rebuild needs_zapret_restart needs_byedpi_restart
|
local previous_urltest_enabled_sections previous_urltest_enabled_sections_known previous_dont_touch_dhcp needs_sing_box_reload needs_nft_rebuild needs_zapret_restart needs_zapret2_restart needs_byedpi_restart
|
||||||
local needs_dnsmasq_configure needs_dnsmasq_restore needs_cron_refresh needs_list_update
|
local needs_dnsmasq_configure needs_dnsmasq_restore needs_cron_refresh needs_list_update
|
||||||
local changed_service_triggers changed_dnsmasq changed_sing_box changed_nft changed_zapret_queue changed_zapret_runtime changed_byedpi_runtime changed_cron changed_list
|
local changed_service_triggers changed_dnsmasq changed_sing_box changed_nft changed_zapret_queue changed_zapret_runtime changed_zapret2_queue changed_zapret2_runtime changed_byedpi_runtime changed_cron changed_list
|
||||||
|
|
||||||
log "Podkop Plus reload"
|
log "Podkop Plus reload"
|
||||||
|
|
||||||
@@ -3458,6 +3537,8 @@ reload() {
|
|||||||
previous_nft_signature="$(read_reload_state_value "nft_signature")"
|
previous_nft_signature="$(read_reload_state_value "nft_signature")"
|
||||||
previous_zapret_queue_signature="$(read_reload_state_value "zapret_queue_signature")"
|
previous_zapret_queue_signature="$(read_reload_state_value "zapret_queue_signature")"
|
||||||
previous_zapret_runtime_signature="$(read_reload_state_value "zapret_runtime_signature")"
|
previous_zapret_runtime_signature="$(read_reload_state_value "zapret_runtime_signature")"
|
||||||
|
previous_zapret2_queue_signature="$(read_reload_state_value "zapret2_queue_signature")"
|
||||||
|
previous_zapret2_runtime_signature="$(read_reload_state_value "zapret2_runtime_signature")"
|
||||||
previous_byedpi_runtime_signature="$(read_reload_state_value "byedpi_runtime_signature")"
|
previous_byedpi_runtime_signature="$(read_reload_state_value "byedpi_runtime_signature")"
|
||||||
previous_list_signature="$(read_reload_state_value "list_signature")"
|
previous_list_signature="$(read_reload_state_value "list_signature")"
|
||||||
previous_cron_signature="$(read_reload_state_value "cron_signature")"
|
previous_cron_signature="$(read_reload_state_value "cron_signature")"
|
||||||
@@ -3481,6 +3562,7 @@ reload() {
|
|||||||
needs_sing_box_reload=0
|
needs_sing_box_reload=0
|
||||||
needs_nft_rebuild=0
|
needs_nft_rebuild=0
|
||||||
needs_zapret_restart=0
|
needs_zapret_restart=0
|
||||||
|
needs_zapret2_restart=0
|
||||||
needs_byedpi_restart=0
|
needs_byedpi_restart=0
|
||||||
needs_dnsmasq_configure=0
|
needs_dnsmasq_configure=0
|
||||||
needs_dnsmasq_restore=0
|
needs_dnsmasq_restore=0
|
||||||
@@ -3492,6 +3574,8 @@ reload() {
|
|||||||
changed_nft=0
|
changed_nft=0
|
||||||
changed_zapret_queue=0
|
changed_zapret_queue=0
|
||||||
changed_zapret_runtime=0
|
changed_zapret_runtime=0
|
||||||
|
changed_zapret2_queue=0
|
||||||
|
changed_zapret2_runtime=0
|
||||||
changed_byedpi_runtime=0
|
changed_byedpi_runtime=0
|
||||||
changed_cron=0
|
changed_cron=0
|
||||||
changed_list=0
|
changed_list=0
|
||||||
@@ -3520,6 +3604,18 @@ reload() {
|
|||||||
needs_zapret_restart=1
|
needs_zapret_restart=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$RELOAD_STATE_ZAPRET2_QUEUE_SIGNATURE" != "$previous_zapret2_queue_signature" ]; then
|
||||||
|
changed_zapret2_queue=1
|
||||||
|
needs_zapret2_restart=1
|
||||||
|
needs_nft_rebuild=1
|
||||||
|
needs_sing_box_reload=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$RELOAD_STATE_ZAPRET2_RUNTIME_SIGNATURE" != "$previous_zapret2_runtime_signature" ]; then
|
||||||
|
changed_zapret2_runtime=1
|
||||||
|
needs_zapret2_restart=1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$RELOAD_STATE_BYEDPI_RUNTIME_SIGNATURE" != "$previous_byedpi_runtime_signature" ]; then
|
if [ "$RELOAD_STATE_BYEDPI_RUNTIME_SIGNATURE" != "$previous_byedpi_runtime_signature" ]; then
|
||||||
changed_byedpi_runtime=1
|
changed_byedpi_runtime=1
|
||||||
needs_byedpi_restart=1
|
needs_byedpi_restart=1
|
||||||
@@ -3552,18 +3648,20 @@ reload() {
|
|||||||
[ "$needs_sing_box_reload" -eq 0 ] &&
|
[ "$needs_sing_box_reload" -eq 0 ] &&
|
||||||
[ "$needs_nft_rebuild" -eq 0 ] &&
|
[ "$needs_nft_rebuild" -eq 0 ] &&
|
||||||
[ "$needs_zapret_restart" -eq 0 ] &&
|
[ "$needs_zapret_restart" -eq 0 ] &&
|
||||||
|
[ "$needs_zapret2_restart" -eq 0 ] &&
|
||||||
[ "$needs_byedpi_restart" -eq 0 ] &&
|
[ "$needs_byedpi_restart" -eq 0 ] &&
|
||||||
[ "$needs_dnsmasq_configure" -eq 0 ] &&
|
[ "$needs_dnsmasq_configure" -eq 0 ] &&
|
||||||
[ "$needs_dnsmasq_restore" -eq 0 ]; then
|
[ "$needs_dnsmasq_restore" -eq 0 ]; then
|
||||||
needs_sing_box_reload=1
|
needs_sing_box_reload=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Reload signature changes: service_triggers=$changed_service_triggers sing-box=$changed_sing_box nft=$changed_nft zapret_queue=$changed_zapret_queue zapret_runtime=$changed_zapret_runtime byedpi_runtime=$changed_byedpi_runtime dnsmasq=$changed_dnsmasq cron=$changed_cron list=$changed_list forced=$force_runtime_reload" "debug"
|
log "Reload signature changes: service_triggers=$changed_service_triggers sing-box=$changed_sing_box nft=$changed_nft zapret_queue=$changed_zapret_queue zapret_runtime=$changed_zapret_runtime zapret2_queue=$changed_zapret2_queue zapret2_runtime=$changed_zapret2_runtime byedpi_runtime=$changed_byedpi_runtime dnsmasq=$changed_dnsmasq cron=$changed_cron list=$changed_list forced=$force_runtime_reload" "debug"
|
||||||
log "Reload plan: sing-box=$needs_sing_box_reload nft=$needs_nft_rebuild zapret=$needs_zapret_restart byedpi=$needs_byedpi_restart dnsmasq_configure=$needs_dnsmasq_configure dnsmasq_restore=$needs_dnsmasq_restore cron=$needs_cron_refresh list_update=$needs_list_update" "debug"
|
log "Reload plan: sing-box=$needs_sing_box_reload nft=$needs_nft_rebuild zapret=$needs_zapret_restart zapret2=$needs_zapret2_restart byedpi=$needs_byedpi_restart dnsmasq_configure=$needs_dnsmasq_configure dnsmasq_restore=$needs_dnsmasq_restore cron=$needs_cron_refresh list_update=$needs_list_update" "debug"
|
||||||
|
|
||||||
if [ "$needs_sing_box_reload" -eq 0 ] &&
|
if [ "$needs_sing_box_reload" -eq 0 ] &&
|
||||||
[ "$needs_nft_rebuild" -eq 0 ] &&
|
[ "$needs_nft_rebuild" -eq 0 ] &&
|
||||||
[ "$needs_zapret_restart" -eq 0 ] &&
|
[ "$needs_zapret_restart" -eq 0 ] &&
|
||||||
|
[ "$needs_zapret2_restart" -eq 0 ] &&
|
||||||
[ "$needs_byedpi_restart" -eq 0 ] &&
|
[ "$needs_byedpi_restart" -eq 0 ] &&
|
||||||
[ "$needs_dnsmasq_configure" -eq 0 ] &&
|
[ "$needs_dnsmasq_configure" -eq 0 ] &&
|
||||||
[ "$needs_dnsmasq_restore" -eq 0 ] &&
|
[ "$needs_dnsmasq_restore" -eq 0 ] &&
|
||||||
@@ -3582,6 +3680,10 @@ reload() {
|
|||||||
stop_zapret_runtime
|
stop_zapret_runtime
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$needs_zapret2_restart" -eq 1 ]; then
|
||||||
|
stop_zapret2_runtime
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$needs_byedpi_restart" -eq 1 ]; then
|
if [ "$needs_byedpi_restart" -eq 1 ]; then
|
||||||
stop_byedpi_runtime
|
stop_byedpi_runtime
|
||||||
fi
|
fi
|
||||||
@@ -3609,6 +3711,10 @@ reload() {
|
|||||||
start_zapret_runtime
|
start_zapret_runtime
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$needs_zapret2_restart" -eq 1 ]; then
|
||||||
|
start_zapret2_runtime
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$needs_byedpi_restart" -eq 1 ]; then
|
if [ "$needs_byedpi_restart" -eq 1 ]; then
|
||||||
start_byedpi_runtime
|
start_byedpi_runtime
|
||||||
fi
|
fi
|
||||||
@@ -4034,6 +4140,22 @@ process_validate_rule() {
|
|||||||
validate_rule_nfqws_opt "$section"
|
validate_rule_nfqws_opt "$section"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$action" = "zapret2" ]; then
|
||||||
|
if ! is_zapret2_installed; then
|
||||||
|
if [ "$PODKOP_ZAPRET2_MISSING_WARNING_EMITTED" -eq 0 ]; then
|
||||||
|
log "There are enabled rules with action 'zapret2', but the zapret2 package is not installed. These rules will be skipped." "error"
|
||||||
|
PODKOP_ZAPRET2_MISSING_WARNING_EMITTED=1
|
||||||
|
fi
|
||||||
|
config_list_foreach "$section" "community_lists" validate_service
|
||||||
|
config_list_foreach "$section" "rule_set" validate_ruleset_reference
|
||||||
|
config_list_foreach "$section" "rule_set_with_subnets" validate_ruleset_reference
|
||||||
|
config_list_foreach "$section" "domain_ip_lists" validate_plain_domain_ip_list_reference
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate_rule_nfqws2_opt "$section"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$action" = "byedpi" ]; then
|
if [ "$action" = "byedpi" ]; then
|
||||||
if ! is_byedpi_installed; then
|
if ! is_byedpi_installed; then
|
||||||
if [ "$PODKOP_BYEDPI_MISSING_WARNING_EMITTED" -eq 0 ]; then
|
if [ "$PODKOP_BYEDPI_MISSING_WARNING_EMITTED" -eq 0 ]; then
|
||||||
@@ -4523,6 +4645,7 @@ create_nft_rules() {
|
|||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_LOCALV4_SET_NAME" return
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_LOCALV4_SET_NAME" return
|
||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output meta mark "$NFT_OUTBOUND_MARK" counter return
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output meta mark "$NFT_OUTBOUND_MARK" counter return
|
||||||
create_zapret_nft_rules
|
create_zapret_nft_rules
|
||||||
|
create_zapret2_nft_rules
|
||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_COMMON_SET_NAME" meta l4proto tcp meta mark set "$NFT_FAKEIP_MARK" counter
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_COMMON_SET_NAME" meta l4proto tcp meta mark set "$NFT_FAKEIP_MARK" counter
|
||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_COMMON_SET_NAME" meta l4proto udp meta mark set "$NFT_FAKEIP_MARK" counter
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr "@$NFT_COMMON_SET_NAME" meta l4proto udp meta mark set "$NFT_FAKEIP_MARK" counter
|
||||||
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr . tcp dport "@$NFT_IP_PORT_SET_NAME" meta mark set "$NFT_FAKEIP_MARK" counter
|
nft add rule inet "$NFT_TABLE_NAME" mangle_output ip daddr . tcp dport "@$NFT_IP_PORT_SET_NAME" meta mark set "$NFT_FAKEIP_MARK" counter
|
||||||
@@ -7895,6 +8018,26 @@ configure_outbound_handler() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$action" = "zapret2" ]; then
|
||||||
|
write_subscription_metadata_json "$section" ""
|
||||||
|
if ! is_zapret2_installed; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local routing_mark outbound_tag zapret2_index
|
||||||
|
|
||||||
|
zapret2_index="$(get_zapret2_rule_index "$section")"
|
||||||
|
if [ "${zapret2_index:-0}" -le 0 ]; then
|
||||||
|
log "Unable to resolve Zapret2 index for rule '$section'. Aborted." "fatal"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
routing_mark="$(get_zapret2_rule_mark_value "$zapret2_index")"
|
||||||
|
outbound_tag="$(get_outbound_tag_by_section "$section")"
|
||||||
|
config=$(sing_box_cm_add_direct_outbound "$config" "$outbound_tag" "$routing_mark")
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$action" = "byedpi" ]; then
|
if [ "$action" = "byedpi" ]; then
|
||||||
if ! is_byedpi_installed; then
|
if ! is_byedpi_installed; then
|
||||||
return 0
|
return 0
|
||||||
@@ -8282,10 +8425,10 @@ create_route_rule_for_action() {
|
|||||||
outbound_tag="$(get_outbound_tag_by_section "$section")"
|
outbound_tag="$(get_outbound_tag_by_section "$section")"
|
||||||
config=$(sing_box_cm_add_route_rule "$config" "$rule_tag" "$inbound_tag" "$outbound_tag")
|
config=$(sing_box_cm_add_route_rule "$config" "$rule_tag" "$inbound_tag" "$outbound_tag")
|
||||||
;;
|
;;
|
||||||
zapret)
|
zapret | zapret2)
|
||||||
local zapret_outbound_tag
|
local provider_outbound_tag
|
||||||
zapret_outbound_tag="$(get_outbound_tag_by_section "$section")"
|
provider_outbound_tag="$(get_outbound_tag_by_section "$section")"
|
||||||
config=$(sing_box_cm_add_route_rule "$config" "$rule_tag" "$inbound_tag" "$zapret_outbound_tag")
|
config=$(sing_box_cm_add_route_rule "$config" "$rule_tag" "$inbound_tag" "$provider_outbound_tag")
|
||||||
;;
|
;;
|
||||||
direct)
|
direct)
|
||||||
local direct_outbound_tag
|
local direct_outbound_tag
|
||||||
@@ -8570,6 +8713,10 @@ configure_route_rule_handler() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$action" = "zapret2" ] && ! is_zapret2_installed; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$action" = "byedpi" ] && ! is_byedpi_installed; then
|
if [ "$action" = "byedpi" ] && ! is_byedpi_installed; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -8681,6 +8828,10 @@ configure_fully_routed_ips_for_section() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$action" = "zapret2" ] && ! is_zapret2_installed; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$action" = "byedpi" ] && ! is_byedpi_installed; then
|
if [ "$action" = "byedpi" ] && ! is_byedpi_installed; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -8800,13 +8951,16 @@ configure_section_mixed_proxy() {
|
|||||||
subscription_section_is_deferred "$section" && return 0
|
subscription_section_is_deferred "$section" && return 0
|
||||||
|
|
||||||
action="$(get_rule_action "$section")"
|
action="$(get_rule_action "$section")"
|
||||||
[ "$action" = "proxy" ] || [ "$action" = "outbound" ] || [ "$action" = "vpn" ] || [ "$action" = "byedpi" ] || [ "$action" = "zapret" ] || return 0
|
[ "$action" = "proxy" ] || [ "$action" = "outbound" ] || [ "$action" = "vpn" ] || [ "$action" = "byedpi" ] || [ "$action" = "zapret" ] || [ "$action" = "zapret2" ] || return 0
|
||||||
if [ "$action" = "byedpi" ] && ! is_byedpi_installed; then
|
if [ "$action" = "byedpi" ] && ! is_byedpi_installed; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
if [ "$action" = "zapret" ] && ! is_zapret_installed; then
|
if [ "$action" = "zapret" ] && ! is_zapret_installed; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
if [ "$action" = "zapret2" ] && ! is_zapret2_installed; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
local mixed_inbound_enabled mixed_proxy_port mixed_inbound_tag mixed_outbound_tag mixed_proxy_address \
|
local mixed_inbound_enabled mixed_proxy_port mixed_inbound_tag mixed_outbound_tag mixed_proxy_address \
|
||||||
mixed_proxy_auth_enabled mixed_proxy_username mixed_proxy_password
|
mixed_proxy_auth_enabled mixed_proxy_username mixed_proxy_password
|
||||||
@@ -9332,7 +9486,10 @@ _determine_first_outbound_section() {
|
|||||||
subscription_section_is_deferred "$section" && return 0
|
subscription_section_is_deferred "$section" && return 0
|
||||||
|
|
||||||
action="$(get_rule_action "$section")"
|
action="$(get_rule_action "$section")"
|
||||||
if [ "$action" = "proxy" ] || [ "$action" = "outbound" ] || [ "$action" = "vpn" ] || { [ "$action" = "byedpi" ] && is_byedpi_installed; }; then
|
if [ "$action" = "proxy" ] || [ "$action" = "outbound" ] || [ "$action" = "vpn" ] ||
|
||||||
|
{ [ "$action" = "byedpi" ] && is_byedpi_installed; } ||
|
||||||
|
{ [ "$action" = "zapret" ] && is_zapret_installed; } ||
|
||||||
|
{ [ "$action" = "zapret2" ] && is_zapret2_installed; }; then
|
||||||
[ -z "$first_section" ] && first_section="$1"
|
[ -z "$first_section" ] && first_section="$1"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -10299,7 +10456,7 @@ write_system_info_cache() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_system_info() {
|
build_system_info() {
|
||||||
local podkop_version podkop_latest_version luci_app_version sing_box_version sing_box_extended zapret_version zapret_installed byedpi_version byedpi_installed openwrt_version device_model
|
local podkop_version podkop_latest_version luci_app_version sing_box_version sing_box_extended zapret_version zapret_installed zapret2_version zapret2_installed byedpi_version byedpi_installed openwrt_version device_model
|
||||||
local generated_at
|
local generated_at
|
||||||
|
|
||||||
podkop_version="$PODKOP_VERSION"
|
podkop_version="$PODKOP_VERSION"
|
||||||
@@ -10327,6 +10484,15 @@ build_system_info() {
|
|||||||
zapret_version="not installed"
|
zapret_version="not installed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
zapret2_installed=0
|
||||||
|
if is_zapret2_installed; then
|
||||||
|
zapret2_installed=1
|
||||||
|
zapret2_version="$(get_zapret2_package_version)"
|
||||||
|
[ -z "$zapret2_version" ] && zapret2_version="unknown"
|
||||||
|
else
|
||||||
|
zapret2_version="not installed"
|
||||||
|
fi
|
||||||
|
|
||||||
byedpi_installed=0
|
byedpi_installed=0
|
||||||
if is_byedpi_installed; then
|
if is_byedpi_installed; then
|
||||||
byedpi_installed=1
|
byedpi_installed=1
|
||||||
@@ -10359,6 +10525,7 @@ build_system_info() {
|
|||||||
"$podkop_version" "$podkop_latest_version" "$luci_app_version" \
|
"$podkop_version" "$podkop_latest_version" "$luci_app_version" \
|
||||||
"$sing_box_version" "$sing_box_extended" \
|
"$sing_box_version" "$sing_box_extended" \
|
||||||
"$zapret_version" "$zapret_installed" \
|
"$zapret_version" "$zapret_installed" \
|
||||||
|
"$zapret2_version" "$zapret2_installed" \
|
||||||
"$byedpi_version" "$byedpi_installed" \
|
"$byedpi_version" "$byedpi_installed" \
|
||||||
"$openwrt_version" "$device_model" "$generated_at"
|
"$openwrt_version" "$device_model" "$generated_at"
|
||||||
}
|
}
|
||||||
@@ -10397,11 +10564,12 @@ get_server_capabilities() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_ui_capabilities() {
|
get_ui_capabilities() {
|
||||||
local sing_box_version sing_box_extended=0 zapret_installed=0 byedpi_installed=0
|
local sing_box_version sing_box_extended=0 zapret_installed=0 zapret2_installed=0 byedpi_installed=0
|
||||||
|
|
||||||
sing_box_version="$(get_sing_box_version)"
|
sing_box_version="$(get_sing_box_version)"
|
||||||
is_sing_box_extended "$sing_box_version" && sing_box_extended=1
|
is_sing_box_extended "$sing_box_version" && sing_box_extended=1
|
||||||
is_zapret_installed && zapret_installed=1
|
is_zapret_installed && zapret_installed=1
|
||||||
|
is_zapret2_installed && zapret2_installed=1
|
||||||
is_byedpi_installed && byedpi_installed=1
|
is_byedpi_installed && byedpi_installed=1
|
||||||
|
|
||||||
INBOUNDS_CONFIG_ENABLED_COUNT=0
|
INBOUNDS_CONFIG_ENABLED_COUNT=0
|
||||||
@@ -10410,6 +10578,7 @@ get_ui_capabilities() {
|
|||||||
json_utils_ucode object-json \
|
json_utils_ucode object-json \
|
||||||
sing_box_extended n "$sing_box_extended" \
|
sing_box_extended n "$sing_box_extended" \
|
||||||
zapret_installed n "$zapret_installed" \
|
zapret_installed n "$zapret_installed" \
|
||||||
|
zapret2_installed n "$zapret2_installed" \
|
||||||
byedpi_installed n "$byedpi_installed" \
|
byedpi_installed n "$byedpi_installed" \
|
||||||
server_inbounds_enabled_count n "${INBOUNDS_CONFIG_ENABLED_COUNT:-0}"
|
server_inbounds_enabled_count n "${INBOUNDS_CONFIG_ENABLED_COUNT:-0}"
|
||||||
}
|
}
|
||||||
@@ -10418,6 +10587,10 @@ get_zapret_status() {
|
|||||||
get_zapret_status_json
|
get_zapret_status_json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_zapret2_status() {
|
||||||
|
get_zapret2_status_json
|
||||||
|
}
|
||||||
|
|
||||||
neutralize_zapret_defaults() {
|
neutralize_zapret_defaults() {
|
||||||
log "Standalone zapret is not neutralized automatically; Podkop Plus uses /opt/zapret/nfq/nfqws as an external provider and manages only its own NFQUEUE range."
|
log "Standalone zapret is not neutralized automatically; Podkop Plus uses /opt/zapret/nfq/nfqws as an external provider and manages only its own NFQUEUE range."
|
||||||
}
|
}
|
||||||
@@ -10426,6 +10599,10 @@ check_zapret_runtime() {
|
|||||||
check_zapret_runtime_json
|
check_zapret_runtime_json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_zapret2_runtime() {
|
||||||
|
check_zapret2_runtime_json
|
||||||
|
}
|
||||||
|
|
||||||
get_byedpi_status() {
|
get_byedpi_status() {
|
||||||
get_byedpi_status_json
|
get_byedpi_status_json
|
||||||
}
|
}
|
||||||
@@ -10593,6 +10770,17 @@ validate_nfqws_strategy_json() {
|
|||||||
json_utils_ucode nfqws-strategy-validation false "$NFQWS_VALIDATE_ERROR" "$NFQWS_VALIDATE_NEEDLE" "$NFQWS_VALIDATE_NEEDLES"
|
json_utils_ucode nfqws-strategy-validation false "$NFQWS_VALIDATE_ERROR" "$NFQWS_VALIDATE_NEEDLE" "$NFQWS_VALIDATE_NEEDLES"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate_nfqws2_strategy_json() {
|
||||||
|
local raw_opt="${1:-}"
|
||||||
|
|
||||||
|
if check_nfqws2_strategy "$raw_opt"; then
|
||||||
|
json_utils_ucode nfqws-strategy-validation true "" "" ""
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
json_utils_ucode nfqws-strategy-validation false "$NFQWS2_VALIDATE_ERROR" "$NFQWS2_VALIDATE_NEEDLE" "$NFQWS2_VALIDATE_NEEDLES"
|
||||||
|
}
|
||||||
|
|
||||||
dns_check_resolve_host() {
|
dns_check_resolve_host() {
|
||||||
local host="$1"
|
local host="$1"
|
||||||
local resolver="$2"
|
local resolver="$2"
|
||||||
@@ -11212,7 +11400,7 @@ global_check() {
|
|||||||
system_info_json=$(get_system_info)
|
system_info_json=$(get_system_info)
|
||||||
|
|
||||||
if [ -n "$system_info_json" ]; then
|
if [ -n "$system_info_json" ]; then
|
||||||
local podkop_version podkop_latest_version luci_app_version sing_box_version sing_box_extended zapret_version zapret_installed byedpi_version byedpi_installed openwrt_version device_model
|
local podkop_version podkop_latest_version luci_app_version sing_box_version sing_box_extended zapret_version zapret_installed zapret2_version zapret2_installed byedpi_version byedpi_installed openwrt_version device_model
|
||||||
|
|
||||||
podkop_version=$(json_get_default "$system_info_json" podkop_version "unknown")
|
podkop_version=$(json_get_default "$system_info_json" podkop_version "unknown")
|
||||||
podkop_latest_version=$(json_get_default "$system_info_json" podkop_latest_version "unknown")
|
podkop_latest_version=$(json_get_default "$system_info_json" podkop_latest_version "unknown")
|
||||||
@@ -11221,6 +11409,8 @@ global_check() {
|
|||||||
sing_box_extended=$(json_get_default "$system_info_json" sing_box_extended 0)
|
sing_box_extended=$(json_get_default "$system_info_json" sing_box_extended 0)
|
||||||
zapret_version=$(json_get_default "$system_info_json" zapret_version "unknown")
|
zapret_version=$(json_get_default "$system_info_json" zapret_version "unknown")
|
||||||
zapret_installed=$(json_get_default "$system_info_json" zapret_installed 0)
|
zapret_installed=$(json_get_default "$system_info_json" zapret_installed 0)
|
||||||
|
zapret2_version=$(json_get_default "$system_info_json" zapret2_version "unknown")
|
||||||
|
zapret2_installed=$(json_get_default "$system_info_json" zapret2_installed 0)
|
||||||
byedpi_version=$(json_get_default "$system_info_json" byedpi_version "unknown")
|
byedpi_version=$(json_get_default "$system_info_json" byedpi_version "unknown")
|
||||||
byedpi_installed=$(json_get_default "$system_info_json" byedpi_installed 0)
|
byedpi_installed=$(json_get_default "$system_info_json" byedpi_installed 0)
|
||||||
openwrt_version=$(json_get_default "$system_info_json" openwrt_version "unknown")
|
openwrt_version=$(json_get_default "$system_info_json" openwrt_version "unknown")
|
||||||
@@ -11237,6 +11427,9 @@ global_check() {
|
|||||||
if [ "$zapret_installed" -eq 1 ]; then
|
if [ "$zapret_installed" -eq 1 ]; then
|
||||||
print_global "🧵 Zapret: $zapret_version"
|
print_global "🧵 Zapret: $zapret_version"
|
||||||
fi
|
fi
|
||||||
|
if [ "$zapret2_installed" -eq 1 ]; then
|
||||||
|
print_global "🧵 Zapret2: $zapret2_version"
|
||||||
|
fi
|
||||||
if [ "$byedpi_installed" -eq 1 ]; then
|
if [ "$byedpi_installed" -eq 1 ]; then
|
||||||
print_global "🧵 ByeDPI: $byedpi_version"
|
print_global "🧵 ByeDPI: $byedpi_version"
|
||||||
fi
|
fi
|
||||||
@@ -11488,6 +11681,15 @@ global_check() {
|
|||||||
print_global "✅ Zapret provider available"
|
print_global "✅ Zapret provider available"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local zapret2_check_json
|
||||||
|
zapret2_check_json=$(check_zapret2_runtime)
|
||||||
|
|
||||||
|
if [ -n "$zapret2_check_json" ] && [ "$(json_get_default "$zapret2_check_json" zapret2_installed 0)" = "1" ]; then
|
||||||
|
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
print_global "🧵 Zapret2 status"
|
||||||
|
print_global "✅ Zapret2 provider available"
|
||||||
|
fi
|
||||||
|
|
||||||
local byedpi_check_json
|
local byedpi_check_json
|
||||||
byedpi_check_json=$(check_byedpi_runtime)
|
byedpi_check_json=$(check_byedpi_runtime)
|
||||||
|
|
||||||
@@ -11646,6 +11848,14 @@ global_check() {
|
|||||||
print_global "⚠️ Standalone zapret autostart is enabled. Podkop Plus will not modify /etc/config/zapret."
|
print_global "⚠️ Standalone zapret autostart is enabled. Podkop Plus will not modify /etc/config/zapret."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -x /etc/init.d/zapret2 ] && /etc/init.d/zapret2 status >/dev/null 2>&1; then
|
||||||
|
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
print_global "⚠️ Standalone zapret2 service is active. Podkop Plus uses separate queues, but packet-level policy overlap is possible."
|
||||||
|
elif [ -x /etc/init.d/zapret2 ] && /etc/init.d/zapret2 enabled >/dev/null 2>&1; then
|
||||||
|
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
print_global "⚠️ Standalone zapret2 autostart is enabled. Podkop Plus will not modify /etc/config/zapret2."
|
||||||
|
fi
|
||||||
|
|
||||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
print_global "🥸 FakeIP status"
|
print_global "🥸 FakeIP status"
|
||||||
|
|
||||||
@@ -11701,6 +11911,7 @@ Available commands:
|
|||||||
check_sing_box_logs Show sing-box logs
|
check_sing_box_logs Show sing-box logs
|
||||||
check_fakeip Test sing-box FakeIP DNS
|
check_fakeip Test sing-box FakeIP DNS
|
||||||
check_zapret_runtime Check external zapret provider state
|
check_zapret_runtime Check external zapret provider state
|
||||||
|
check_zapret2_runtime Check external zapret2 provider state
|
||||||
check_byedpi_runtime Check external ByeDPI provider state
|
check_byedpi_runtime Check external ByeDPI provider state
|
||||||
neutralize_zapret_defaults
|
neutralize_zapret_defaults
|
||||||
Compatibility no-op; Podkop Plus does not manage standalone zapret
|
Compatibility no-op; Podkop Plus does not manage standalone zapret
|
||||||
@@ -11716,19 +11927,22 @@ Available commands:
|
|||||||
Get UI-only metadata for a subscription rule
|
Get UI-only metadata for a subscription rule
|
||||||
get_sing_box_status Get sing-box service status
|
get_sing_box_status Get sing-box service status
|
||||||
get_zapret_status Get zapret provider and Podkop Plus-managed nfqws status
|
get_zapret_status Get zapret provider and Podkop Plus-managed nfqws status
|
||||||
|
get_zapret2_status Get zapret2 provider and Podkop Plus-managed nfqws2 status
|
||||||
get_byedpi_status Get ByeDPI provider and Podkop Plus-managed ciadpi status
|
get_byedpi_status Get ByeDPI provider and Podkop Plus-managed ciadpi status
|
||||||
get_system_info Get system information in JSON format
|
get_system_info Get system information in JSON format
|
||||||
get_server_capabilities Get server UI capabilities in JSON format
|
get_server_capabilities Get server UI capabilities in JSON format
|
||||||
get_ui_capabilities Get lightweight UI capabilities in JSON format
|
get_ui_capabilities Get lightweight UI capabilities in JSON format
|
||||||
generate_reality_keypair
|
generate_reality_keypair
|
||||||
Generate a sing-box Reality key pair in JSON format
|
Generate a sing-box Reality key pair in JSON format
|
||||||
component_action Manage Podkop Plus, sing-box, zapret, and ByeDPI components
|
component_action Manage Podkop Plus, sing-box, zapret, zapret2, and ByeDPI components
|
||||||
component_action_async Start a component action in the background
|
component_action_async Start a component action in the background
|
||||||
component_action_status Get background component action status
|
component_action_status Get background component action status
|
||||||
check_dns_available Check DNS server availability
|
check_dns_available Check DNS server availability
|
||||||
global_check Run global system check
|
global_check Run global system check
|
||||||
validate_nfqws_strategy_json
|
validate_nfqws_strategy_json
|
||||||
Validate an NFQWS strategy and print JSON result
|
Validate an NFQWS strategy and print JSON result
|
||||||
|
validate_nfqws2_strategy_json
|
||||||
|
Validate an NFQWS2 strategy and print JSON result
|
||||||
validate_byedpi_strategy_json
|
validate_byedpi_strategy_json
|
||||||
Validate a ByeDPI ciadpi strategy and print JSON result
|
Validate a ByeDPI ciadpi strategy and print JSON result
|
||||||
EOF
|
EOF
|
||||||
@@ -11810,6 +12024,9 @@ check_fakeip)
|
|||||||
check_zapret_runtime)
|
check_zapret_runtime)
|
||||||
check_zapret_runtime
|
check_zapret_runtime
|
||||||
;;
|
;;
|
||||||
|
check_zapret2_runtime)
|
||||||
|
check_zapret2_runtime
|
||||||
|
;;
|
||||||
check_byedpi_runtime)
|
check_byedpi_runtime)
|
||||||
check_byedpi_runtime
|
check_byedpi_runtime
|
||||||
;;
|
;;
|
||||||
@@ -11852,6 +12069,9 @@ get_sing_box_status)
|
|||||||
get_zapret_status)
|
get_zapret_status)
|
||||||
get_zapret_status
|
get_zapret_status
|
||||||
;;
|
;;
|
||||||
|
get_zapret2_status)
|
||||||
|
get_zapret2_status
|
||||||
|
;;
|
||||||
get_byedpi_status)
|
get_byedpi_status)
|
||||||
get_byedpi_status
|
get_byedpi_status
|
||||||
;;
|
;;
|
||||||
@@ -11885,6 +12105,9 @@ global_check)
|
|||||||
validate_nfqws_strategy_json)
|
validate_nfqws_strategy_json)
|
||||||
validate_nfqws_strategy_json "${2:-}"
|
validate_nfqws_strategy_json "${2:-}"
|
||||||
;;
|
;;
|
||||||
|
validate_nfqws2_strategy_json)
|
||||||
|
validate_nfqws2_strategy_json "${2:-}"
|
||||||
|
;;
|
||||||
validate_byedpi_strategy_json)
|
validate_byedpi_strategy_json)
|
||||||
validate_byedpi_strategy_json "${2:-}"
|
validate_byedpi_strategy_json "${2:-}"
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -97,6 +97,26 @@ ZAPRET_DESYNC_MARK_POSTNAT="0x20000000"
|
|||||||
ZAPRET_LEGACY_DEFAULT_NFQWS_OPT="--filter-tcp=80 <HOSTLIST> --dpi-desync=fake,fakedsplit --dpi-desync-autottl=2 --dpi-desync-fooling=badsum --new --filter-tcp=443 --hostlist=/opt/zapret/ipset/zapret-hosts-google.txt --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-repeats=11 --dpi-desync-fooling=badsum --dpi-desync-fake-tls-mod=rnd,dupsid,sni=www.google.com --new --filter-udp=443 --hostlist=/opt/zapret/ipset/zapret-hosts-google.txt --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin --new --filter-udp=443 <HOSTLIST_NOAUTO> --dpi-desync=fake --dpi-desync-repeats=11 --new --filter-tcp=443 <HOSTLIST> --dpi-desync=multidisorder --dpi-desync-split-pos=1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1"
|
ZAPRET_LEGACY_DEFAULT_NFQWS_OPT="--filter-tcp=80 <HOSTLIST> --dpi-desync=fake,fakedsplit --dpi-desync-autottl=2 --dpi-desync-fooling=badsum --new --filter-tcp=443 --hostlist=/opt/zapret/ipset/zapret-hosts-google.txt --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-repeats=11 --dpi-desync-fooling=badsum --dpi-desync-fake-tls-mod=rnd,dupsid,sni=www.google.com --new --filter-udp=443 --hostlist=/opt/zapret/ipset/zapret-hosts-google.txt --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin --new --filter-udp=443 <HOSTLIST_NOAUTO> --dpi-desync=fake --dpi-desync-repeats=11 --new --filter-tcp=443 <HOSTLIST> --dpi-desync=multidisorder --dpi-desync-split-pos=1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1"
|
||||||
ZAPRET_DEFAULT_NFQWS_OPT="--filter-tcp=80 --dpi-desync=fake,fakedsplit --dpi-desync-autottl=2 --dpi-desync-fooling=badsum --new --filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-repeats=11 --dpi-desync-fooling=badsum --dpi-desync-fake-tls-mod=rnd,dupsid,sni=www.google.com --new --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin"
|
ZAPRET_DEFAULT_NFQWS_OPT="--filter-tcp=80 --dpi-desync=fake,fakedsplit --dpi-desync-autottl=2 --dpi-desync-fooling=badsum --new --filter-tcp=443 --dpi-desync=fake,multidisorder --dpi-desync-split-pos=1,midsld --dpi-desync-repeats=11 --dpi-desync-fooling=badsum --dpi-desync-fake-tls-mod=rnd,dupsid,sni=www.google.com --new --filter-udp=443 --dpi-desync=fake --dpi-desync-repeats=11 --dpi-desync-fake-quic=/opt/zapret/files/fake/quic_initial_www_google_com.bin"
|
||||||
|
|
||||||
|
## Zapret2
|
||||||
|
ZAPRET2_PROVIDER_BASE_DIR="/opt/zapret2"
|
||||||
|
ZAPRET2_PROVIDER_NFQWS2_BIN="$ZAPRET2_PROVIDER_BASE_DIR/nfq2/nfqws2"
|
||||||
|
ZAPRET2_PROVIDER_FILES_DIR="$ZAPRET2_PROVIDER_BASE_DIR/files"
|
||||||
|
ZAPRET2_PROVIDER_IPSET_DIR="$ZAPRET2_PROVIDER_BASE_DIR/ipset"
|
||||||
|
ZAPRET2_PROVIDER_LUA_DIR="$ZAPRET2_PROVIDER_BASE_DIR/lua"
|
||||||
|
ZAPRET2_NFQWS2_BIN="$ZAPRET2_PROVIDER_NFQWS2_BIN"
|
||||||
|
ZAPRET2_STATE_DIR="/var/run/podkop-plus/zapret2"
|
||||||
|
ZAPRET2_PID_DIR="$ZAPRET2_STATE_DIR/pid"
|
||||||
|
ZAPRET2_CHILD_PID_DIR="$ZAPRET2_STATE_DIR/child-pid"
|
||||||
|
ZAPRET2_LOG_DIR="$ZAPRET2_STATE_DIR/log"
|
||||||
|
ZAPRET2_ROUTE_MARK_BASE="0x01100000"
|
||||||
|
# Keep zapret2 queues outside the zapret provider range (4000-4255).
|
||||||
|
ZAPRET2_QUEUE_BASE=4300
|
||||||
|
ZAPRET2_QUEUE_RANGE_SIZE=256
|
||||||
|
ZAPRET2_NFQWS2_RESPAWN_DELAY=5
|
||||||
|
ZAPRET2_DESYNC_MARK="0x40000000"
|
||||||
|
ZAPRET2_DESYNC_MARK_POSTNAT="0x20000000"
|
||||||
|
ZAPRET2_DEFAULT_NFQWS2_OPT="--filter-tcp=80 --filter-l7=http --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 --new --filter-tcp=443 --filter-l7=tls --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld --new --filter-udp=443 --filter-l7=quic --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6"
|
||||||
|
|
||||||
## ByeDPI
|
## ByeDPI
|
||||||
BYEDPI_BIN="/usr/bin/ciadpi"
|
BYEDPI_BIN="/usr/bin/ciadpi"
|
||||||
BYEDPI_SERVICE_INIT="/etc/init.d/byedpi"
|
BYEDPI_SERVICE_INIT="/etc/init.d/byedpi"
|
||||||
|
|||||||
@@ -345,6 +345,45 @@ function byedpi_asset_matches(name, arch, ext) {
|
|||||||
(str_contains(name, "_" + arch + "." + ext) || str_contains(name, "-" + arch + "." + ext));
|
(str_contains(name, "_" + arch + "." + ext) || str_contains(name, "-" + arch + "." + ext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function release_asset_matches_arch(name, prefix, arch, ext) {
|
||||||
|
return (str_startswith(name, prefix + "_") || str_startswith(name, prefix + "-")) &&
|
||||||
|
str_endswith(name, "." + ext) &&
|
||||||
|
(str_contains(name, "_" + arch + "." + ext) || str_contains(name, "-" + arch + "." + ext));
|
||||||
|
}
|
||||||
|
|
||||||
|
function named_release_select_asset(release_prefix, asset_prefix, asset_ext, arch_candidates) {
|
||||||
|
let releases = array_or_empty(read_stdin_json());
|
||||||
|
|
||||||
|
for (let release in releases) {
|
||||||
|
if (type(release) != "object")
|
||||||
|
continue;
|
||||||
|
if (release.draft === true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let release_name = as_string(release.name || "");
|
||||||
|
if (!str_startswith(release_name, release_prefix))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (let arch in split(as_string(arch_candidates), " ")) {
|
||||||
|
if (arch == "")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (let asset in array_or_empty(release.assets)) {
|
||||||
|
if (type(asset) != "object")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
let name = as_string(asset.name || "");
|
||||||
|
let url = as_string(asset.browser_download_url || "");
|
||||||
|
if (url != "" && release_asset_matches_arch(name, asset_prefix, arch, asset_ext)) {
|
||||||
|
print(arch, "\t", name, "\t", url, "\t",
|
||||||
|
as_string(release.html_url || ""), "\t", as_string(release.tag_name || ""), "\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function select_byedpi_asset_from_release(release, asset_ext, arch_candidates) {
|
function select_byedpi_asset_from_release(release, asset_ext, arch_candidates) {
|
||||||
for (let arch in split(as_string(arch_candidates), " ")) {
|
for (let arch in split(as_string(arch_candidates), " ")) {
|
||||||
if (arch == "")
|
if (arch == "")
|
||||||
@@ -427,11 +466,13 @@ function system_info_json() {
|
|||||||
sing_box_extended: arg_number(ARGV[5]),
|
sing_box_extended: arg_number(ARGV[5]),
|
||||||
zapret_version: as_string(ARGV[6]),
|
zapret_version: as_string(ARGV[6]),
|
||||||
zapret_installed: arg_number(ARGV[7]),
|
zapret_installed: arg_number(ARGV[7]),
|
||||||
byedpi_version: as_string(ARGV[8]),
|
zapret2_version: as_string(ARGV[8]),
|
||||||
byedpi_installed: arg_number(ARGV[9]),
|
zapret2_installed: arg_number(ARGV[9]),
|
||||||
openwrt_version: as_string(ARGV[10]),
|
byedpi_version: as_string(ARGV[10]),
|
||||||
device_model: as_string(ARGV[11]),
|
byedpi_installed: arg_number(ARGV[11]),
|
||||||
generated_at: arg_number(ARGV[12])
|
openwrt_version: as_string(ARGV[12]),
|
||||||
|
device_model: as_string(ARGV[13]),
|
||||||
|
generated_at: arg_number(ARGV[14])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -932,6 +973,8 @@ else if (mode == "release-asset-name-by-suffix")
|
|||||||
release_asset_name_by_suffix(ARGV[1]);
|
release_asset_name_by_suffix(ARGV[1]);
|
||||||
else if (mode == "release-asset-url-by-suffix")
|
else if (mode == "release-asset-url-by-suffix")
|
||||||
release_asset_url_by_suffix(ARGV[1]);
|
release_asset_url_by_suffix(ARGV[1]);
|
||||||
|
else if (mode == "named-release-select-asset")
|
||||||
|
named_release_select_asset(ARGV[1], ARGV[2], ARGV[3], ARGV[4]);
|
||||||
else if (mode == "byedpi-select-asset")
|
else if (mode == "byedpi-select-asset")
|
||||||
byedpi_select_asset(ARGV[1], ARGV[2], ARGV[3]);
|
byedpi_select_asset(ARGV[1], ARGV[2], ARGV[3]);
|
||||||
else if (mode == "sing-box-extended-release-tag")
|
else if (mode == "sing-box-extended-release-tag")
|
||||||
|
|||||||
@@ -225,6 +225,44 @@ function zapret_check(installed, package_installed, provider_path) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function zapret2_status(args) {
|
||||||
|
write_json({
|
||||||
|
installed: bool_arg(args[0]),
|
||||||
|
package_installed: bool_arg(args[1]),
|
||||||
|
provider_available: bool_arg(args[2]),
|
||||||
|
provider_path: as_string(args[3]),
|
||||||
|
files_available: bool_arg(args[4]),
|
||||||
|
ipset_available: bool_arg(args[5]),
|
||||||
|
version: as_string(args[6]),
|
||||||
|
configured: bool_arg(args[7]),
|
||||||
|
enabled_rule_count: int_arg(args[8]),
|
||||||
|
expected_process_count: int_arg(args[9]),
|
||||||
|
running_process_count: int_arg(args[10]),
|
||||||
|
supervisor_process_count: int_arg(args[11]),
|
||||||
|
standalone_service_enabled: bool_arg(args[12]),
|
||||||
|
standalone_service_running: bool_arg(args[13]),
|
||||||
|
standalone_config_present: bool_arg(args[14]),
|
||||||
|
standalone_conflict: bool_arg(args[15]),
|
||||||
|
luci_app_installed: bool_arg(args[16]),
|
||||||
|
queue_base: int_arg(args[17]),
|
||||||
|
queue_range_end: int_arg(args[18]),
|
||||||
|
queue_overlap: bool_arg(args[19]),
|
||||||
|
ready: bool_arg(args[20]),
|
||||||
|
conflict: bool_arg(args[21]),
|
||||||
|
outbounds_configured: bool_arg(args[22]),
|
||||||
|
routes_configured: bool_arg(args[23]),
|
||||||
|
status_message: as_string(args[24])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function zapret2_check(installed, package_installed, provider_path) {
|
||||||
|
write_json({
|
||||||
|
zapret2_installed: bool_arg(installed),
|
||||||
|
zapret2_package_installed: bool_arg(package_installed),
|
||||||
|
zapret2_provider_path: as_string(provider_path)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let mode = ARGV[0] || "";
|
let mode = ARGV[0] || "";
|
||||||
|
|
||||||
if (mode == "byedpi-validation")
|
if (mode == "byedpi-validation")
|
||||||
@@ -249,6 +287,10 @@ else if (mode == "zapret-status")
|
|||||||
zapret_status(slice(ARGV, 1));
|
zapret_status(slice(ARGV, 1));
|
||||||
else if (mode == "zapret-check")
|
else if (mode == "zapret-check")
|
||||||
zapret_check(ARGV[1], ARGV[2], ARGV[3]);
|
zapret_check(ARGV[1], ARGV[2], ARGV[3]);
|
||||||
|
else if (mode == "zapret2-status")
|
||||||
|
zapret2_status(slice(ARGV, 1));
|
||||||
|
else if (mode == "zapret2-check")
|
||||||
|
zapret2_check(ARGV[1], ARGV[2], ARGV[3]);
|
||||||
else {
|
else {
|
||||||
warn("Usage: provider_status.uc <operation> ...\n");
|
warn("Usage: provider_status.uc <operation> ...\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ UPDATES_ZAPRET_PACKAGE_FILE=""
|
|||||||
UPDATES_ZAPRET_PACKAGE_NAME=""
|
UPDATES_ZAPRET_PACKAGE_NAME=""
|
||||||
UPDATES_ZAPRET_PACKAGE_VERSION=""
|
UPDATES_ZAPRET_PACKAGE_VERSION=""
|
||||||
UPDATES_ZAPRET_RELEASE_URL=""
|
UPDATES_ZAPRET_RELEASE_URL=""
|
||||||
|
UPDATES_ZAPRET2_ARCH=""
|
||||||
|
UPDATES_ZAPRET2_BUNDLE_URL=""
|
||||||
|
UPDATES_ZAPRET2_BUNDLE_NAME=""
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_FILE=""
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_NAME=""
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_VERSION=""
|
||||||
|
UPDATES_ZAPRET2_RELEASE_URL=""
|
||||||
UPDATES_BYEDPI_ARCH=""
|
UPDATES_BYEDPI_ARCH=""
|
||||||
UPDATES_BYEDPI_PACKAGE_URL=""
|
UPDATES_BYEDPI_PACKAGE_URL=""
|
||||||
UPDATES_BYEDPI_PACKAGE_NAME=""
|
UPDATES_BYEDPI_PACKAGE_NAME=""
|
||||||
@@ -146,9 +153,11 @@ updates_fail() {
|
|||||||
local message="$3"
|
local message="$3"
|
||||||
local current_version="${4:-}"
|
local current_version="${4:-}"
|
||||||
local latest_version="${5:-}"
|
local latest_version="${5:-}"
|
||||||
|
local status="${6:-}"
|
||||||
|
local release_url="${7:-}"
|
||||||
|
|
||||||
updates_log "$message" "error"
|
updates_log "$message" "error"
|
||||||
updates_json_response false "$component" "$action" "$message" "$current_version" "$latest_version" 0
|
updates_json_response false "$component" "$action" "$message" "$current_version" "$latest_version" 0 "$status" "$release_url"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1020,6 +1029,8 @@ updates_extract_arch_package_version() {
|
|||||||
version="$(printf '%s\n' "$package_name" | sed 's/\.ipk$//;s/\.apk$//')"
|
version="$(printf '%s\n' "$package_name" | sed 's/\.ipk$//;s/\.apk$//')"
|
||||||
|
|
||||||
case "$version" in
|
case "$version" in
|
||||||
|
zapret2_*) version="${version#zapret2_}" ;;
|
||||||
|
zapret2-*) version="${version#zapret2-}" ;;
|
||||||
zapret_*) version="${version#zapret_}" ;;
|
zapret_*) version="${version#zapret_}" ;;
|
||||||
zapret-*) version="${version#zapret-}" ;;
|
zapret-*) version="${version#zapret-}" ;;
|
||||||
byedpi_*) version="${version#byedpi_}" ;;
|
byedpi_*) version="${version#byedpi_}" ;;
|
||||||
@@ -1184,6 +1195,63 @@ updates_download_and_extract_zapret_package() {
|
|||||||
[ -n "$UPDATES_ZAPRET_PACKAGE_VERSION" ] || UPDATES_ZAPRET_PACKAGE_VERSION="$(updates_extract_arch_package_version "$UPDATES_ZAPRET_PACKAGE_NAME" "$UPDATES_ZAPRET_ARCH")"
|
[ -n "$UPDATES_ZAPRET_PACKAGE_VERSION" ] || UPDATES_ZAPRET_PACKAGE_VERSION="$(updates_extract_arch_package_version "$UPDATES_ZAPRET_PACKAGE_NAME" "$UPDATES_ZAPRET_ARCH")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updates_resolve_zapret2_release() {
|
||||||
|
local releases_json resolved
|
||||||
|
|
||||||
|
UPDATES_ZAPRET2_ARCH=""
|
||||||
|
UPDATES_ZAPRET2_BUNDLE_URL=""
|
||||||
|
UPDATES_ZAPRET2_BUNDLE_NAME=""
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_VERSION=""
|
||||||
|
UPDATES_ZAPRET2_RELEASE_URL=""
|
||||||
|
|
||||||
|
releases_json="$(updates_fetch_github_releases_json "remittor" "zapret-openwrt" 30)" || return 1
|
||||||
|
|
||||||
|
resolved="$(
|
||||||
|
printf '%s' "$releases_json" |
|
||||||
|
json_utils_ucode named-release-select-asset "zapret2 " "zapret2" "zip" "$UPDATES_ARCH_CANDIDATES" 2>/dev/null
|
||||||
|
)"
|
||||||
|
[ -n "$resolved" ] || return 1
|
||||||
|
|
||||||
|
UPDATES_ZAPRET2_ARCH="$(printf '%s\n' "$resolved" | cut -f1)"
|
||||||
|
UPDATES_ZAPRET2_BUNDLE_NAME="$(printf '%s\n' "$resolved" | cut -f2)"
|
||||||
|
UPDATES_ZAPRET2_BUNDLE_URL="$(printf '%s\n' "$resolved" | cut -f3)"
|
||||||
|
UPDATES_ZAPRET2_RELEASE_URL="$(printf '%s\n' "$resolved" | cut -f4)"
|
||||||
|
[ -n "$UPDATES_ZAPRET2_ARCH" ] || return 1
|
||||||
|
[ -n "$UPDATES_ZAPRET2_BUNDLE_NAME" ] || return 1
|
||||||
|
[ -n "$UPDATES_ZAPRET2_BUNDLE_URL" ] || return 1
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_VERSION="$(updates_extract_zapret2_bundle_version "$UPDATES_ZAPRET2_BUNDLE_NAME")"
|
||||||
|
[ -n "$UPDATES_ZAPRET2_PACKAGE_VERSION" ] || UPDATES_ZAPRET2_PACKAGE_VERSION="$(printf '%s\n' "$UPDATES_ZAPRET2_BUNDLE_NAME" | sed 's/\.zip$//')"
|
||||||
|
}
|
||||||
|
|
||||||
|
updates_download_and_extract_zapret2_package() {
|
||||||
|
local bundle_file inner_package_path
|
||||||
|
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_FILE=""
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_NAME=""
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_VERSION=""
|
||||||
|
|
||||||
|
bundle_file="$UPDATES_TMP_DIR/$UPDATES_ZAPRET2_BUNDLE_NAME"
|
||||||
|
updates_download_with_retry "$UPDATES_ZAPRET2_BUNDLE_URL" "$bundle_file" "$UPDATES_ZAPRET2_BUNDLE_NAME" || return 1
|
||||||
|
|
||||||
|
if updates_is_apk; then
|
||||||
|
inner_package_path="$(unzip -l "$bundle_file" | awk '{print $4}' | grep -E '^apk/zapret2-.*\.apk$' | sed -n '1p')"
|
||||||
|
else
|
||||||
|
inner_package_path="$(unzip -l "$bundle_file" | awk '{print $4}' | grep -E "^zapret2_.*_${UPDATES_ZAPRET2_ARCH}\.ipk$" | sed -n '1p')"
|
||||||
|
[ -n "$inner_package_path" ] || inner_package_path="$(unzip -l "$bundle_file" | awk '{print $4}' | grep -E '^zapret2_.*\.ipk$' | sed -n '1p')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -n "$inner_package_path" ] || return 1
|
||||||
|
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_NAME="$(basename "$inner_package_path")"
|
||||||
|
UPDATES_ZAPRET2_PACKAGE_FILE="$UPDATES_TMP_DIR/$UPDATES_ZAPRET2_PACKAGE_NAME"
|
||||||
|
|
||||||
|
unzip -p "$bundle_file" "$inner_package_path" >"$UPDATES_ZAPRET2_PACKAGE_FILE" || return 1
|
||||||
|
[ -s "$UPDATES_ZAPRET2_PACKAGE_FILE" ] || return 1
|
||||||
|
|
||||||
|
[ -n "$UPDATES_ZAPRET2_PACKAGE_VERSION" ] || UPDATES_ZAPRET2_PACKAGE_VERSION="$(updates_extract_zapret2_bundle_version "$UPDATES_ZAPRET2_BUNDLE_NAME")"
|
||||||
|
[ -n "$UPDATES_ZAPRET2_PACKAGE_VERSION" ] || UPDATES_ZAPRET2_PACKAGE_VERSION="$(updates_extract_arch_package_version "$UPDATES_ZAPRET2_PACKAGE_NAME" "$UPDATES_ZAPRET2_ARCH")"
|
||||||
|
}
|
||||||
|
|
||||||
updates_resolve_byedpi_release() {
|
updates_resolve_byedpi_release() {
|
||||||
local response release_series asset_ext resolved
|
local response release_series asset_ext resolved
|
||||||
|
|
||||||
@@ -1230,6 +1298,13 @@ updates_disable_standalone_zapret_service() {
|
|||||||
updates_log_command "Disabling standalone zapret autostart" /etc/init.d/zapret disable || true
|
updates_log_command "Disabling standalone zapret autostart" /etc/init.d/zapret disable || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updates_disable_standalone_zapret2_service() {
|
||||||
|
[ -x /etc/init.d/zapret2 ] || return 0
|
||||||
|
|
||||||
|
updates_log_command "Stopping standalone zapret2 service" /etc/init.d/zapret2 stop || true
|
||||||
|
updates_log_command "Disabling standalone zapret2 autostart" /etc/init.d/zapret2 disable || true
|
||||||
|
}
|
||||||
|
|
||||||
updates_disable_standalone_byedpi_service() {
|
updates_disable_standalone_byedpi_service() {
|
||||||
[ -x /etc/init.d/byedpi ] || return 0
|
[ -x /etc/init.d/byedpi ] || return 0
|
||||||
|
|
||||||
@@ -1272,6 +1347,43 @@ updates_install_zapret() {
|
|||||||
updates_success "zapret" "$action" "zapret package has been installed" "$current_version" "$UPDATES_ZAPRET_PACKAGE_VERSION" 1 "latest"
|
updates_success "zapret" "$action" "zapret package has been installed" "$current_version" "$UPDATES_ZAPRET_PACKAGE_VERSION" 1 "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updates_install_zapret2() {
|
||||||
|
local action="$1"
|
||||||
|
local current_version installed normalized_current normalized_latest
|
||||||
|
|
||||||
|
updates_init_tmp_dir || updates_fail "zapret2" "$action" "Failed to create temporary directory"
|
||||||
|
updates_resolve_arch_candidates || updates_fail "zapret2" "$action" "Failed to detect package architecture"
|
||||||
|
updates_retry_resolve "Resolving zapret2 package" updates_resolve_zapret2_release ||
|
||||||
|
updates_fail "zapret2" "$action" "Failed to resolve zapret2 package for this router architecture"
|
||||||
|
|
||||||
|
installed=0
|
||||||
|
is_zapret2_installed && installed=1
|
||||||
|
current_version="$(get_zapret2_package_version)"
|
||||||
|
|
||||||
|
if [ "$action" = "check_update" ]; then
|
||||||
|
[ "$installed" -eq 1 ] ||
|
||||||
|
updates_fail "zapret2" "$action" "zapret2 is not installed" "$current_version" "$UPDATES_ZAPRET2_PACKAGE_VERSION" "" "$UPDATES_ZAPRET2_RELEASE_URL"
|
||||||
|
normalized_current="$(updates_normalize_zapret_version "$current_version")"
|
||||||
|
normalized_latest="$(updates_normalize_zapret_version "$UPDATES_ZAPRET2_PACKAGE_VERSION")"
|
||||||
|
updates_check_success_compared "zapret2" "$current_version" "$UPDATES_ZAPRET2_PACKAGE_VERSION" "$normalized_current" "$normalized_latest" "$UPDATES_ZAPRET2_RELEASE_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
updates_ensure_package_tool "unzip" "unzip" || updates_fail "zapret2" "$action" "Failed to install unzip"
|
||||||
|
updates_download_and_extract_zapret2_package ||
|
||||||
|
updates_fail "zapret2" "$action" "Failed to download zapret2 package" "$current_version" "$UPDATES_ZAPRET2_PACKAGE_VERSION" "" "$UPDATES_ZAPRET2_RELEASE_URL"
|
||||||
|
|
||||||
|
if ! updates_log_command "Installing zapret2 package $UPDATES_ZAPRET2_PACKAGE_NAME" updates_pkg_install_files "$UPDATES_ZAPRET2_PACKAGE_FILE"; then
|
||||||
|
updates_fail "zapret2" "$action" "Failed to install zapret2 package" "$current_version" "$UPDATES_ZAPRET2_PACKAGE_VERSION" "" "$UPDATES_ZAPRET2_RELEASE_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
updates_disable_standalone_zapret2_service
|
||||||
|
updates_restart_podkop_after_successful_change
|
||||||
|
updates_clear_version_caches
|
||||||
|
|
||||||
|
current_version="$(get_zapret2_package_version)"
|
||||||
|
updates_success "zapret2" "$action" "zapret2 package has been installed" "$current_version" "$UPDATES_ZAPRET2_PACKAGE_VERSION" 1 "latest" "$UPDATES_ZAPRET2_RELEASE_URL"
|
||||||
|
}
|
||||||
|
|
||||||
updates_install_byedpi() {
|
updates_install_byedpi() {
|
||||||
local action="$1"
|
local action="$1"
|
||||||
local current_version installed
|
local current_version installed
|
||||||
@@ -1436,6 +1548,17 @@ updates_extract_zapret_bundle_version() {
|
|||||||
printf '%s\n' "$version" | sed 's/^v//'
|
printf '%s\n' "$version" | sed 's/^v//'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updates_extract_zapret2_bundle_version() {
|
||||||
|
local bundle_name="$1"
|
||||||
|
local version
|
||||||
|
|
||||||
|
version="$(basename "$bundle_name" | sed -n 's/^zapret2_v\([^_][^_]*\)_.*/\1/p')"
|
||||||
|
[ -n "$version" ] || version="$(basename "$bundle_name" | sed -n 's/^zapret2_\([^_][^_]*\)_.*/\1/p')"
|
||||||
|
[ -n "$version" ] || version="$(updates_extract_zapret_bundle_version "$bundle_name")"
|
||||||
|
|
||||||
|
printf '%s\n' "$version" | sed 's/^v//'
|
||||||
|
}
|
||||||
|
|
||||||
updates_normalize_zapret_version() {
|
updates_normalize_zapret_version() {
|
||||||
printf '%s\n' "$1" |
|
printf '%s\n' "$1" |
|
||||||
sed 's/^v//;s/-r[0-9][0-9]*$//;s/+.*$//;s/[[:space:]].*$//'
|
sed 's/^v//;s/-r[0-9][0-9]*$//;s/+.*$//;s/[[:space:]].*$//'
|
||||||
@@ -1771,6 +1894,12 @@ component_action() {
|
|||||||
zapret:remove)
|
zapret:remove)
|
||||||
updates_remove_optional_component "zapret" "zapret" "zapret" is_zapret_installed get_zapret_package_version
|
updates_remove_optional_component "zapret" "zapret" "zapret" is_zapret_installed get_zapret_package_version
|
||||||
;;
|
;;
|
||||||
|
zapret2:check_update | zapret2:install)
|
||||||
|
updates_install_zapret2 "$action"
|
||||||
|
;;
|
||||||
|
zapret2:remove)
|
||||||
|
updates_remove_optional_component "zapret2" "zapret2" "zapret2" is_zapret2_installed get_zapret2_package_version
|
||||||
|
;;
|
||||||
byedpi:check_update | byedpi:install)
|
byedpi:check_update | byedpi:install)
|
||||||
updates_install_byedpi "$action"
|
updates_install_byedpi "$action"
|
||||||
;;
|
;;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user