Kaskad Platform

Платформа управления каскадным VPN.

Смысл проекта: клиент подключается к российскому входному серверу через WireGuard/AirGuard. Этот сервер не выпускает трафик напрямую, а пересылает его на один из зарубежных выходных серверов. Выходной сервер уже отправляет трафик в интернет. Если один зарубежный сервер недоступен, платформа может переключить маршрут на резервный сервер.

Что уже сделано

  • Создана FastAPI веб-панель.
  • Добавлены вкладки: обзор, клиенты, серверы, конфиги, настройки WireGuard.
  • Добавлен выпуск WireGuard ключей и клиентских .conf.
  • Добавлен выбор типа клиента: Обычный WireGuard, AmneziaWG 2.0, AmneziaWG Legacy.
  • Добавлены дефолтные параметры AmneziaWG 2.0: S3/S4, H1-H4 ranges, I1 DNS-signature.
  • Добавлено скачивание клиентских конфигов.
  • Добавлена видимость активности клиентов: online/offline, последний handshake, RX/TX.
  • Добавлен серверный конфиг RU entry.
  • Добавлены шаблоны конфигов для выходных серверов.
  • Добавлена установка выходного сервера по SSH.
  • Добавлена привязка клиента к конкретному выходу или авто-выбору.
  • Добавлена смена выходного сервера клиента после создания: Авто или конкретный exit.
  • Смена выхода клиента применяет runtime policy rule на RU сервере: IP клиента -> таблица выбранного exit.
  • Добавлены действия клиента: включить, выключить, удалить.
  • Добавлены действия exit: включить, выключить, удалить.
  • Добавлена проверка доступности выходных серверов через ping.
  • Добавлены метрики серверов: ping, CPU, RAM, входящий/исходящий канал exit, число клиентов, общий load score.
  • Добавлен режим выходов: резерв/failover или распределение клиентов по нагрузке.
  • Добавлен RU direct-routing: выбранные RU GeoIP CIDR/IP и GeoSite домены остаются на RU entry, остальное идет в каскад.
  • Добавлен WARP/WARP+ на выходных серверах: трафик после US/foreign exit может уходить через Cloudflare WARP.
  • Добавлена автопроверка выходных серверов раз в 60 секунд.
  • Добавлен авто-failover: если основной выход недоступен, выбирается доступный резерв.
  • Добавлен вход в веб-панель по логину/паролю.
  • Добавлена смена логина/пароля из панели.
  • Добавлено хранение состояния в JSON с правами 0600.
  • Добавлена модель каскада: клиент -> RU вход -> US/foreign выход.
  • Добавлены несколько RU входов: добавление, установка WireGuard/AmneziaWG по SSH, выбор входа при создании клиента.
  • Добавлен SSH key auth для установки RU/exit серверов: можно указать private key вместо пароля.
  • Добавлено сохранение SSH доступа серверов encrypted: нужно для CPU/RAM и WARP одной кнопкой.
  • Добавлен раздел $: даты отключения клиентов, expired-клиенты не участвуют в маршрутизации.
  • Добавлен выборочный $: клиент попадает в платный раздел только после нажатия $.
  • Добавлены поля платного раздела: комментарий и внешний адрес.
  • Добавлен Telegram bot alerts: offline/online клиенты/серверы и даты отключения.
  • Добавлена кнопка ручного failover.
  • Настроен systemd-сервис на сервере.

Где открывать

Веб-панель:

http://SERVER_IP:8000

Дефолтный вход:

admin / admin

Важно: это только первичный аварийный вход. Панель показывает красное предупреждение, пока admin/admin активен. Сразу смените логин и пароль в Настройки WG -> Доступ к панели. Новый пароль: минимум 8 символов.

Проверка API:

http://SERVER_IP:8000/api/health

Статус платформы:

http://SERVER_IP:8000/api/status

Как это должно работать в финальной версии

  1. В панели создается клиент.
  2. Платформа создает WireGuard/AirGuard учетную запись на российском входном сервере.
  3. Клиент получает конфиг и подключается к российскому серверу.
  4. Российский сервер выбирает зарубежный exit:
    • вручную
    • по пингу
    • по загрузке
    • по доступности
    • через failover
  5. Если RU direct включен, трафик на заданные RU CIDR/домены выходит напрямую через RU entry.
  6. Остальной трафик клиента идет по схеме:

Клиент -> российский входной сервер -> зарубежный выходной сервер -> интернет

Где настраивать

  • Клиенты: вкладка Клиенты. Там выбирается тип, RU вход, выход и дата отключения.
  • RU входы: вкладка Серверы -> блок RU вход. Выбери Только добавить в платформу или Установить по SSH, затем режим Обычный WireGuard вход или AmneziaWG вход.
  • Выход клиента: вкладка Клиенты, колонка Выход. Можно выбрать Авто или конкретный exit.
  • Даты отключения: вкладка $.
  • Комментарий и внешний адрес клиента: вкладка $.
  • Telegram уведомления: вкладка Настройки WG -> Telegram уведомления.
  • Активность клиентов: вкладка Клиенты, колонки Активен, Handshake, Трафик.
  • US/foreign серверы: вкладка Серверы. Там же Выключить, Включить, Удалить.
  • Авто-установка US/foreign серверов: вкладка Серверы -> Добавить и установить по SSH.
  • WARP/WARP+ для скрытия IP exit: вкладка Серверы -> WARP на выходе; обычный WARP можно включить кнопкой WARP в строке exit, если SSH сохранен.
  • Режим exit-серверов: вкладка Обзор -> Режим выходов.
  • RU direct-routing: вкладка Обзор -> блок RU direct.
  • Свой домен и нейтральный сайт на 80: вкладка Настройки WG -> Домен и сайт маскировки.
  • Бэкап/restore для переезда: отдельная вкладка Бэкап.
  • WireGuard сеть, порт, DNS, MTU: вкладка Настройки WG.
  • Логин/пароль панели: вкладка Настройки WG -> Доступ к панели.
  • Конфиги клиента, RU entry и exit-серверов: вкладка Конфиги.

Бэкап и переезд

Блок находится в отдельной вкладке Бэкап.

Что делает:

  • Скачать backup отдает полный state.json;
  • backup содержит приватные ключи клиентов/RU, SSH-секреты, Telegram token и настройки;
  • Восстановить из backup заменяет состояние панели целиком;
  • перед restore нужен текущий пароль панели;
  • после restore запускается нормализация state, чтобы новые поля появились автоматически.

Переезд на новый RU сервер:

  1. На старой панели скачать backup.
  2. Поднять чистую платформу на новом сервере.
  3. Открыть вкладку Бэкап.
  4. Выбрать backup JSON, ввести текущий пароль панели, нажать restore.
  5. Проверить wg-quick@kaskad-entry, AWG/Mieru и маршруты.
  6. Если у RU входа задан Домен для клиентов, направить DNS A-запись на новый IP.
  7. Нажать Сверить маршруты и проверить handshake клиентов.

Важно: backup — секретный файл. Не хранить в GitHub, не отправлять в чат, лучше держать encrypted.

Если клиентские конфиги выпущены с доменом RU входа (endpoint_host), при переезде достаточно восстановить backup на новом сервере и перевести DNS A-запись домена на новый IP. Клиенты переподключатся после обновления DNS/повторного handshake. Если в старых конфигах был IP, конфиги нужно скачать заново.

Свой домен и сайт на 80

Блок находится в Настройки WG -> Домен и сайт маскировки.

Рекомендуемое разделение DNS:

  • ru1.example.ru / ru2.example.ru — только Домен для клиентов у RU входа, попадает в Endpoint клиентских конфигов;
  • example.ru и www.example.ru — нейтральный сайт маскировки на 80/443;
  • Host/IP RU сервера остаётся IP для SSH, мониторинга и каскада.

Пример:

@    A    SERVER_IP
www  A    SERVER_IP
ru1  A    SERVER_IP

Что делает:

  • ставит нейтральный HTML-сайт на порт 80 выбранного сервера;
  • работает отдельно для каждого сервера: local, RU вход или US/foreign exit;
  • не ставит сайт автоматически после деплоя;
  • перед установкой проверяет порт 80;
  • если порт 80 занят чужим процессом, установка блокируется;
  • если порт 80 уже слушает nginx с чужим сайтом, установка без домена блокируется;
  • если домен указан, платформа добавляет отдельный nginx server_name.

Как поставить:

  1. Создать DNS A запись @ -> SERVER_IP.
  2. Опционально создать www -> SERVER_IP.
  3. Дождаться обновления DNS.
  4. В панели выбрать конкретный сервер.
  5. Ввести домен без http://, например example.ru.
  6. Нажать Установить сайт на 80.

Свой HTML:

  1. Выбрать .html или .htm файл.
  2. Нажать Добавить HTML сайт.
  3. Лимит файла: 1 MB.

Удаление:

  • Удалить сайт убирает symlink и nginx config /etc/nginx/sites-enabled/kaskad-platform-mask;
  • чужие nginx-конфиги и другие сайты не трогаются;
  • site_enabled=false сохраняется в состоянии платформы.

Важно:

  • HTML должен быть нейтральным: без секретов, токенов, приватных ссылок и внутренних адресов.
  • Default HTML не содержит слов про VPN/proxy/MTProxy/Telegram/название проекта.
  • Если nginx уже занят другим default-сайтом, домен должен смотреть на выбранный сервер и совпадать с server_name.
  • Если хотите сайт именно по IP без домена, порт 80 должен быть свободен.

Замер скорости выходов и переезды клиентов

Выход проверяется двумя способами: check_exit доказывает только достижимость (ICMP/TCP/SSH), а раз в THROUGHPUT_INTERVAL (300 с) через каскадный туннель каждого выхода тянется 10-мегабайтный файл и меряется реальная скорость.

  • зеркала перебираются по списку EXIT_PROBE_URLS, берётся максимум из успешных проб, а не первое попавшееся значение: медленное зеркало занижает оценку канала, а мёртвое (tele2 по HTTPS отдаёт 000) просто пропускается;
  • probe_mbps — медиана последних пяти замеров, одиночный выброс ничего не решает;
  • в degraded выход уходит после двух плохих замеров подряд (ниже EXIT_PROBE_MIN_MBPS = 12), а выходит только после двух хороших подряд и с запасом (EXIT_PROBE_RECOVER_MBPS = 18) — асимметрия не даёт ему мигать;
  • auto-клиент переезжает на более быстрый выход не чаще раза в EXIT_MOVE_COOLDOWN (30 минут), но с отказавшего выхода уезжает сразу.

Бесшовной смена выхода не бывает: у клиента меняется внешний IP и открытые TCP-сессии рвутся. Поэтому задача не «переехать незаметно», а не переезжать без причины — этим и заняты медиана, гистерезис и выдержка.

Уборка пиров без клиента

prune_orphan_peers() раз в цикл монитора сверяет пиров на kaskad-entry, kaskad-awg и kaskad-awg2 с ключами всех клиентов и снимает чужие: пир, которого нет ни у одного клиента, — это ключ удалённого клиента, и он продолжает пускать бывшего владельца в туннель. Каждая уборка пишется в журнал панели.

Тесты и боевая машина

Тесты гоняются в том числе на самом sber2, поэтому tests/conftest.py:

  • выставляет временный KASKAD_DATA_DIR до импорта server.main — иначе SNAPSHOT_DIR указывает на боевой data/backups и тесты пишут снимки туда;
  • подменяет subprocess.run для wg/awg/ip/nft/iptables/ipset/systemctl/sysctl — без этого прогон добавлял WireGuard-пиров в живой интерфейс (105 → 210 за два прогона);
  • изолирует live_interface_public_key, иначе автодетект видит живые kaskad-awg* и тесты «AWG не установлен» падают именно на боевой машине.

Метрики и режимы exit

В таблице Серверы для каждого выходного сервера показывается:

  • Ping — задержка до сервера через обычный ping.
  • CPU — загрузка CPU сервера.
  • RAM — загрузка RAM сервера.
  • Канал — текущий RX/TX Mbps по основному сетевому интерфейсу exit.
  • Клиенты — сколько клиентов сейчас закреплено за этим exit.
  • Load — общий score: клиенты + ping + RX/TX Mbps. Чем меньше, тем легче сервер.

Режимы:

  • Резерв: основной + запасные — используется основной exit. Если он offline, платформа выбирает доступный резерв.
  • Распределение по нагрузке — новый клиент с выбором Авто получает самый легкий доступный exit по Load.

Для CPU, RAM и Канал нужен SSH доступ панели к серверу. Если сервер установлен через панель, платформа кладет служебный public key и сохраняет SSH auth encrypted. Если сервер добавлен вручную, открой Серверы -> SSH доступ сервера, выбери сервер и сохрани пароль или private key. В API секрет не показывается.

Авто у клиента хранится как режим. Платформа выбирает фактический exit по текущей политике и показывает его строкой сейчас: .... Если exit выключен или удален, клиент автоматически уходит обратно в Авто.

RU direct-routing

RU direct нужен, когда российский трафик должен оставаться на RU сервере, а зарубежный трафик идти через US/foreign exit.

Как работает:

  • GeoIP CIDR/IP — IP или сети, например 77.88.0.0/16.
  • GeoSite домены — домены, например yandex.ru; платформа резолвит их в IPv4 и добавляет /32.
  • Включено: для каждого WireGuard-клиента платформа ставит правило выше каскада: from CLIENT_IP to RU_CIDR lookup main.
  • Выключено: direct-правила удаляются, весь трафик клиента идет в каскадный exit.

GeoSite — DNS-снимок на момент сохранения. Если IP у домена поменялся, нажмите Сохранить RU direct еще раз.

Несколько RU входов

Модель: каждый RU вход держит свои туннели к тем же US/foreign exit.

Пример:

  • RU-1 -> us1/us2/us3
  • RU-2 -> us1/us2/us3

В панели:

  • RU вход добавляется вручную или ставится по SSH.
  • Для AmneziaWG вход SSH installer ставит пакет amneziawg, создает /etc/wireguard/kaskad-entry.conf с AWG 2.0 параметрами и запускает awg-quick@kaskad-entry.
  • При создании клиента выбирается Вход.
  • Клиентский конфиг получает endpoint выбранного RU: Endpoint = RU_HOST:PORT.
  • В таблице клиентов видна колонка Вход.
  • В таблице серверов для RU входов видны status, ping, clients, load.

Важно: локальные runtime route rules применяются только к локальному RU entry, где запущена панель. Для нового удаленного RU входа панель ставит базовый wg-quick@kaskad-entry или awg-quick@kaskad-entry; peers/маршруты на удаленном RU нужно применять через его RU config после диагностики.

$ и даты отключения

Вкладка $ показывает клиентов и дату отключения.

  • Клиент попадает во вкладку $ после нажатия кнопки $ в строке клиента.
  • Пустая дата — клиент без срока.
  • Будущая дата — клиент активен.
  • Прошедшая дата — клиент expired, effective exit становится пустым, клиент не считается в нагрузке.
  • Для локального RU runtime rule удаляется автоматически.
  • Комментарий и Внешний адрес хранятся вручную в карточке оплаты.

Telegram уведомления

Блок находится в Настройки WG -> Telegram уведомления.

Поддерживается:

  • bot token, не показывается в /api/status;
  • chat id вручную или авто через getUpdates после /start боту;
  • предупреждение за N дней до даты отключения;
  • колокольчик на каждом клиенте.

Бот присылает:

  • RU/exit server offline и recovery online;
  • client offline и recovery online, если у клиента включен колокольчик;
  • скоро дата отключения;
  • дата отключения прошла.

Telegram бот: оплаты и админ-меню

Клиент:

  • /start -> присылает телефон из базы -> бот привязывает TG ID и показывает карточку подписки (аккаунт, телефон, протокол, выход, статус, окончание, осталось N дн.);
  • кнопки Оплатил и Проверить срок;
  • Оплатил создаёт нумерованную заявку Заявка на оплату #N и отправляет её админу.

Админ (chat_id из настроек Telegram):

  • /start или /admin показывает reply-меню: 📊 Отчёт за месяц, 💰 Кто оплатил, ⚠️ Не оплатили, ⏳ Ожидают оплаты, 📢 Рассылка, ❌ Отмена;
  • по заявке #N кнопки 30/60/90/180 дн. и ❌ Отклонить;
  • подтверждение продлевает все конфиги аккаунта и уведомляет клиента; защита от двойного подтверждения (pending -> processing -> approved);
  • 📢 Рассылка -> следующий текст уходит всем привязанным клиентам.

Заявки и счётчик хранятся в JSON state (payments, payment_seq); цены не считаются (статусы и сроки).

WARP / WARP+

Схема:

Клиент -> RU вход -> US/foreign exit -> Cloudflare WARP -> интернет

Зачем:

  • сайты видят Cloudflare WARP IP;
  • IP твоего US/foreign VPS скрыт за Cloudflare WARP;
  • все клиенты, которые идут через этот exit, получают один WARP-выход.

Как включить:

  1. Открыть Серверы.
  2. Если SSH доступ уже сохранен, нажать WARP в строке exit для обычного WARP.
  3. Для WARP+ или ручных исключений открыть блок WARP на выходе и выбрать exit.
  4. Выбрать WARP или WARP+.
  5. Для WARP+ указать license key. Он не сохраняется.
  6. Указать SSH доступ, если он еще не сохранен.
  7. Нажать Применить WARP.

Платформа ставит официальный cloudflare-warp, регистрирует клиент, включает warp-cli mode warp+doh, подключает WARP и показывает public IP. Для WARP+ используется warp-cli registration license <KEY>.

Защита от потери доступа:

  • RU входы добавляются в excluded routes;
  • текущий SSH client IP добавляется в excluded routes;
  • дополнительные исключения можно указать вручную.

Важно: Cloudflare WARP не является способом выбрать конкретную страну. Это Cloudflare egress, страна/город зависят от сети Cloudflare.

Удаление exit:

  • удаляет exit из панели;
  • убирает его из primary/backup политики;
  • переводит клиентов этого exit в Авто;
  • если у панели есть SSH-key доступ к exit, останавливает wg-quick@kaskad-exit и удаляет /etc/wireguard/kaskad-exit.* на exit-сервере.

Активность клиентов

Панель читает локальный вывод wg show all dump и awg show all dump на RU entry/VPS:

  • свежий handshake до 180 секунд -> online;
  • нет handshake или нет wg/awg на сервере -> offline;
  • также показываются RX/TX bytes клиента.

Если RU WireGuard/AWG еще не поднят, клиенты будут отображаться как offline. Это нормально: конфиг создан, но серверная часть не слушает порт.

NaiveProxy

В панели добавлен блок Настройки WG -> NaiveProxy.

Что делает:

  • ставит на выбранный local / RU entry / US exit отдельный Caddy с forwardproxy@naive;
  • слушает HTTPS порт, по умолчанию 443;
  • использует реальный домен и Let's Encrypt TLS;
  • отдаёт нейтральную HTML-страницу обычному браузеру;
  • выдаёт admin-панели Client URI вида https://user:password@domain.

Как включить:

  1. Создать DNS A запись домена на IP выбранного сервера.
  2. Проверить, что порт 443 свободен.
  3. Открыть Настройки WG -> NaiveProxy.
  4. Выбрать конкретный сервер.
  5. Указать домен, email, login/password.
  6. Нажать Установить NaiveProxy на 443.

Ограничения:

  • без домена установка блокируется: NaiveProxy нужен реальный TLS, иначе маскировка слабая;
  • если порт 443 занят чужим процессом, установка блокируется;
  • NaiveProxy является TCP HTTPS proxy и не заменяет WireGuard UDP каскад RU -> US;
  • для Telegram нужен клиент/мост с поддержкой Naive, либо используйте уже добавленный SOCKS5 proxy.

Для маскировки именно связи RU -> US поверх UDP WireGuard лучше отдельная транспортная схема: Hysteria2/TUIC/Xray REALITY/ShadowTLS. NaiveProxy можно использовать как дополнительный HTTPS-proxy слой, но не как прямой UDP-туннель WireGuard.

Mieru proxy

В панели добавлен протокол клиента Mieru proxy.

Как работает:

  • это отдельный proxy-протокол, не WireGuard peer;
  • серверная часть Mieru называется mita, клиентская часть — mieru;
  • на RU входе mita слушает TCP порт, по умолчанию 2999;
  • каждый клиент получает username/password, app-import config и CLI config;
  • для Karing iOS используйте кнопку Копировать или QR в панели: они отдают чистый sing-box/Mieru JSON через /api/clients/{id}/share;
  • старую строку mierus://... не вставляйте в экран подписки Karing — приложение показывает «Нет доступных серверов», потому что ждёт profile/content JSON;
  • клиент импортирует JSON командой mieru apply config client_config.json, потом запускает mieru start;
  • после запуска приложения используют локальный SOCKS5 127.0.0.1:1080.

Что копировать:

  • Копировать / QR у Mieru peer: короткий JSON для Karing/sing-box.
  • Конфиг: полный админский текст. Для Karing копируйте только блок Karing/sing-box JSON; для desktop CLI — блок Mieru CLI.

Runtime:

  • на RU входе есть кнопка Mieru: она ставит серверный пакет mita и проверяет, что выбранный TCP порт не занят чужим процессом;
  • если mita установлен на RU входе, платформа применяет users/ports через mita apply config и запускает mita;
  • если mita не установлен, клиент всё равно создаётся, но runtime status будет mieru-not-installed;
  • когда Mieru-клиентов нет, платформа держит скрытого idle-пользователя, потому что mita падает с no user found при TCP port binding без users;
  • несколько Mieru пользователей могут жить на одном порту;
  • max_connections хранится в клиенте и отображается в панели.

Лимиты:

  • SOCKS5 proxy уже режет активные соединения через встроенный Python runtime;
  • Mieru имеет серверные users и traffic/quota команды, но native per-user active connection limit в текущих docs не описан;
  • NaiveProxy/Caddy также не режет per-user active connections из коробки;
  • для жёсткого лимита Mieru/NaiveProxy нужен отдельный wrapper/firewall accounting слой.

Официальные reference:

  • https://github.com/enfein/mieru/blob/main/docs/server-install.md
  • https://github.com/enfein/mieru/blob/main/docs/client-install.md
  • https://github.com/enfein/mieru/blob/main/docs/operation.md

VLESS Reality

Основной DPI-устойчивый протокол для телефонов. На RU входе поднимается xray с VLESS-Reality, маскировка идёт под настоящий сайт SberCloud (obs.ru-moscow-1.hc.sbercloud.ru): входы физически живут в AS208677, поэтому связка SNI и IP для DPI выглядит обычным облачным трафиком.

  • кнопка Включить Reality на карточке RU входа — ставит xray, генерит Reality-ключи (идемпотентно, повторное нажатие не ломает уже выданные конфиги), занимает :443 или :8443, если 443 занят;
  • клиент с протоколом VLESS Reality получает не WireGuard-ключи, а uuid-личность;
  • /api/clients/{id}/subscription отдаёт sing-box конфиг сразу с двумя входами (sber_2 + sber_1) и urltest — переключение между входами занимает около 40 секунд;
  • ?format=links отдаёт vless:// ссылки, /subscription_qr — QR для Karing/sing-box;
  • лимит устройств считается по access-логу xray (email = uuid): монитор раз в 60 секунд смотрит уникальные source-IP и шлёт алерт при превышении, без автоматического отключения.

Протоколы клиентов

WireGuard, AmneziaWG 2.0, AmneziaWG Legacy, SOCKS5 proxy, Mieru proxy, VLESS Reality.

Протокол AIVPN (анти-DPI мимикрия) был добавлен 22.06.2026 и удалён 26.08.2026 — за два месяца им пользовались два клиента, последний хендшейк был 22.06.2026. Подробности в CHANGELOG.

Текущий режим

Панель уже выпускает WireGuard, AmneziaWG 2.0 и AmneziaWG Legacy конфиги, ставит WireGuard на выходные серверы по SSH, проверяет выходы, считает метрики и выбирает доступный/легкий выход. На RU сервере она пока не применяет wg0/awg0, iptables и policy routing автоматически. Это сделано специально: перед применением маршрутов нужна диагностика интерфейсов и firewall, иначе можно потерять SSH.

Важно: AmneziaWG 2.0/Legacy клиент требует, чтобы RU вход был поднят через awg / AmneziaWG. Обычный wg не принимает AWG-параметры Jc/Jmin/Jmax/S1-S4/H1-H4/I1-I5.

SSH установка AmneziaWG вход поддерживает Ubuntu/Debian через официальный Amnezia PPA и Fedora/RHEL-like через COPR. Для DKMS нужны kernel headers; если ядро старое или headers недоступны, installer вернет ошибку и покажет stderr.

AmneziaWG 2.0 в панели использует усиленную маскировку по актуальной документации Amnezia: S3/S4, непересекающиеся диапазоны H1-H4, I1 signature packet под DNS.

Важно: панель сейчас доступна по HTTP. Смените дефолтный admin/admin сразу после входа. Для эксплуатации нужен HTTPS или доступ к панели только через VPN/SSH-туннель.

Security baseline:

  • session cookie: HttpOnly, SameSite=Lax, Secure при HTTPS;
  • login rate-limit: 5 ошибочных попыток на IP за 10 минут;
  • базовые HTTP security headers: X-Frame-Options, X-Content-Type-Options, Referrer-Policy;
  • state/secrets файлы: 0600, data directory: 0700;
  • /api/status не отдаёт приватные ключи, SSH секреты и bot token.

Основные компоненты

  • server/main.py — FastAPI приложение и веб-панель.
  • server/store.py — JSON-хранилище состояния.
  • docs/architecture.md — архитектура каскада.
  • docs/instructions.md — инструкции по запуску, проверке и обслуживанию.
  • docs/audit-2026-06-07.md — последний полный аудит.
  • CHANGELOG.md — история изменений.
  • ROADMAP.md — ближайшие доработки.
  • tests/test_api.py — тесты API.

Правила безопасности

  • Не хранить секреты в GitHub.
  • Не писать пароли, токены и приватные ключи в чат.
  • Хранить доступы только в .env, password manager или закрытых заметках.
  • Логи не должны печатать приватные ключи, токены, пароли и полные клиентские конфиги.
  • Перед изменениями на проде сначала диагностика.
Description
kaskad_platform
Readme 129 KiB
Languages
Python 100%