15 KiB
15 KiB
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, но сама служба должна запускаться с нужными привилегиями).
- Собрать стартовый список фактов по каждому модулю: с какими
systemdunit'ами,nftset'ами, 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,domainsstate; можно использовать для расчёта прогресса и восстановления.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 и формируетTrafficAuditissues, полезные для мониторинга.
dns_settings.go + resolver.go
- Хранит конфигурацию
dns-upstreams.conf, режим (dns_mode.json) и pool upstreams; отвечает за benchmark, SmartDNS control (smartdnsservice 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.systemdunit может быть недоступна (не установлен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, SSElogin_state_changedотражает current state; приCmdResult.ok=falseпишетсяerrorв file/event.trace.log— задействованtrace_handlers.goиwatchFileChange, SSEtrace_changedпарсит tail.trace_appendendpoint пишет новые строки (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). SSEevents/streamчитает ихsince/Last-Event-ID. При ошибок (blocked mutex, dropped events) нужно логироватьselective-vpn-apiи отображатьstatus_error.events.pushиспользуется дляroutes_nft_progress,smartdns,trace_changed. Вебу важно знать ключи, чтобы фильтровать события по статус/trace/health.