Архитектурное решение
Содержание
Контекст #
Сеть Sigil Gate изначально строилась по древовидной модели «ядро-периферия»: один или несколько узлов ядра, к каждому из которых привязана своя изолированная группа входных узлов. Каждый узел — и входной, и выходной — имел собственное доменное имя. Управление сетью было централизовано через Root-ноду с SSH-доступом ко всем остальным узлам.
На начальном этапе эта модель была достаточной. Сеть росла, появились новые участники, расширилась география инфраструктуры.
Выявленные проблемы #
1. Избыточное доверие между узлами ядра #
Узлы ядра были объединены в доверенную SSH-сеть: каждый узел мог подключиться к другому без пароля. Это удобно для оперативного управления, но создает критическую уязвимость: компрометация одного узла означает мгновенный доступ ко всем остальным. Латеральное перемещение по кластеру ядра не требует никаких дополнительных усилий.
Инцидент с несанкционированным доступом подтвердил эту уязвимость: злоумышленник, получив доступ к одному узлу, методично прошел по всем остальным за несколько минут.
2. Дефицит доменных имен #
Архитектура требовала отдельного домена для каждого узла — как входного, так и выходного. При масштабировании это превратилось в операционное ограничение: нехватка доменных имен блокировала подключение новых участников даже при наличии серверных ресурсов.
3. Операционная сложность онбординга #
Подключение нового участника требовало передачи SSH-доступа к его серверу, ручной настройки каждого узла, выдачи сертификатов через Root-ноду. Процесс не масштабировался.
4. Централизация управления #
Root-нода была единой точкой управления всей сетью. Её компрометация означала критический инцидент для всей инфраструктуры.
Принятые решения #
Нулевое доверие между узлами #
Узлы сети не доверяют друг другу по умолчанию. Всё взаимодействие — только через взаимную аутентификацию по сертификатам (mTLS). SSH-доверие между узлами ядра упразднено полностью.
Двухслойная федеративная архитектура #
Сеть разделена на два независимых слоя:
- Входной слой — однородный кластер входных узлов под управлением Kubernetes. Один домен на весь кластер в рамках одной ячейки. Каждый участник вносит один входной узел как worker-ноду кластера.
- Выходной слой — независимые узлы ядра, принадлежащие участникам. Узлы не доверяют друг другу, не взаимодействуют напрямую и управляются через механизм самостоятельной регистрации (phone-home).
Управляющий кластер как центр доверия #
Функции Root-ноды заменены распределённым управляющим кластером из трёх серверов с HA etcd и Kubernetes control plane. Кластер выполняет роль единственного удостоверяющего центра (CA) и хранит оперативное состояние сети.
Ячеистая топология #
Несколько узлов ядра, разделяющих один домен и SNI, образуют ячейку. Сеть может состоять из нескольких ячеек. Компрометация одной ячейки не затрагивает остальные. Участники скомпрометированной ячейки получают временный резервный выход через живые ячейки и восстанавливают свою инфраструктуру с нуля.
Контейнеризованный онбординг #
Новый участник устанавливает Docker, получает одноразовый join-токен и запускает контейнер. Всё остальное — генерация ключей, выпуск сертификата, регистрация в сети — происходит автоматически.
Последствия #
| Аспект | До | После |
|---|---|---|
| Доверие между узлами ядра | SSH без пароля | Только mTLS, нулевое доверие |
| Домены | По одному на каждый узел | Один на ячейку (входной слой), один на ячейку (выходной) |
| Управление | Централизованная Root-нода | Распределённый управляющий кластер |
| Онбординг участника | Ручной, SSH-доступ к серверу | Контейнер + join-токен |
| Устойчивость к компрометации | Потеря одного узла ядра — риск для всего кластера | Потеря ячейки — временный инцидент с регенерацией |
| Масштабирование | Ограничено доменами и ручными операциями | Линейное, за счет участников |
Здесь пока нет статей