8.0 KiB
Netrunner Control Plane
Бэкенд VPN-сервиса «Netrunner»: авторизация (Telegram / анонимный «Ghost Protocol»), биллинг подписок через TON, реферальная программа, оркестрация VPN-нод по SSH, Telegram-бот как второй канал входа и встроенная раздача SPA-фронтенда.
Стек: Rust (axum, sqlx/Postgres, teloxide, tokio) + React/TypeScript (Vite) фронтенд, собранные в единый Docker-образ.
Структура репозитория
| Путь | Что там | Подробнее |
|---|---|---|
src/ |
Rust-бэкенд (control plane) | см. ниже |
src/modules/ |
Бизнес-модули (auth, billing, nodes, referrals, users) | README |
src/db/ |
Модели и репозиторий (доступ к Postgres) | README |
frontend/ |
React/Vite SPA (личный кабинет, игра, админка нод) | README |
migrations/ |
SQL-миграции (sqlx) | — |
templates/init_node.sh |
Bash-скрипт инициализации новой VPN-ноды, исполняется по SSH | — |
tests/ |
Интеграционные тесты репозитория (sqlx::test, требуют Postgres) |
— |
Инфраструктура и процесс деплоя подробно описаны в DEPLOYMENT.md;
список закрытых и остаточных угроз безопасности — в SECURITY_AUDIT.md.
Неструктурированный бэклог идей и задач — в things.txt.
Архитектура бэкенда
Слоями, сверху вниз:
main.rs— точка входа: поднимает пул Postgres, собираетApiState(репозиторий + сервисы всех модулей) и параллельно запускает HTTP API, Telegram-бота и фоновые задачи биллинга до общего сигнала остановки (Ctrl+C / SIGTERM).api.rs— сборка axum-роутера: монтирует контроллеры модулей, rate-limiting (tower_governor), CORS, Prometheus-метрики (/metrics), health-пробы (/health,/health/ready) и раздачу статики фронтенда как SPA-фолбэк.modules/*/controller.rs— HTTP-контракты (axum-роуты, JSON DTO), тонкий слой без бизнес-логики.modules/*/service.rs— бизнес-логика модуля.db::repository::AppRepository— трейт доступа к БД; единственная реализация —PgRepository(Postgres/sqlx). Сервисы знают только о трейте, поэтому теоретически подменяемы в тестах без реальной БД.bot.rs— Telegram-бот (teloxide), использует те же сервисы, что и HTTP API.tasks.rs— фоновый цикл: сброс просроченных подписок и сверка блокчейна на предмет потерянных платежей.error.rs— единыйAppErrorсIntoResponse: маппинг в HTTP-статус, безопасное сообщение наружу и подробности только в логи/метрики.
Быстрый старт (локальная разработка)
cp .env.example .env # заполнить секреты (JWT_SECRET, ARGON_SALT, TELOXIDE_TOKEN, ...)
make dev # docker compose: db + redis + app с hot-reload (cargo watch)
Приложение поднимется на http://localhost:8080 (/health, /health/ready).
Остальные команды — make help.
Известные незавершённые места (недоделки)
Ниже — то, что явно недоделано или является временной заглушкой в текущем коде.
В самих файлах эти места помечены комментариями // TODO: — см. также
SECURITY_AUDIT.md для рисков безопасности отдельно.
- Cyberhack без анти-чита.
POST /users/hack/resultпринимаетscoreот клиента и лишь клампит его в0..=500— сервер не проверяет, что игра реально была сыграна честно. Пока не эксплуатируемо (баланс E$ нигде не тратится), но станет дырой, как только появится трата баланса. См.src/modules/users/controller.rs. GET /nodes/routingвозвращает неполный конфиг. Отдаёт толькоip/port/region/supported_protocols(последнее — статичная заглушка). Реальному VPN-клиенту нужны ещёtunnel_*-поля (уже есть в моделиVpnNode, но не сериализуются),public_key/sni_domain(их нет даже в схеме БД) и одноразовый session-токен. См.src/modules/nodes/controller.rs.GET /nodes/statsотдаёт фейковыйuptime: "99.9%"для всех нод — не реальная метрика.- Нет health-check воркера для VPN-нод. Статус ноды в БД не переоценивается сам:
если физический сервер лёг, control plane продолжит считать его
onlineи выдавать клиентам. См.src/tasks.rs. - Провижининг ноды — синхронный.
POST /admin/nodesдержит HTTP-запрос открытым на всё время SSH-провижининга (может занимать минуты) вместо немедленного202 Accepted+ фоновой задачи. См.src/modules/nodes/service.rs. - Курс TON запрашивается синхронно на каждый инвойс (
BillingService::initiate_payment) — не кешируется, хотя Redis в проекте уже подключён. - Таблица
auth_sessionsобъявлена в миграции, но нигде не используется — заброшенный черновик флоу авторизации через Magic Link из бота. Либо доделать, либо убрать из схемы. - Telegram-бот: разделы «Тарифы» и «Синдикат» в inline-меню — заглушка
«В разработке...» (
src/bot.rs,handle_callbacks). - Фронтенд,
AdminDashboard.tsx: кнопка «Force Restart» ничего не делает (нетonClick); UI для удаления ноды тоже отсутствует, хотя бэкенд уже умеетDELETE /api/v1/admin/nodes/{id}. - Фронтенд,
Auth.tsx: искусственные задержки (setTimeout800мс/6000мс) чисто ради вида терминала; при генерации Ghost-seed нет кнопки «скачать ключ» — если юзер не успеет скопировать seed за 6 секунд до авто-редиректа, доступ к анонимному аккаунту теряется безвозвратно (seed невосстановим). frontend/README.mdбыл шаблоном Vite по умолчанию (сейчас заменён на специфичный для проекта).