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

Входной слой (Entry)

·2 минуты·
Входной слой — однородный Kubernetes-кластер Entry-подов, принимающих клиентские подключения. Каждый под stateless: маршрут клиента определяется запросом в etcd при установке соединения. Один домен на ячейку, горизонтальное масштабирование без ограничений.

Роль в архитектуре #

graph LR Client["Клиент"] LB["K8s LoadBalancer"] E1["Entry-под 1"] E2["Entry-под 2"] E3["Entry-под N"] Core["Core-нода"] Client -->|"TLS 1.3"| LB LB --> E1 LB --> E2 LB --> E3 E1 -->|"mTLS"| Core E2 -->|"mTLS"| Core E3 -->|"mTLS"| Core style LB fill:#7c3aed,color:#fff,stroke:#6d28d9 style E1 fill:#0891b2,color:#fff,stroke:#0e7490 style E2 fill:#0891b2,color:#fff,stroke:#0e7490 style E3 fill:#0891b2,color:#fff,stroke:#0e7490 style Client fill:#64748b,color:#fff,stroke:#475569 style Core fill:#1d4ed8,color:#fff,stroke:#1e40af

Характеристики #

ПараметрЗначение
ИнфраструктураKubernetes worker nodes
Единица деплояPod (Nginx + Xray)
МасштабированиеГоризонтальное, без ограничений
СостояниеStateless
ДоменОдин на ячейку
Открытые порты80 (→ HTTPS), 443
МаскировкаОбычный HTTPS-сайт

Компоненты пода #

Nginx #

  • TLS-терминация с сертификатом от публичного CA.
  • Маршрутизация по URL: gRPC-трафик (по serviceName) → Xray, всё остальное → сайт-прикрытие.
  • Fallback: любой запрос без VLESS-заголовков возвращает сайт-прикрытие (HTTP 200 OK).

Xray-core #

  • Слушает только на 127.0.0.1 — недоступен извне.
  • Протокол: VLESS + gRPC.
  • Inbound: принимает трафик от клиентов.
  • Outbound: перенаправляет трафик на Core-ноду через mTLS + VLESS + gRPC.

Stateless-роутинг #

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

  1. Извлекает UUID из VLESS-заголовка.
  2. Запрашивает etcd: UUID → адрес Core-ноды + SNI ячейки.
  3. Кеширует результат на время активной сессии.
  4. Устанавливает mTLS-соединение с Core-нодой.

Если связность с etcd нарушена — новые соединения не устанавливаются. Активные сессии продолжаются до завершения.

Масштабирование #

Каждый новый участник сети добавляет один сервер в K8s-кластер в качестве worker node. Kubernetes автоматически размещает на нём Entry-поды.

ДействиеЧто происходит
Добавление worker nodeНовые Entry-поды распределяются на неё автоматически
Выход worker nodeПоды перемещаются на оставшиеся ноды
Обновление конфигурацииRolling update без прерывания активных сессий

Защита от активного зондирования #

На каждом Entry-поде Xray расположен за Nginx. Любой запрос без правильных VLESS-заголовков возвращает сайт-прикрытие. Нет характерных ошибок, редиректов или отказов, по которым можно было бы идентифицировать прокси-сервер.

serviceName (gRPC-путь) случайный и периодически ротируется. Наблюдатель, не знающий serviceName, не может отличить VPN-трафик от обычных запросов к сайту.

Сертификаты #

Entry-поды получают два вида сертификатов:

СертификатИсточникНазначение
TLS (публичный)Let’s EncryptTLS-терминация клиентских соединений
mTLS (внутренний)Управляющий кластер (CA)Аутентификация при подключении к Core-нодам

Реагирование на инциденты #

Признаки компрометации Entry-пода: несанкционированный доступ к серверу участника. Компрометация раскрывает только маршруты активных в этот момент сессий.

Порядок действий:

  1. Исключить скомпрометированный worker node из K8s-кластера.
  2. Отозвать mTLS-сертификат ноды в управляющем кластере.
  3. Проверить Core-ноды, к которым шёл трафик через скомпрометированный под — при необходимости сменить serviceName.
  4. Добавить новую worker node взамен выведенной.