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

Ротация gRPC-путей

·2 минуты·
На каждом участке сети gRPC-путь (serviceName) периодически меняется. Постоянный путь — это паттерн, который можно выделить статистическим анализом. Ротация делает трафик неотличимым от активности множества разных сервисов на одном хосте.

Зачем нужна ротация #

VLESS поверх gRPC практически неотличим от легитимного HTTPS: TLS 1.3, валидный сертификат, HTTP/2. Сигнатурный анализ здесь бессилен.

Однако постоянное соединение по одному и тому же gRPC-пути между двумя хостами — это паттерн. Реальные gRPC-микросервисы обращаются к множеству разных эндпоинтов в разное время. Статический путь, неизменный неделями, может быть выделен из общего потока.

Решение: менять serviceName с заданной периодичностью.

Два участка — два механизма #

УчастокУправляет ротациейЗатрагивает клиента
Client → EntryУправляющий кластерНет (subscription обновляет автоматически)
Entry → CoreУправляющий кластерНет (Entry получает из etcd)

Ротация на участке Client → Entry #

Что ротируется #

serviceName на Entry-ноде — путь, по которому клиент подключается к Xray внутри Entry-пода.

https://<DOMAIN>/api.v2.rpc.<serviceName>  →  Xray
https://<DOMAIN>/*                          →  сайт-прикрытие

Механизм #

  1. Управляющий кластер генерирует новый serviceName для Entry-ноды ячейки.
  2. Обновляет конфигурацию Nginx и Xray на Entry-подах через K8s (rolling update).
  3. Записывает новый serviceName в etcd.
  4. При следующем обращении клиента к subscription URL — микросервис возвращает ссылку с новым serviceName.
  5. Клиент автоматически обновляет профиль.

Клиент не вовлечён в процесс — всё происходит прозрачно.

Расписание #

ПараметрЗначение
ИнтервалКаждые 2 часа
Случайное смещение0–30 минут

Ротация на участке Entry → Core #

Что ротируется #

serviceName на Core-ноде — путь, по которому Entry-под подключается к Xray на Core-ноде.

Механизм #

  1. Управляющий кластер генерирует новый serviceName для Core-ноды.
  2. Обновляет запись в etcd: Core-нода X → новый serviceName.
  3. Доставляет новую конфигурацию Core-ноде через phone-home канал.
  4. Core-нода обновляет конфигурацию Nginx и Xray (без перезапуска, hot reload).
  5. Entry-поды при следующем запросе в etcd получают актуальный serviceName.

Расписание #

ПараметрЗначение
ИнтервалКаждый час
Случайное смещение0–30 минут

Формат serviceName #

api.v2.rpc.<16 hex-символов>

Имитирует реальные gRPC-эндпоинты API микросервисов.

Обработка ошибок #

На обоих участках ротация безопасна: при ошибке обновления конфигурации старый serviceName остаётся рабочим. Новый применяется только после успешной валидации.

Если Entry-под не успел получить новый serviceName из etcd — при следующем запросе он получит актуальную версию. Расхождение конфигураций длится не более нескольких секунд.

Сводная таблица #

КомпонентХранитсяКогда меняется
serviceName Client → Entryetcd, конфиг Nginx/Xray EntryКаждые 2 часа ± 30 мин
serviceName Entry → Coreetcd, конфиг Nginx/Xray CoreКаждый час ± 30 мин
Клиентский UUIDetcd, конфиг XrayПри компрометации устройства
Subscription URLТолько на устройствеПри компрометации устройства