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

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

Давно было в планах — и вот, наконец, свершилось.

В нашей архитектуре самый критический участок — это соединение между entry-нодой и core-нодой. Это трансграничный канал: именно он пересекает периметр, на который направлено повышенное внимание систем DPI.

VLESS поверх gRPC — сильная комбинация. Трафик практически неотличим от обычного HTTPS: TLS с валидным сертификатом, HTTP/2, браузерный TLS-фингерпринт. Со стороны это выглядит как обращение к обычному веб-сервису. Распознать его по сигнатурам практически невозможно.

Но «практически неотличим» не означает «невозможно вычислить».

Даже если содержимое трафика зашифровано и протокол замаскирован, остаются метаданные: кто, куда, как часто, как долго. Постоянное соединение по одному и тому же gRPC-пути на одном хосте — это паттерн. Даже для легитимного gRPC-микросервиса это выглядит подозрительно: реальные сервисы обычно обращаются по разным эндпоинтам.

Если путь не меняется неделями — это маркер. Статистический анализ может выделить такое соединение из общего потока.

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

Я долго откладывал реализацию, но сегодня руки наконец дошли.

В минимальной реализации это bash-скрипт на core-ноде, который запускается по systemd timer. Скрипт генерирует новый случайный путь, обновляет конфигурации Nginx и Xray на core-ноде, а затем по SSH пушит изменение outbound-пути на каждую entry-ноду.

Важный момент: клиентская сторона не затрагивается. Путь ротируется только на внутреннем участке entry→core. Клиентам не нужно ничего перенастраивать — они продолжают подключаться к entry-ноде по прежнему адресу.

Текущие ограничения #

На короткие секунды в момент ротации связь может пропадать — сервисы перезагружаются. Клиент переподключается автоматически, но разрыв заметен.

В перспективе мы перейдем на Xray gRPC API (hot reload). Это позволит менять пути без перезагрузки сервисов — ротация станет бесшовной, без разрыва соединения.

Сейчас ротация настроена на каждый час. Практика покажет, приносит ли это ощутимые неудобства на клиенте. Если нет — будем увеличивать интервал или перенесем время ротации на периоды наименьшей активности.