11 KiB
11 KiB
E1 Дизайн multi-client маршрутизации (PBR)
Дата: 2026-03-04 Статус: draft Владелец: Engineering
1) Цель
- Спроектировать расширение текущего ядра так, чтобы несколько transport-клиентов (
sing-box,dnstt-client,phoenix->slipstream) работали под единым control-plane API. - Сохранить один источник истины для маршрутизации: только Go-ядро управляет PBR/nft/ip rule, UI только вызывает API.
- Обеспечить безопасную многоклиентную схему без конфликтов: один трафик/сайт не должен одновременно идти через два интерфейса.
2) Текущий baseline (по коду)
- Сейчас модель маршрутизации бинарная:
vpn|direct+ глобальныеMARK/MARK_APP/MARK_DIRECT/MARK_INGRESS. - Runtime app routing хранится в
traffic-appmarks.json, persistent launcher-профили вtraffic-app-profiles.json. - Центр оркестрации:
traffic_mode.go,traffic_appmarks.go,routes_update.go. - Ограничение: нет сущности "клиент-транспорт" как объекта с собственным iface/table/mark.
3) Архитектурный инвариант
PBR Engineв Go-ядре остается единственным writer для:ip rule,ip route table,nft chains/sets/rules,conntrack mark policy.
- Transport backends (sing-box/dnstt/phoenix) подключаются через backend-адаптеры и не пишут маршруты напрямую.
- UI (desktop/web/iOS/android) оперирует одинаковым API-контрактом, не знает о внутреннем устройстве backend-клиентов.
4) Целевая модель данных
4.1 TransportClient
id: стабильный ключ (sb-main,dnstt-home,phoenix-eu).kind:singbox | dnstt | phoenix.enabled: bool.status:starting | up | degraded | down.iface: фактический интерфейс/туннель.routing_table: имя таблицы (agvpn_<id>).mark_hex: выделенная fwmark клиента.priority_base: базовый диапазонip rule prefдля клиента.capabilities:tcp,udp,dns_tunnel,ssh_tunnel.health: last_check, latency, last_error.
4.2 RouteIntent
- Нормализованная запись назначения трафика к клиенту:
selector_type:domain | cidr | app_key | cgroup | uid.selector_value: значение селектора.client_id: целевой клиент.priority: порядок применения.mode:strict | fallback.
4.3 ConflictRecord
- Запись о конфликте маршрутизации:
key: нормализованный ключ пересечения.owners: списокclient_id.severity:warn | block.reason: человеко-читаемая причина.suggested_resolution: автоматическая подсказка.
5) Схема марков и таблиц (без конфликтов)
5.1 Mark allocator
- Ввести менеджер выделения марков из пула, например:
0x100-0x1FFдля client-specific route marks,0x66/0x67/0x68/0x69оставить для legacy/системных сценариев.
- Для каждого
client_idвыделяется:client_mark,client_reply_mark(если нужен отдельный ingress stickiness).
5.2 Table allocator
- Для каждого клиента заводится отдельная routing table:
agvpn_sb_main,agvpn_dnstt_home,agvpn_phoenix_eu.
- В таблице только default route через iface клиента + локальные bypass-правила.
5.3 Rule priority allocator
- Для каждого клиента выделяется непересекаемый диапазон
pref:- пример:
13000-13049клиент A,13050-13099клиент B.
- пример:
- Это исключает перетирание правил между клиентами при apply/reconcile.
6) Защита от "мешанины" трафика
6.1 Destination ownership lock
- Один домен/cidr/app_key в активной конфигурации может иметь только одного владельца (
client_id). - При пересечении:
- по умолчанию
block(HTTP409на apply), - опционально
force_overrideс явным подтверждением пользователя.
- по умолчанию
6.2 Flow stickiness (conntrack)
- Для первого пакета потока проставляется
ct mark = client_mark. - Для последующих пакетов mark восстанавливается из
ct mark, чтобы один и тот же flow не перескакивал между интерфейсами. - Правило действует в
outputиprerouting, аналогично текущему ingress-reply подходу.
6.3 DNS/IP coherence
- Для domain-based маршрутизации вводится owner-cache:
domain -> client_id -> ip setс TTL.
- Один и тот же домен в активной политике не может одновременно резолвиться в разные клиентские set-цепочки.
6.4 Audit/guardrail
- Расширить
traffic_auditна multi-client проверки:- duplicate destination ownership,
- overlap CIDR между клиентами,
- app_key на двух клиентах одновременно,
- nft/rule drift по client chains.
7) UX дизайн (удобное добавление/переключение)
7.1 Экран "Клиенты"
- Список клиентов: имя, тип, статус, интерфейс, health.
- Действия:
Добавить,Включить/Выключить,Перезапустить,Удалить. - Мастер добавления:
- Шаг 1: тип клиента (
sing-box,dnstt,phoenix), - Шаг 2: параметры подключения,
- Шаг 3: health-check,
- Шаг 4: назначение default policy.
- Шаг 1: тип клиента (
- Подпункты UX для engine:
- единый селектор
Active engineс вариантамиsingbox|dnstt|phoenix; - быстрые действия
Connect,Disconnect,Switch to ...; - явное отображение
desired_enginevsactive_engine; - при деградации показывать
last_errorи actionRollback to previous engine.
- единый селектор
7.2 Экран "Маршрутизация"
- Матрица
Селектор -> Клиент. - Массовое назначение списков IP/CIDR/доменов.
- Быстрый переключатель "перенести селектор на другой клиент" с dry-run проверкой конфликтов.
7.3 UX предупреждения
- Перед apply показывать diff:
- какие селекторы сменят владельца,
- какие потоки могут быть прерваны,
- какие конфликты заблокируют применение.
- При
force_overrideобязательное подтверждение пользователя с явным риском:- "Один и тот же сайт может потерять стабильность при частой смене интерфейса".
- При switch/connect engine:
- показывать предупреждение о кратковременном разрыве активных сессий;
- запрещать параллельные mutating-операции до завершения текущего switch;
- при failed switch предлагать rollback на предыдущий engine.
8) API-контракт (новые ручки, проект)
GET /api/v1/transport/clientsPOST /api/v1/transport/clientsPOST /api/v1/transport/clients/{id}/startPOST /api/v1/transport/clients/{id}/stopGET /api/v1/transport/clients/{id}/healthGET /api/v1/transport/policiesPOST /api/v1/transport/policies/validatePOST /api/v1/transport/policies/applyGET /api/v1/transport/conflictsGET /api/v1/transport/capabilities
Принцип:
- Все операции изменения policy идут через
validate -> apply. applyатомарный: либо вся новая политика применена, либо rollback на предыдущую snapshot-конфигурацию.
9) Реализация по шагам
E1.1 Контракты и состояние
- Ввести state-файлы:
transport-clients.json,transport-policies.json,transport-conflicts.json.
- Добавить DTO и минимальные read endpoints.
E1.2 PBR compiler v2
- Реализовать компиляцию RouteIntent в:
- nft sets/chains per client,
- ip rule pref ranges per client,
- table route entries per client.
E1.3 Guardrails
- Валидация ownership/overlap до apply.
- Conntrack stickiness rules для стабильности flow.
E1.4 UX-ready слой
- API предупреждений + dry-run diff.
- SSE события:
transport_client_state_changed,transport_policy_applied,transport_conflict_detected.
10) Критерии готовности дизайна
- Можно добавить 2+ клиентов и поднять 2+ интерфейса без перезаписи чужих rule/table.
- Нельзя назначить один и тот же selector двум клиентам без explicit override.
traffic_auditпоказывает целостную картину конфликтов и drift.- UI получает понятные предупреждения до применения рискованной конфигурации.
11) Обратная совместимость
- Текущие
/api/v1/traffic/*продолжают работать в legacy-режиме. - При отсутствии multi-client политики ядро использует текущий single-client pipeline.
- Миграция: legacy
vpn|directможет быть автоматически представлена как:client_id=legacy-vpn,client_id=legacy-direct.