From d3a69e6ec54a497719882374bbb795152fc9d016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=91=D0=BE=D0=B1?= =?UTF-8?q?=D1=8B=D1=80=D0=B5=D0=B2?= Date: Thu, 14 May 2026 21:06:37 +0300 Subject: [PATCH] docs: drop third-party names; simplify system panel README turnkey focus; remove BOT fields and yaskad label; neutral iptables comments; default SERVICE_UNITS without bot units. Co-authored-by: Cursor --- README.md | 128 +++++++++++++++++++------------------------ install.sh | 2 +- kaskad_store.py | 6 +- static/dashboard.js | 4 +- system_info.py | 36 ++++-------- templates/index.html | 2 +- 6 files changed, 75 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index a957251..76e3ea9 100644 --- a/README.md +++ b/README.md @@ -1,109 +1,95 @@ -# kaskad_web_vpn — Kaskad Web UI v2 +# kaskad_web_vpn — каскад NAT под ключ -Веб-панель на **Flask** с **HTTP Basic Auth**: дашборд в духе «каскада» — **Система**, **Сервисы**, CRUD **NAT / DNAT**, сырые **iptables**. Это **отдельная открытая реализация** под ваш GitHub: без пунктов меню PROMO/«anten-ka», без телеграм-бота и терминального `gokaskad` из коммерческого Kaskad PRO; зато установка **curl | bash** с этого репозитория и понятный NAT для AmneziaWG / TCP по схеме «RU VPS → DNAT → зарубежный сервер». +Веб-панель на **Flask** с **HTTP Basic Auth**: **каскад** (DNAT UDP/TCP с российского VPS на зарубежный узел AmneziaWG / WireGuard / TCP), блок **Система**, **Сервисы**, таблица правил и вывод **iptables**. Установка одной командой с **вашего** репозитория GitHub. Репозиторий: [github.com/andrey271192/kaskad_web_vpn](https://github.com/andrey271192/kaskad_web_vpn) +## Установка под ключ + +На VPS под root: + +```bash +curl -fsSL https://raw.githubusercontent.com/andrey271192/kaskad_web_vpn/main/install.sh | sudo bash +``` + +Дальше откройте в браузере **`http://:8088/setup`** и задайте пароль (или передайте **`ADMIN_PASSWORD`** при установке — см. ниже). + +Удаление: + +```bash +curl -fsSL https://raw.githubusercontent.com/andrey271192/kaskad_web_vpn/main/uninstall.sh | sudo bash +``` + ## Первый вход и пароль -- **По умолчанию** скрипт установки **не** задаёт пароль в Docker: откройте в браузере **`http://<ваш_IP>:<порт>/setup`**, придумайте пароль (≥ 8 символов) и логин (часто оставляют `user1`). Хэш сохраняется в томе: **`/var/lib/kaskad/web_auth.json`**. -- Чтобы задать пароль сразу при установке: **`ADMIN_PASSWORD`** или файл **`PASSWORD_FILE`** — тогда шаг `/setup` не нужен. -- Как раньше (случайный пароль в файл): **`FORCE_RANDOM_PASSWORD=1`**. -- Если заданы **`BASIC_AUTH_PASSWORD`** / **`ADMIN_PASSWORD`**, используется они (перекрывают файл). +- По умолчанию пароль **не** подставляется в Docker: страница **`/setup`** (файл **`/var/lib/kaskad/web_auth.json`** на томе). +- Готовый пароль при установке: **`ADMIN_PASSWORD='…'`** или файл **`PASSWORD_FILE`**. +- Случайный пароль в файл: **`FORCE_RANDOM_PASSWORD=1`**. -## NAT и совместимость с логикой Kaskad PRO +## Как устроен NAT -Переменная **`KASKAD_IPTABLES_MODE`** (в контейнере, install передаёт **`compat`** по умолчанию): +Переменная **`KASKAD_IPTABLES_MODE`** (install передаёт **`compat`** по умолчанию): -| Значение | Поведение | -|----------|-----------| -| **`compat`** (по умолчанию) | Как в Kaskad PRO: **DNAT** в **`nat/PREROUTING`**, **INPUT** и парой правил **FORWARD** с комментарием **`kaskad:PORT:proto`**, один раз **MASQUERADE** на исходящем интерфейсе (авто через `ip route` или **`KASKAD_OUT_IFACE`**). | -| **`chain`** | Старая схема: отдельная цепочка **`nat/KASKAD_WEB`** и jump из PREROUTING. | +| Значение | Описание | +|----------|----------| +| **`compat`** | Классический каскад: **DNAT** в **`nat/PREROUTING`**, правила **INPUT** и **FORWARD** с меткой **`kaskad:PORT:proto`**, **MASQUERADE** на исходящем интерфейсе (авто или **`KASKAD_OUT_IFACE`**). | +| **`chain`** | Отдельная цепочка **`nat/KASKAD_WEB`** и переход из PREROUTING. | -Нужны **`net.ipv4.ip_forward=1`** и достаточное место на диске под Docker. - -Установка по умолчанию: **`--network host`** и **`--privileged`**, чтобы правила применялись к **таблицам хоста**. Данные правил: **`KASKAD_DATA_DIR`** → `/var/lib/kaskad/rules.json`. - -Попытка сохранить правила в **`netfilter-persistent`**, если установлен на хосте. +Нужно **`net.ipv4.ip_forward=1`**. Контейнер обычно с **`--network host`** и **`--privileged`**. Данные правил: **`KASKAD_DATA_DIR`** → `rules.json`. ## Требования -- Linux с Docker (для NAT — host network + privileged). -- По желанию **`/var/run/docker.sock`** (чтобы в «Сервисах» отображался статус контейнера как `kaskad-web.service`). +- Linux, Docker, для NAT — host network и privileged (как в скрипте). -## Сборка образа: «invalid signature» / apt - -См. блок в Wiki ниже — типично кэш builder, прокси, диск, время. +## Если сборка образа ругается на подпись apt ```bash docker builder prune -af docker build --pull --no-cache -t kaskad-web-vpn:test . ``` -В Dockerfile зеркала APT переведены на HTTPS. +Проверьте время (`date -u`), место на диске, при необходимости отключите HTTP-прокси при сборке. -## Установка одной командой +## Переменные install.sh -```bash -curl -fsSL https://raw.githubusercontent.com/andrey271192/kaskad_web_vpn/main/install.sh | sudo bash -``` +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| `HOST_PORT` | `8088` | порт HTTP | +| `KASKAD_HOST_NETWORK` | `1` | host network / или `-p` | +| `KASKAD_DATA_DIR` | `/var/lib/kaskad` | том данных | +| `KASKAD_IPTABLES_MODE` | `compat` | `compat` или `chain` | +| `ADMIN_PASSWORD` | — | пароль без `/setup` | +| `FORCE_RANDOM_PASSWORD` | `0` | автопароль в `PASSWORD_FILE` | +| `PASSWORD_FILE` | `/root/kaskad_web.initial-password` | чтение/запись пароля | +| `BASIC_AUTH_USER` | `user1` | логин при env-пароле | +| `PANEL_URL` | — | доп. ссылка в шапке | +| `KASKAD_REPO` | `andrey271192/kaskad_web_vpn` | откуда качать исходники | -Затем откройте **`/setup`** или задайте пароль при установке: +## Переменные приложения + +| Переменная | Описание | +|------------|----------| +| `KASKAD_UI_VERSION` | строка версии в блоке «Система» | +| `SERVICE_UNITS` | CSV systemd-юнитов для таблицы (первые строки); третья строка может быть статусом Docker-контейнера панели | +| `DOCKER_WEB_CONTAINER`, `DOCKER_WEB_DISPLAY_UNIT` | контейнер и подпись в «Сервисах» | +| `KASKAD_OUT_IFACE` | интерфейс для MASQUERADE | +| `WEB_AUTH_JSON` | путь к файлу пароля веб-интерфейса | + +Примеры установки с паролем и портом: ```bash curl -fsSL https://raw.githubusercontent.com/andrey271192/kaskad_web_vpn/main/install.sh | sudo \ env ADMIN_PASSWORD='ваш_секрет' HOST_PORT=8443 bash ``` -Старый режим «случайный пароль в файл»: - -```bash -curl -fsSL https://raw.githubusercontent.com/andrey271192/kaskad_web_vpn/main/install.sh | sudo \ - env FORCE_RANDOM_PASSWORD=1 bash -``` - -### Переменные install.sh - -| Переменная | По умолчанию | Описание | -|------------|--------------|----------| -| `HOST_PORT` | `8088` | HTTP-порт | -| `KASKAD_HOST_NETWORK` | `1` | host network / или `-p` | -| `KASKAD_DATA_DIR` | `/var/lib/kaskad` | том данных | -| `KASKAD_IPTABLES_MODE` | `compat` | `compat` или `chain` | -| `ADMIN_PASSWORD` | — | пароль без `/setup` | -| `FORCE_RANDOM_PASSWORD` | `0` | `1` — автопароль в `PASSWORD_FILE` | -| `PASSWORD_FILE` | `/root/kaskad_web.initial-password` | при FORCE_RANDOM или чтении пароля | -| `BASIC_AUTH_USER` | `user1` | логин при использовании env-пароля | -| `PANEL_URL` | — | ссылка в шапке | - -### Переменные приложения - -| Переменная | Описание | -|------------|----------| -| `BOT_TOKEN`, `BOT_CHAT_ID` | только отображение в «Системе» (маска), без бота | -| `SERVICE_UNITS`, `DOCKER_WEB_*` | таблица сервисов | -| `KASKAD_OUT_IFACE` | исходящий интерфейс для MASQUERADE | -| `WEB_AUTH_JSON` | путь к `web_auth.json` | - -## Удаление контейнера - -```bash -curl -fsSL https://raw.githubusercontent.com/andrey271192/kaskad_web_vpn/main/uninstall.sh | sudo bash -``` - -Режим **`chain`**: удаление jump в **`KASKAD_WEB`** см. исторический README в git. - -Режим **`compat`**: проще снять правила через панель (удалить клиентов) или выборочно удалять строки с **`kaskad:`** в `iptables -S INPUT/FORWARD` и соответствующие DNAT в `iptables -t nat -S PREROUTING`. - -## Локально без Docker +## Локальный запуск (без Docker) ```bash pip install -r requirements.txt -# либо задайте BASIC_AUTH_PASSWORD, либо откройте /setup sudo -E env PATH="$PATH" flask --app app run --host 0.0.0.0 --port 8088 ``` -`GET /health` без авторизации. `GET /api/meta` — флаг `needs_setup`, режим iptables. +`GET /health` без авторизации. `GET /api/meta` — `needs_setup`, режим iptables. ## API diff --git a/install.sh b/install.sh index 8bc4669..17c748e 100755 --- a/install.sh +++ b/install.sh @@ -123,5 +123,5 @@ if [[ "${#AUTH_ENV_ARGS[@]}" -gt 0 ]]; then else echo " Пароль: создайте на странице /setup при первом открытии." fi -echo " NAT: режим ${KASKAD_IPTABLES_MODE:-compat} (compat ≈ Kaskad PRO), данные: ${KASKAD_DATA_DIR}" +echo " NAT: режим ${KASKAD_IPTABLES_MODE:-compat}, данные: ${KASKAD_DATA_DIR}" echo " Рекомендуется: sysctl net.ipv4.ip_forward=1." diff --git a/kaskad_store.py b/kaskad_store.py index 41ea87a..924d46e 100644 --- a/kaskad_store.py +++ b/kaskad_store.py @@ -1,8 +1,8 @@ """Хранение правил NAT и синхронизация с iptables. Режимы (KASKAD_IPTABLES_MODE): -- compat — как Kaskad PRO: DNAT в PREROUTING, INPUT/FORWARD с комментарием kaskad:PORT:proto, MASQUERADE. -- chain — отдельная цепочка nat/KASKAD_WEB (старый вариант). +- compat — DNAT в PREROUTING, INPUT/FORWARD с комментарием kaskad:PORT:proto, MASQUERADE. +- chain — отдельная цепочка nat/KASKAD_WEB (альтернатива). """ from __future__ import annotations @@ -184,7 +184,7 @@ def _flush_matching_rules(table: str | None, chain: str, predicate) -> None: def compat_remove_rule(proto: str, in_port: int) -> None: - """Убирает DNAT + INPUT/FORWARD как в Kaskad PRO.""" + """Удаляет связанные DNAT и правила filter по порту/протоколу.""" cm = _kaskad_comment(in_port, proto) def pred_nat(rest: str) -> bool: diff --git a/static/dashboard.js b/static/dashboard.js index b302f8d..56b5edb 100644 --- a/static/dashboard.js +++ b/static/dashboard.js @@ -35,9 +35,7 @@ ["Load", data.load], ["Mem", data.mem], ["IPADDR / IPv4", String(data.ipaddrs || "").replace(/\n/g, "
")], - ["yaskad", data.yaskad_version], - ["BOT_TOKEN", data.bot_token_masked], - ["BOT_CHAT_ID", data.bot_chat_masked], + ["Версия UI", data.ui_version], ]; g.innerHTML = cells .map(function (kv) { diff --git a/system_info.py b/system_info.py index b8f96ee..cae3184 100644 --- a/system_info.py +++ b/system_info.py @@ -89,12 +89,17 @@ def _ipv4_addrs() -> str: return "\n".join(lines) if lines else "—" -def mask_secret(val: str, keep_start: int = 4, keep_end: int = 2) -> str: - if not val: - return "—" - if len(val) <= keep_start + keep_end: - return "***" - return val[:keep_start] + "…" + val[-keep_end:] +def collect_system_payload() -> dict: + ui_ver = os.environ.get("KASKAD_UI_VERSION", "v2.2").strip() + + return { + "machine_id": _read_machine_id(), + "uptime": _uptime_h(), + "load": _load_avg(), + "mem": _mem_mb(), + "ipaddrs": _ipv4_addrs(), + "ui_version": ui_ver, + } def systemd_unit_row(unit: str) -> dict[str, str]: @@ -156,27 +161,10 @@ def docker_container_row(name: str, display_unit: str | None = None) -> dict[str return row -def collect_system_payload() -> dict: - ui_ver = os.environ.get("KASKAD_UI_VERSION", "v2.2").strip() - bot_token = os.environ.get("BOT_TOKEN", "") - bot_chat = os.environ.get("BOT_CHAT_ID", "") - - return { - "machine_id": _read_machine_id(), - "uptime": _uptime_h(), - "load": _load_avg(), - "mem": _mem_mb(), - "ipaddrs": _ipv4_addrs(), - "yaskad_version": ui_ver, - "bot_token_masked": mask_secret(bot_token), - "bot_chat_masked": mask_secret(bot_chat, 2, 2), - } - - def collect_services_rows() -> list[dict[str, str]]: units_csv = os.environ.get( "SERVICE_UNITS", - "kaskad_bot.service,kaskad-monitor.service,kaskad-web.service", + "dbus.service,systemd-networkd.service,kaskad-web.service", ) units = [u.strip() for u in units_csv.split(",") if u.strip()] docker_web = os.environ.get("DOCKER_WEB_CONTAINER", "").strip() diff --git a/templates/index.html b/templates/index.html index e876273..a9500fb 100644 --- a/templates/index.html +++ b/templates/index.html @@ -91,7 +91,7 @@ {% if iptables_mode == 'chain' %} Kaskad Web UI · kaskad_web_vpn · HTTP Basic Auth · DNAT в цепочке KASKAD_WEB (nat). {% else %} - Kaskad Web UI · kaskad_web_vpn · HTTP Basic Auth · режим как у Kaskad PRO: DNAT в PREROUTING, метки kaskad:PORT:proto в INPUT/FORWARD, MASQUERADE на исходящем интерфейсе (KASKAD_IPTABLES_MODE=compat). + Kaskad Web UI · kaskad_web_vpn · HTTP Basic Auth · каскад: DNAT в PREROUTING, метки kaskad:PORT:proto в INPUT/FORWARD, MASQUERADE (KASKAD_IPTABLES_MODE=compat). {% endif %}