Skip to content

Мультихоп

Цепочка — упорядоченный список из N ≥ 2 нод: входная (entry), 0+ промежуточных (relay), выходная (exit). Клиент подключается к entry; дальше трафик идёт между нодами внутри инфраструктуры, в интернет выходит только exit.

flowchart LR
    C[Клиент] -->|"клиентский инбаунд"| E[Entry · NL]
    E -->|VLESS Reality| R[Relay · DE]
    R -->|VLESS Reality| X[Exit · US]
    X -->|freedom| I((Интернет))

Провайдер клиента видит только entry. Сайт назначения видит IP exit. Блокировка entry лечится заменой первого хопа без перестройки остального.

Цепочка присоединяется к инбаунду, а не к клиенту: inbounds.chain_id направляет весь трафик этого инбаунда в цепочку (Инбаунды). Подписки и группы доступа о мультихопе не знают — «мультихоп-тариф» выражается группой доступа, содержащей инбаунды с цепочкой.

Сущность Поля
chains name
chain_hops chain_id, node_id, position (0 — первый после entry), port, 🔒 секрет хопа, 🔒 Reality keypair

Entry-нода в chain_hops не входит — entry определяется инбаундами, ссылающимися на цепочку. Одна цепочка может обслуживать несколько entry-инбаундов на разных нодах.

Хопы — не инбаунды в смысле Инбаунды и профили: у них нет профиля, клиентов и групп доступа. Их серверная часть (инбаунд chain-in на relay/exit) рендерится из chain_hops напрямую при сборке desired state соответствующей ноды.

VLESS + Reality — тот же стек, что для клиентов: трафик хопа неотличим от TLS к прикрытию (dest), сертификаты relay-нодам не нужны, отдельный код в агенте не нужен. Каждый хоп имеет собственный keypair, short_id и dest — одинаковый fingerprint на нескольких нодах создавал бы корреляцию, от которой мультихоп защищает.

Единственный «пользователь» инбаунда chain-in — секрет предыдущего хопа. Sniffing на chain-in выключен: внутри уже проксированный поток.

Каждая нода получает свою часть цепочки в составе обычного desired state:

Роль ноды Что рендерится
Entry Клиентский инбаунд (как обычно) + аутбаунд на хоп 0 + правило инбаунд → аутбаунд
Relay i Инбаунд chain-in (секрет хопа i) + аутбаунд на хоп i+1 + правило
Exit Инбаунд chain-in + правило chain-in → freedom

Порядок применения между нодами не координируется: каждая нода сходится к своему состоянию независимо, reconciliation повторяет попытки. Пока не сошлись все ноды цепочки, трафик через неё не проходит — это видно по applied_revision участников; оркестровать «развёртывание с хвоста» и откаты не нужно (сравнение с императивной моделью — в Архитектуре).

Изменения и деградация

Section titled “Изменения и деградация”
  • Замена/вставка хопа — правка chain_hops; ревизии всех затронутых нод инкрементируются, каждая применяет свой новый фрагмент.
  • Нода цепочки offline — цепочка помечается degraded в UI (вычисляется из связности участников, не хранится). Трафик через мёртвый хоп не проходит; автопереключение на резервный relay — не MVP, но модель его допускает (замена node_id хопа).
  • Удаление цепочки — запрещено, пока на неё ссылаются инбаунды.

Мультихоп защищает от одной точки наблюдения (провайдер клиента, один скомпрометированный узел). Не защищает от глобального наблюдателя, коррелирующего трафик entry и exit по таймингу и объёму. Каждый хоп добавляет RTT; через relay проходит трафик всех клиентов всех цепочек этого relay — учитывается в планировании ёмкости.