Перейти к содержанию

Плоскость данных

·2 минуты·
Пользовательский трафик проходит через два слоя: входной (Entry-кластер) и выходной (Core-нода участника). Управляющий кластер не участвует в передаче данных.
graph LR Client["Клиент"] LB["K8s LoadBalancer"] Entry["Entry-под"] Core["Core-нода"] Internet["Интернет"] Client -->|"VLESS + gRPC\nTLS 1.3"| LB LB --> Entry Entry -->|"mTLS\nVLESS + gRPC"| Core Core --> Internet style Client fill:#64748b,color:#fff,stroke:#475569 style LB fill:#7c3aed,color:#fff,stroke:#6d28d9 style Entry fill:#0891b2,color:#fff,stroke:#0e7490 style Core fill:#1d4ed8,color:#fff,stroke:#1e40af style Internet fill:#374151,color:#fff,stroke:#1f2937

Входной слой #

Приём трафика #

K8s LoadBalancer принимает входящие соединения и распределяет их по Entry-подам. LoadBalancer работает на уровне L4 — он не терминирует TLS и не видит содержимое трафика. TLS-терминация происходит внутри Entry-пода.

Stateless-роутинг #

Entry-под не хранит таблицу маршрутов локально. При каждом новом клиентском подключении:

  1. Извлекает UUID клиента из VLESS-заголовков.
  2. Запрашивает etcd управляющего кластера: «на какую Core-ноду направить UUID X?»
  3. Получает адрес Core-ноды и SNI-домен ячейки.
  4. Кеширует результат на время активной сессии.
  5. Проксирует трафик на Core-ноду через mTLS.
sequenceDiagram participant C as Клиент participant E as Entry-под participant KV as etcd participant Core as Core-нода C->>E: VLESS + gRPC (UUID в заголовке) E->>KV: lookup(UUID) → Core-адрес, SNI KV-->>E: ip=, sni= E->>Core: mTLS → VLESS + gRPC Core-->>E: трафик E-->>C: трафик

Компрометация Entry-пода раскрывает только маршруты активных в этот момент сессий — не полную таблицу маршрутов сети.

Выходной слой #

Core-нода принимает трафик от Entry-подов по mTLS и направляет его в открытый интернет. Каждая Core-нода принадлежит отдельному участнику и работает автономно.

Связи между Core-нодами нет — они не знают друг о друге и не взаимодействуют напрямую.

Маскировка трафика #

На каждом участке трафик неотличим от легитимной HTTPS-активности.

УчастокЧто видит наблюдательРеальность
Клиент → EntryHTTPS-запросы к обычному сайтуVPN-туннель (VLESS + gRPC)
Entry → CoregRPC-вызовы к API микросервисовVPN-туннель (VLESS + gRPC)

На обоих участках:

  • TLS 1.3 handshake — стандартный, неотличимый от обычного.
  • Валидный сертификат от публичного CA.
  • При обращении без VLESS-заголовков — сайт-прикрытие (HTTP 200 OK).

Протокольный стек #

graph TB subgraph "Протокольный стек" TLS["TLS 1.3"] gRPC["gRPC (HTTP/2)"] VLESS["VLESS"] end TLS --- gRPC gRPC --- VLESS style TLS fill:#7c3aed,color:#fff,stroke:#6d28d9 style gRPC fill:#2563eb,color:#fff,stroke:#1d4ed8 style VLESS fill:#1d4ed8,color:#fff,stroke:#1e40af
УровеньТехнологияНазначение
ШифрованиеTLS 1.3Шифрование канала, валидный сертификат
ТранспортgRPC (HTTP/2)Мультиплексирование, маскировка под API
ПротоколVLESSЛегковесный прокси-протокол

Независимость слоёв #

Входной и выходной слои масштабируются независимо. Количество Entry-подов не обязано совпадать с количеством Core-нод.

СлойМасштабированиеОграничения
ВходнойДобавление K8s worker nodesНет — горизонтально
ВыходнойПодключение новых участниковОдин участник = одна Core-нода