Files
elmprodvpn/docs/phase-b/B1_CORE_VERIFICATION.md

15 KiB
Raw Blame History

B1 Проверка ядра и внешних зависимостей

Дата: 2026-02-27 Статус: draft Владелец: Engineering

1) Цель

  • Убедиться, что Go-ядро имеет централизованную логику для работы с nftables, policy routing, systemd, cgroup и SmartDNS, и что эти зависимости отражены в конфигурациях/документации.
  • Выявить потенциальные отверстия (например, части логики, которые напрямую обращаются к shell-скриптам routes_update, autoloop, trace) перед тем, как стартовать задачи для веба.

2) Критерии завершения

  • Описание работы ключевых модулей ({routes_update.go, traffic_mode.go, events_bus.go, watchers.go, resolver.go, smartdns_runtime.go, vpn_handlers.go}) подготовлено, включая внешние зависимости (nftables, SmartDNS, systemd, AdGuard VPN API).
  • Сформулирован список требований (root, обязательные сервисы, долгие операции, возможные блокировки) на случай запуска через веб-консоль.
  • Уточнено, какие данные уже сохраняются в stateDir, appmark и routes файлах, чтобы веб мог отображать информацию без дополнительного API.

3) Задачи

  • Пройти routes_update.go, routes_units.go, routes_cache.go, nft_update.go и описать, как обновляются маршруты и кэшируются состояния.
  • Проанализировать traffic_mode.go, traffic_appmarks.go, traffic_app_profiles.go, traffic_audit.go: что именно меняют (fwmark, cgroup, nft sets) и какие проверки выполняются.
  • Прописать взаимодействие с DNS/SmartDNS (dns_settings.go, smartdns_runtime.go, smartdns_wildcards_store.go, resolver.go), включая init/restore/caching жизненный цикл.
  • Проверить watchers.go, events_bus.go, trace_handlers.go: какие события стримятся, какие веб-интерфейсы они смогут потреблять, и нужны ли дополнительные фильтры или буферизация.
  • Отметить, какие части кода требуют root-доступ и как это влияет на веб (например, API будет работать под сервис-аккаунтом и выполнять nft/update через internal API, но сама служба должна запускаться с нужными привилегиями).
  • Собрать стартовый список фактов по каждому модулю: с какими systemd unit'ами, nft set'ами, SmartDNS/AdGuard VPN API и stateDir работает, и какие ограничения это накладывает.
  • Задокументировать потенциальные точки отказа (недоступность nftables/systemd, SmartDNS/AdGuard API) и предложить стратегию контроля ошибок для веб-интерфейса.

4) Модули и зависимости

routes_update.go

  • Основной контроллер обновления маршрутов: строит policy routes, nftables-цепочки agvpn/agvpn4/agvpn_dyn4, запускает runResolverJob, пишет список доменов/IP в stateDir и сохраняет status.json.
  • Поддерживает прогресс через events.push("routes_nft_progress", ...), пишет heartbeat-файлы и требует доступа к iproute2, nft, stateDir, trace.log и воркеру резольвера.
  • Обрабатывает force/auto конфигурации из TrafficModeState и фиксирует trafficEval в статусе, что важно для отображения в вебе.

routes_units.go, routes_cache.go, nft_update.go

  • routes_units.go разрешает systemd имя (routesServiceUnitName, routesTimerUnitName) и используется в /routes/service/timer.
  • routes_cache.go кеширует domains, ips, domains state; можно использовать для расчёта прогресса и восстановления.
  • nft_update.go держит “умный” апдейтер, который управляет правилами и sets; важно документировать, какие команды выполняются и как проверяется успех (runNFTUpdate, progressCb) для веба.

traffic_mode.go + traffic_appmarks*

  • Управляют состоянием (stateDir/state-traffic-mode.json), применяют флаги fwmark и policy rules (applyTrafficMode), читают/пишут список принудительных субнетов/UID/cgroup.
  • traffic_appmarks.go работает с cgroup v2, создаёт маркеры MARK_APP/MARK_DIRECT и задаёт TTL (через systemd scopes) для runtime управления per-app traffic.
  • traffic_app_profiles.go хранит профили в stateDir и предоставляет CRUD, что пригодится вебу для создания shortcut-профилей.
  • traffic_audit.go проверяет состояние nft/route и формирует TrafficAudit issues, полезные для мониторинга.

dns_settings.go + resolver.go

  • Хранит конфигурацию dns-upstreams.conf, режим (dns_mode.json) и pool upstreams; отвечает за benchmark, SmartDNS control (smartdns service start/stop) и режим ViaSmartDNS.
  • resolver.go запускает Go-резольвер, читает domains.txt, meta-special.txt, static-ips.txt, использует кеши (domain-cache.json, ptr-cache.json) и пишет результат в stateDir.
  • Сервисы SmartDNS (smartdns_runtime.go, smartdns_wildcards_store.go) управляют дополнительными wildcard-базами, runtime stats и prewarm, что потребует отображения статуса SmartDNS в веб.

vpn_handlers.go + vpn_login_session.go

  • Интеграция с AdGuard VPN API: autoloop, autoconnect, locations, set location, logout и status založený na HTTP-запросах к локальному adguardvpn сервису.
  • vpn_login_session.go создаёт PTY-сессию (через runCommand + systemd-run --user?), сохраняет состояния в loginStatePath и выпускает события (events.push) для SSE; вебу потребуется поддерживать эти пользователи.

events_bus.go, watchers.go, trace_handlers.go

  • startWatchers запускает наблюдение за status.json, loginState, autoloop логом, trace.log, state traffic appmarks TTL и systemd unitами (routes service/timer, VPN unit, SmartDNS).
  • Все watcher-изменения отправляются в events и поступают клиенту через handleEventsStream, что даёт вебу источник realtime данных.
  • trace_handlers.go читает trace.log, trace-json и принимает append, что позволяет вебу показывать live trace и записывать дополнительные строки.

routes_handlers.go

  • Управление systemd-unit'ами (routes_service, routes_timer), ручной rollback/clear, fixing policy route, переключение режимов/advanced config.
  • Служит фасадом для CLI (как routes-update, routes-clear, autoloop), следовательно API может использоваться как POST /api/v1/routes/service и POST /api/v1/routes/update.

Корневые ограничения и привилегии

  • routes_update/routes_handlers запускаются как root (nft, ip, systemctl); веб-интерфейс должен вызывать API, а не повторять команды, сохраняя сервис privileged.
  • SmartDNS требует запуска smartdns-local.service; VPN команды ждут доступ к AdGuard VPN (возможно, adguardvpn.service).
  • stateDir и domains файлы должны быть доступны API, а вебу важно понять, какие endpoints кешируют/читают эти файлы. Например, routes timer enable хранится в routes_timer_state.json.
  • Потенциальные точки отказа:
    • nft команды падут, если kernel не поддерживает nftables или service не запущен — API должен возвращать CmdResult с stderr и exitCode.
    • systemd unit может быть недоступна (не установлен routes-service), мониторинг через watchers должен отправлять unit_state_changed.
    • SmartDNS runtime может не стартовать: нужно отразить ошибку через events.push("smartdns_error"... ) и вернуть CmdResult.ok=false.
    • AdGuard VPN API или PTY могут быть недоступны; API должен возвращать ошибки и веб должен приступать к повторной попытке.

5) Матрица зависимостей

Модуль http/cli Зависимости Состояния/файлы Потенциальные ошибки
events_bus.go, watchers.go, events_handlers.go /api/v1/events/stream in-memory queue, watcher goroutines status.json, login_state.json, trace.log, systemd unit polling, autoloop.log SSE disconnected, poll errors, buffer overflow
routes_update.go POST /api/v1/routes/update, CLI routes-update iproute2, nft, runResolverJob, SmartDNS stateDir/{domains,ips}*, status.json, trace.log, heartbeat Нет VPN-интерфейса, резольвер падает, nft пишет ошибки
routes_units.go /api/v1/routes/service, /routes/timer, CLI routes-clear systemd (service/timer names) routes_timer_state.json, unit name env Unit не установлена, systemctl возвращает error
routes_cache.go, nft_update.go внутренняя логика routes update nft, temp files /var/run/selective-vpn temp files nft прогресс в stderr, temp-файлы не создаются
traffic_mode.go + traffic_appmarks* /api/v1/traffic/* nft, policy routing, cgroup v2, systemd stateDir/traffic-mode.json, appmarks.json, cgroup scopes Некорректная конфигурация, nft не применяет правила
traffic_app_profiles.go /api/v1/traffic/app-profiles файловые операции stateDir/app-profiles.json Файл повреждён, не сохраняется
dns_settings.go + resolver.go /api/v1/dns-* resolv.conf, SmartDNS binary dns-upstreams.conf, dns_mode.json, domain-cache.json, ptr-cache.json Нет upstream, benchmark таймаут
smartdns_runtime.go, smartdns_wildcards_store.go /api/v1/smartdns/* smartdns-local.service, wildcard files smartdns.conf, wildcards.json Service fail, wildcard file read-only
vpn_handlers.go, vpn_login_session.go /api/v1/vpn/* AdGuard VPN API, PTY, systemd-user login_state.json, autoloop.log API недоступен, PTY не стартует
trace_handlers.go /api/v1/trace* доступ к trace.log trace.log Файл недоступен, append write error

Эта матрица показывает, какие компоненты требуют привилегий и как ошибка отражается на UI. В Phase D можно перенести эти строки в таблицу web-ready и отметить status (готово/требует/blocked).

Технические state-файлы и кеши

  • stateDir (по умолчанию /var/lib/selective-vpn) содержит:
    • domains.txt, ips-*.txt, ipmap-*.txt — сериализация выходных данных resolver, используются trace/expand logic.
    • state-traffic-mode.json, appmarks.json, app-profiles.json — основные состояния traffic mode/appmarks/profiles, читаются traffic_mode.go, traffic_appmarks.go, traffic_app_profiles.go.
    • domain-cache.json, ptr-cache.json — кеш resolver, обновляется из runResolverJob и влияет на routes_update (limit/ttl).
  • status.json, heartbeat — пишутся routes_update. watchStatusFile читает file, events.push("status_changed") доставляет web info (iface, table, healthy).
  • login_state.json — создаётся vpn_login_session.go, SSE login_state_changed отражает current state; при CmdResult.ok=false пишется error в file/event.
  • trace.log — задействован trace_handlers.go и watchFileChange, SSE trace_changed парсит tail. trace_append endpoint пишет новые строки (CmdResult). Web должна ограничить size (<=1<<20) и показывать stderr/exitCode.

Watchers и события

  • watchStatusFile, watchLoginFile, watchAutoloop, watchTrafficAppMarksTTL, watchSystemdUnit* запускаются на startWatchers и публикуют события (status_changed, login_state_changed, autoloop_status_changed, unit_state_changed, appmarks_ttl).
  • events_bus буферизует последние SVPN_EVENTS_CAP событий (config via env). SSE events/stream читает их since/Last-Event-ID. При ошибок (blocked mutex, dropped events) нужно логировать selective-vpn-api и отображать status_error.
  • events.push используется для routes_nft_progress, smartdns, trace_changed. Вебу важно знать ключи, чтобы фильтровать события по статус/trace/health.