Skip to content

Exordos NAC: архитектура#

Exordos NAC управляет доступом корпоративных устройств к сетевым ресурсам. Он связывает зарегистрированное устройство с его текущим сетевым адресом, проверяет условия доступа и передаёт разрешения шлюзу. Шлюз применяет их к реальному трафику с помощью nftables.

Главная идея — разделить идентичность устройства, подключение к сети и право доступа к ресурсам. Сертификат удостоверяет устройство, VPN или офисная сеть предоставляют подключение, а политика NAC определяет доступ. Разрешения действуют ограниченное время и требуют регулярного обновления.

Этот документ описывает реализацию брокера в exordos_nac и её взаимодействие с агентом из exordos_nac_agent. Форматы запросов и ответов определены в протоколе, порядок установки — в руководстве по развёртыванию, а команды проверок — в руководстве по тестированию.

1. Назначение и границы системы#

NAC отвечает на три связанных вопроса:

  1. Какое зарегистрированное устройство обращается к брокеру?
  2. Какие ресурсы доступны ему при текущем состоянии устройства и политике?
  3. На каком сетевом адресе шлюз должен применить эти разрешения?

Система предназначена для управляемых устройств с установленным агентом. Поддерживаемые платформы агента — Linux, Windows и macOS; возможности аппаратной защиты и их серверной проверки различаются между платформами.

Подключение к сети находится вне NAC. Продукт не выдаёт VPN-доступ, не поднимает собственный VPN-туннель и не выполняет аутентификацию Wi-Fi через RADIUS. Устройство сначала получает подключение и адрес через существующую инфраструктуру. Даже без разрешений NAC оно должно иметь минимальный доступ, необходимый для обращения к брокеру.

NAC контролирует трафик, проходящий через его шлюз. Он не контролирует соединения, которые обходят шлюз, в том числе прямой обмен внутри одного L2-сегмента. Изоляцию таких устройств обеспечивают коммутаторы и точки доступа. Требования к сети приведены в разделе 9.

Основные термины#

Термин Значение в этом проекте
Устройство Запись Device с постоянным device_uuid, владельцем, тегами и привязанным открытым ключом.
Брокер Сервер, который регистрирует устройства, проверяет обращения и формирует решения о доступе.
Агент Программа на устройстве: работает с ключом, обращается к брокеру и собирает сведения о состоянии ОС. На шлюзе тот же агент запускается в роли точки применения правил.
Точка применения правил Linux-шлюз с агентом в режиме enforce. В коде и протоколе используется имя enforcer.
Сессия Временная привязка устройства к адресу, с результатом проверок и наборами разрешённых ресурсов. Это не TLS-соединение и не VPN-сессия.
Набор ресурсов Именованный список адресов, протоколов и портов — resource_set. Решение политики выдаёт доступ к таким наборам.
Состояние устройства Результат оценки измеренных агентом сигналов; в протоколе — posture.
Срок разрешения Период, в течение которого разрешение сохраняется без нового подтверждения; в протоколе — lease.

2. Компоненты и их связи#

У системы два контура: принятие решений и передача трафика.

Контур принятия решений и контур передачи трафика: агенты устройства и
шлюза проходят аутентификацию через nginx в брокере, который хранит состояние
в PostgreSQL; шлюз применяет правила доступа к пересылаемому трафику.

В схеме HTTPS заканчивается на nginx перед брокером. Брокер сам TLS не обслуживает; его HTTP API слушает loopback-интерфейс.

Компонент Ответственность Что он не делает
Агент устройства Создаёт или открывает ключ, регистрируется, продлевает сертификат, отправляет измерения и доказательства владения ключом. Не назначает себе владельца, теги или разрешения.
nginx Проверяет TLS, цепочку клиентского сертификата и передаёт брокеру сертификат и наблюдаемый адрес клиента. Ограничивает частоту запросов и размер тела. Не принимает решений по политике NAC и не знает статуса устройства в БД.
Брокер Сопоставляет сертификат с устройством, проверяет доказательства, оценивает состояние, ведёт сессии и отдаёт состояние шлюзам. Не пересылает пользовательский трафик и не устанавливает правила на удалённых шлюзах.
Удостоверяющий центр устройств Подписывает сертификаты для открытых ключей зарегистрированных устройств. В текущей реализации ключ CA загружается из файла в процесс брокера. Не является сертификатом HTTPS-сервера и не подписывает релизы агента.
Движок политики Загружает YAML, проверяет ограничения, выбирает наборы ресурсов и компилирует правила nftables. Не обращается к агентам и не хранит сессии.
PostgreSQL Хранит токены регистрации, устройства, сертификаты, сессии и события аудита. Не хранит закрытые ключи устройств.
Агент шлюза Получает состояние от брокера, согласует его с nftables, отслеживает привязки IP/MAC и очищает conntrack при сокращении доступа. Не вычисляет бизнес-политику самостоятельно.
CLI оператора Управляет токенами и устройствами, проверяет политику, показывает сессии, аудит и состояние обновлений. Не устанавливает правила на шлюзе: это делает агент шлюза.

2.1. Границы доверия#

Данные устройства не равны решению сервера. Агент сообщает измерения и заявленный способ хранения ключа. Брокер отдельно записывает то, что проверил сам. Владелец, теги и область ответственности шлюза приходят из токена, созданного оператором, а не из запроса устройства.

nginx входит в доверенный контур аутентификации. Он перезаписывает X-Client-Verify, X-Client-Cert и X-Real-IP на каждом запросе. Брокер использует эти значения, поэтому его HTTP-порт нельзя открывать клиентам напрямую. Иначе клиент сможет подставить собственные заголовки.

Loopback не ограничивает доступ между локальными пользователями. Текущий слушатель принимает подключения и от непривилегированных локальных процессов, которые могут подделать доверенные заголовки. Проверки issuer и CN на этом пути не доказывают владение закрытым ключом. Ограничения upstream-сокета только для nginx или аутентификации транспорта прокси сейчас нет; хост с недоверенными локальными пользователями выходит за пределы защиты этой схемы развёртывания.

Шлюз входит в доверенный контур исполнения. Брокер доверяет наблюдениям шлюза о MAC-адресах в пределах назначенных ему сетей. Компрометация шлюза позволяет нарушить применение правил в этих сетях; сертификат шлюза не доказывает корректность работающего на нём nftables.

Система выпуска релизов — отдельный доверенный контур. Брокер передаёт подписанные предложения обновления, но ключ подписи релизов должен находиться вне брокера. Подробнее — в разделе 11.

3. Основные инварианты#

  1. Идентичность задаёт сертификат. После регистрации device_uuid извлекается из CN проверенного клиентского сертификата. Запросы продления и подтверждения сессии не принимают device_uuid в теле.
  2. Ключ сохраняется при продлении. Новый CSR должен содержать тот же открытый ключ, что и запись устройства. Замена ключа требует отдельной регистрации.
  3. Политика использует проверенные сведения. Для защиты ключа она читает key_protection_verified, а не key_protection_claimed. Обычные измерения ОС остаются сведениями от агента.
  4. Права не бессрочны. Сессия брокера и элементы nftables имеют ограниченный срок действия. Шлюз не продлевает разрешения по старому состоянию, когда брокер недоступен.
  5. Неоднозначный адрес не получает разрешений. Если несколько устройств с действующими разрешениями претендуют на один IP, брокер сообщает конфликт и не выдаёт разрешение для этого адреса.
  6. Устройство имеет одну текущую сетевую привязку. Подтверждение с нового известного адреса закрывает сессии того же устройства на других адресах.
  7. Путь к брокеру доступен до выдачи разрешений. Он сохраняется и после них, иначе устройство потеряет возможность обновлять доступ.
  8. Блокировка проверяется в БД. Действующий по срокам сертификат не позволяет заблокированному устройству подтвердить сессию, продлить сертификат или получить состояние шлюза.
  9. Отказ имеет объяснение. Решение содержит сработавшие правила и результаты проверок. Ошибка загрузки политики сообщается отдельно от отказа, принятого исправной политикой.

4. Идентичность и защита ключа#

4.1. Ключи и сертификаты#

В реализации используются несколько независимых ключей.

Ключ или сертификат Где находится Для чего нужен
Закрытый ключ устройства На устройстве: TPM 2.0, поддерживаемый аппаратный backend или файл. Подписывает CSR и участвует в mTLS. Устройство доказывает владение им при TLS-рукопожатии.
AK — ключ аттестации TPM В TPM; его открытая часть передаётся брокеру. Подписывает структуры TPM2_Certify и TPM2_Quote. Это отдельный ключ, поскольку ключ устройства должен уметь подписывать данные TLS.
EK — ключ идентификации TPM В TPM; брокер хранит открытый ключ и его отпечаток. Используется в проверке непрерывности идентичности через MakeCredential / ActivateCredential.
Ключ CA устройств На сервере брокера, в файловом хранилище текущей реализации. Подписывает клиентские сертификаты устройств.
Сертификат и ключ HTTPS-сервера В nginx. Позволяют агенту удостовериться, что он обращается к нужному брокеру.
Ключ подписи релизов В системе выпуска релизов, отдельно от брокера. Авторизует установку конкретного пакета агента.

Ключ устройства — ECDSA P-256. Брокер проверяет подпись CSR и отклоняет ключи других кривых. Сертификат устройства содержит его UUID в CN и действует 60 дней. Для mTLS агент использует ключ через интерфейс подписи; аппаратный backend не передаёт закрытую часть агенту.

Программный backend хранит копируемый ключ. Поэтому формулировка «ключ устройства нельзя перенести» применима к подходящему аппаратному backend, а не к любому зарегистрированному устройству.

4.2. Заявленный и проверенный уровни#

key_protection_claimed описывает заявление агента. Ему разрешено заявлять software или hardware_bound. Уровни attested и device_attested назначает только брокер после проверки доказательств.

Уровень Что означает
software Сервер не получил доказательств аппаратного размещения ключа. Это также исходный проверенный уровень для нового устройства.
hardware_bound Агент заявляет аппаратное хранение ключа. Брокер не присваивает это значение проверенному уровню: без проверенного TPM-доказательства остаётся software.
attested Брокер проверил согласованность TPM-доказательства: подпись AK, свойства ключей, nonce, имя сертифицируемого ключа и его соответствие CSR.
device_attested Дополнительно получен корректный ответ на проверку с закреплённым EK, что подтверждает сохранение идентичности относительно регистрации.

Это имена состояний протокола, а не шкала абсолютной защищённости. Политика перечисляет допустимые значения явно; порядок строк таблицы сам по себе не даёт устройству дополнительных прав.

На Linux и Windows TPM-путь позволяет получить attested и device_attested. Брокер проверяет доказательства вида tpm2; у ключей Secure Enclave нет пути серверной проверки аттестации.

На macOS агент может использовать постоянный ключ Secure Enclave, но брокер сохраняет key_protection_verified = software, даже если агент заявляет hardware_bound. Если оператор проверяет установку лично, результат можно отразить управляемым оператором тегом и отдельной политикой. Это организационная процедура, а не серверная аттестация. Особенности подписанной установки, пользовательского LaunchAgent и нескольких учётных записей описаны в документе о macOS.

4.3. Что аттестация доказывает и чего не доказывает#

Брокер закрепляет EK при первом обращении и далее проверяет его неизменность. Это модель доверия при первом использовании — TOFU. Цепочки сертификатов EK от производителей TPM не проверяются.

Следствие существенно: согласованное доказательство ещё не доказывает наличие настоящего TPM. Злоумышленник, контролирующий регистрацию, может создать согласованный набор программных ключей и структур, который пройдёт проверки. Такой случай предусмотрен тестами брокера. Поэтому device_attested нельзя трактовать как независимое подтверждение подлинности аппаратуры.

Для настоящего TPM закрепление ключей обнаруживает разрыв идентичности при переносе диска на другую машину, замене или сбросе TPM. Оно не отличает оригинал виртуальной машины от клона с копией состояния vTPM: у них те же ключи. Повторная регистрация одного открытого ключа фиксируется как duplicate_public_key, но сама по себе не блокируется. Клон уже зарегистрированного состояния не обязан регистрироваться заново, поэтому этот сигнал не гарантирует обнаружение каждого клона.

Одноразовый токен и контролируемая оператором регистрация остаются основой доверия к первому появлению устройства. Аппаратный ключ также не защищает от использования ключа атакующим, уже получившим доступ к работающей машине: невозможность извлечь ключ и невозможность вызвать операцию подписи — разные свойства.

4.4. Проверка состояния загрузки#

При TPM-проверке агент может прислать TPM2_Quote для PCR 0–7. Брокер проверяет подпись закреплённым AK, ожидаемый nonce, состав PCR и соответствие переданных значений подписанному digest.

Первый корректный digest сохраняется как исходное состояние. Далее сервер формирует сигнал verified_boot_state:

  • pinned — измерения совпадают с сохранёнными;
  • changed — корректное доказательство содержит другие измерения;
  • invalid — присланное доказательство не прошло проверку.

Совпадение означает неизменность относительно принятого исходного состояния, а не соответствие универсальному списку «безопасных» загрузок. Обновление BIOS или ОС может законно изменить PCR. Брокер не принимает новое состояние автоматически; для этого есть операторская процедура повторного закрепления с событием аудита.

Проверка непрерывности и загрузки выполняется с периодичностью continuity_minutes, по умолчанию 60 минут. Между проверками сервер использует последний результат. Значение 0 запрашивает доказательство при каждом подтверждении. Таким образом, периодичность проверки TPM задаёт отдельное предполагаемое окно обнаружения изменений и не совпадает со сроком сетевого разрешения.

Текущая реализация не проверяет свежесть результата загрузки отдельно. Корректный ответ на проверку непрерывности без PCR-цитаты может сохранить старое pinned и обновить общую временную отметку непрерывности. Повторение позволяет сохранять это значение бессрочно. Поэтому заданную периодичность нельзя считать гарантированным пределом обнаружения изменений загрузки у враждебного агента.

5. Жизненный цикл устройства#

5.1. Регистрация#

  1. Оператор создаёт одноразовый токен с владельцем, тегами и сроком действия; по умолчанию токен действует 30 минут. Для шлюза добавляет role:enforcer и обслуживаемые префиксы enforces.
  2. Токен передаётся устройству доверенным способом. CLI может выдать билет регистрации, который также содержит URL брокера и отпечаток сертификата для проверки его HTTPS-идентичности.
  3. Агент создаёт или открывает ключ и подписывает CSR. Он обращается к POST /v1/enroll/, передавая токен, CSR и сведения об устройстве. Клиентского сертификата у него ещё нет; HTTPS-сервер всё равно должен быть проверен.
  4. Брокер проверяет CSR и атомарно захватывает токен для однократного использования. Владелец, теги и enforces копируются из токена. Если передано TPM-доказательство, брокер проверяет его до создания записи устройства.
  5. Брокер создаёт Device, выдаёт сертификат, записывает событие регистрации и при необходимости возвращает TPM-запрос для следующего обращения.
  6. Агент сохраняет полученное состояние и начинает подтверждать сетевую сессию.

Регистрация не выдаёт корпоративные разрешения сама по себе. Она создаёт идентичность, которую затем оценивает политика доступа.

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

5.2. Продление сертификата#

Агент обращается к POST /v1/renew/ по mTLS с ещё действующим сертификатом. Брокер проверяет активность устройства, отзыв сертификата и совпадение открытого ключа нового CSR с сохранённым ключом. Изменение ключа отклоняется как key_rotation_not_allowed.

Ответ содержит новый сертификат и время следующего продления renew_after. Продление сертификата и обновление сетевого доступа разделены: новый сертификат не заменяет подтверждение сессии.

5.3. Блокировка и потеря ключа#

device block переводит устройство в BLOCKED. Брокер отказывает в его дальнейших аутентифицированных обращениях, а состояние для шлюзов больше не содержит его разрешений. Работающий шлюз применяет изменение при получении нового состояния; недоступный шлюз сохраняет старые разрешения только до истечения их таймеров.

Если закрытый ключ утрачен или перестал работать, обычное продление невозможно: агент не может выполнить mTLS со старой идентичностью. Сбросьте состояние агента и зарегистрируйте устройство с новым токеном. Оно получит новый device_uuid; старую запись следует отдельно заблокировать или удалить. hw_fingerprint используется для диагностики и не служит достаточным основанием для выдачи нового ключа.

Переход с ранее используемого аппаратного ключа на программный требует осознанного решения: агент хранит историю использования аппаратного backend и не должен молча создавать копируемую замену. Если старый ключ полностью потерян, понижение проверенного уровня на сервере само по себе не восстанавливает способность устройства пройти mTLS.

6. Модель политики#

6.1. Входные данные решения#

Рабочий путь подтверждения сессии передаёт движку:

Измерение Источник
state Для решения после подтверждения — proven. Правила admitted определяют минимальный доступ до подтверждения.
tier managed для всех зарегистрированных устройств.
device_tags Теги из записи устройства, назначенные оператором.
key_protection_verified Результат серверной проверки защиты ключа.
posture Результат оценки сигналов сервером.

Формат движка содержит owner_groups, но брокер не получает группы владельца из IAM и не передаёт их в решение. Загрузка политики отклоняет правила с owner_groups. Владелец сохраняется для учёта, а политика использует назначенные оператором device_tags.

IAM используется CLI для поиска UUID владельца по имени, если эта интеграция настроена. Агенту не нужен пользовательский IAM-токен для обычного подтверждения доступа.

6.2. Правила и объединение разрешений#

Политика — YAML-файл формата version: 2, состоящий из:

  • resource_sets — сетевые назначения: имя узла, IPv4-адрес или префикс, транспортный протокол и порт либо диапазон портов;
  • posture — необходимые сигналы и допустимый возраст отчёта;
  • policies — условия и выдаваемые наборы ресурсов;
  • constraints — запрещённые сочетания условий и разрешений;
  • tests — примеры ожидаемых решений.

Совпавшие правила складываются. Движок объединяет наборы ресурсов всех подходящих правил, удаляет повторы и сортирует результат. Приоритетов по порядку строк и правила «первое совпадение» нет. Если ни одно правило не совпало, дополнительных разрешений нет. Правила с пустым grant отвергаются при загрузке политики; отменяющих правил нет.

Например, в примерной политике устройство отдела разработки может получить base и eng по правилу отдела, а затем grafana по отдельному правилу для дополнительного тега. Итог — объединение этих трёх наборов. Каждое правило само должно задавать достаточные условия доступа.

Теги бывают простыми (hardened) и вида ключ:значение (type:full, dept:engineering). Устройство имеет одно значение для каждого ключа. Между разными ключами действует «И», между разрешёнными значениями одного ключа — «ИЛИ». Отсутствующий тег не считается подходящим значением.

constraints проверяются при загрузке против правил, а не только против отдельных тестовых запросов. Например, ограничение может запретить доступ к prod_ro любому правилу, допускающему software, или потребовать обязательный тег hardened для выдачи этого набора.

Имена ресурсов разрешаются в IPv4-адреса при загрузке политики. В nftables передаются адреса, а не доменные имена. Изменение DNS само по себе не обновляет уже загруженные наборы; нужно обеспечить повторную загрузку. Команда policy check --no-resolve проверяет структуру с подстановочным адресом и не доказывает правильность DNS.

6.3. Оценка состояния устройства#

Агент отправляет posture_report с временем измерения и набором сигналов, например версией агента. Брокер сравнивает их с требованиями политики и формирует одно из состояний:

Состояние Условие
compliant Все заданные проверки выполнены.
degraded Есть отчёт, но хотя бы одна проверка не выполнена.
unknown Отчёта нет, он устарел или существенно датирован будущим временем.

По умолчанию допустимый возраст отчёта — 300 секунд; его меняет posture.max_age_seconds. Проверка отсутствующего сигнала не проходит. При наличии свежего отчёта и отсутствии требований результат будет compliant: отсутствие требований не означает наличие защиты.

Агенту запрещено присылать сигналы с префиксом verified_. Их добавляет брокер, например verified_boot_state. Это не позволяет подменить серверный результат обычным полем отчёта.

Прочие сигналы всё равно измеряет агент, и скомпрометированный агент может сообщить ложные значения. Перенос оценки на сервер обеспечивает единые требования, но не превращает каждое измерение ОС в аппаратное доказательство.

Состояние вычисляется для всей сессии. Перед введением обязательного сигнала нужно проверить его наличие на всех целевых платформах, иначе правило с posture: compliant закроет доступ части парка. Сокращённый доступ при software, degraded или unknown задаётся политикой явно; сервер не выдаёт его автоматически.

7. От подтверждения устройства к разрешению#

7.1. Подтверждение сессии#

Агент                 nginx                 Брокер                  Шлюз
  │ HTTPS/mTLS          │                      │                      │
  ├────────────────────►│ проверка сертификата  │                      │
  │                     ├─────────────────────►│                      │
  │                     │                      │ проверка устройства  │
  │                     │                      │ TPM и posture        │
  │                     │                      │ решение политики     │
  │                     │                      │ запись сессии        │
  │◄────────────────────┴──────────────────────┤                      │
  │ решение, причины, срок                     │                      │
  │                                            │◄─────────────────────┤ запрос состояния
  │                                            ├─────────────────────►│ разрешения и ruleset
  │                                            │                      │ применение nftables
  ├───────────────────── трафик к ресурсам ────────────────────────────►│

В POST /v1/session/prove/ агент отправляет измерения и, если запрос был выдан ранее, ответ на TPM-проверку и доказательство загрузки. Брокер определяет устройство по сертификату, а адрес — по X-Real-IP, который nginx сформировал из адреса принятого соединения.

Затем брокер проверяет доказательства, оценивает состояние, выполняет политику и сохраняет решение в сессии для пары «устройство, адрес». После обработки состояние сессии — proven, в том числе при пустом списке разрешений. Это означает, что запрос обработан, а не что доступ обязательно разрешён.

Агент получает наборы ресурсов, сработавшие правила, причины неудачных проверок и срок сессии. Поля enforced, enforced_from, enforced_to и broker_endpoints описывают известную брокеру область применения и помогают агенту выбрать правильный сетевой путь.

enforced: true означает, что зарегистрирован активный шлюз с подходящей областью ответственности. Это не подтверждение, что шлюз в данный момент доступен, применил последнее решение или что пакеты действительно проходят через него.

Ответ агенту и установка разрешения на шлюзе — два разных события. Решение становится действующим для трафика после получения и применения состояния шлюзом. Брокер не ждёт подтверждения установки перед ответом на prove.

7.2. Три независимых срока#

Механизм Значение Что происходит при истечении
Сертификат устройства 60 дней Невозможно новое успешное mTLS-обращение без продления сертификата.
Сессия брокера 15 минут после последнего решения Сессия подлежит закрытию и перестаёт попадать в полный ответ с разрешениями.
Элемент разрешения nftables 15 минут после установки или обновления элемента Ядро убирает адрес из набора разрешённых источников.

Шлюз применяет относительный lease_seconds, а не абсолютное время lease_expires_at из каждой записи. Серверный срок и таймер ядра поэтому не синхронны. Удаление разрешения после прекращения prove зависит от закрытия сессии и получения нового состояния шлюзом.

При недоступности брокера шлюз не переустанавливает элементы из кеша. Действующие элементы заканчиваются по своим таймерам: для текущих 15-минутных разрешений — не позднее 15 минут после последнего успешного обновления элементов на этом шлюзе. Это точнее, чем обещание «через 15 минут после последнего запроса устройства».

Истечение элемента ограничивает доступ в исходящем направлении. Для прекращения уже отслеживаемого ответного трафика требуется также очистка conntrack, описанная в разделе 8.2. Она выполняется агентом в цикле применения состояния. При неуспешном запросе к брокеру этот цикл не меняет ядро, поэтому таймер элемента нельзя считать самостоятельной гарантией немедленного прекращения всех ранее открытых потоков.

Сбой TPM-проверки непрерывности при сохранённой возможности mTLS понижает проверенный уровень, после чего политика решает, какие ресурсы остаются. Полная потеря ключа — другой случай, описанный в разделе 5.3.

8. Применение разрешений на шлюзе#

8.1. Получение состояния#

Шлюз регистрируется как обычное устройство с тегом role:enforcer. Отдельного сертификата шлюза или второй CA для него нет.

По mTLS шлюз вызывает GET /v1/dataplane/state/ и получает:

  • скомпилированный ruleset и его policy_version;
  • разрешения по адресам: наборы ресурсов, UUID устройства и MAC-привязку;
  • общий срок разрешения lease_seconds;
  • конфликты адресов и собственную область enforces.

Брокер исключает истёкшие сессии, заблокированные устройства, неизвестные текущей политике наборы и адреса вне области этого шлюза. Пустой список enforces означает все адреса, а не отсутствие полномочий. При нескольких шлюзах области нужно задавать явно. Те же границы проверяются при приёме сообщений шлюза о привязках.

Есть два режима опроса:

  1. Быстрый условный запрос — по умолчанию каждые 3 секунды. Шлюз передаёт непрозрачный ETag в If-None-Match. Если применяемое состояние не изменилось, брокер отвечает 304 с новым курсором.
  2. Периодический полный запрос — через треть срока разрешения, то есть примерно каждые 5 минут. Он выполняется без курсора, чтобы обновить таймеры даже при неизменных правах.

Ответ 304 ничего не переустанавливает и не продлевает таймеры. Сравнение учитывает правила, состав разрешений, привязки и область шлюза; обычное изменение серверного срока при очередном prove не обязано вызвать полную перезапись всех элементов.

Версия правил определяется по их содержимому. Новая версия требует загрузки правил, а обычное изменение разрешений — обновления элементов. Агент применяет изменения транзакцией nftables. При ошибке применения следующий запрос должен получить полное состояние, чтобы шлюз не принял «ничего не изменилось» за подтверждение неустановленных правил.

8.2. Структура nftables#

Компилятор создаёт таблицу inet nac:

  • rs_<name> содержит назначения набора: IPv4-адрес, протокол и порт;
  • granted_<name> содержит адреса устройств с доступом к этому набору и таймером 15 минут;
  • bound_addrs и device_bindings содержат проверяемые IP/MAC-привязки;
  • цепочка forward применяет правила к проходящему через шлюз трафику.

Правила существуют для наборов ресурсов, а не отдельно для каждого устройства. Число устройств увеличивает число элементов в множествах, но не создаёт отдельную цепочку правил на каждую машину.

В режиме применения цепочка по умолчанию закрыта. Порядок проверок:

  1. Разрешить ответное направление уже отслеживаемого соединения: ct direction reply ct state established,related accept.
  2. Разрешить минимальные назначения до подтверждения устройства.
  3. Отклонить Ethernet-кадр с чужим MAC для уже закреплённого IP.
  4. Разрешить трафик, соответствующий наборам, выданным источнику.
  5. Отклонить остальной трафик; IPv6 учитывается отдельным счётчиком.

Общее правило ct state established,related accept здесь не подходит: оно оставило бы инициированный устройством поток открытым после сокращения его прав. Для прекращения серверного трафика в обратном направлении агент шлюза дополнительно удаляет conntrack-записи источника при потере разрешений. Очистка выполняется после применения новых правил и имеет собственную диагностику ошибок.

Компилятор поддерживает режим наблюдения monitor: журналирует трафик, который был бы отклонён, но не блокирует его. Такой режим пригоден для оценки политики и не обеспечивает изоляцию.

8.3. Минимальный доступ до подтверждения#

Наборы, указанные в правилах с state: admitted, формируют доступ, который действует для любого источника на контролируемом пути, без индивидуального разрешения. Обычно это брокер, DNS и необходимые службы регистрации. quarantine — обычное имя набора, а не отдельный режим фильтрации.

Брокер добавляет адреса из broker_endpoints в эти наборы при загрузке. Поэтому они должны существовать либо доступ к брокеру должен быть обеспечен отдельно. Разрешения для них находятся до индивидуальных проверок: устройство должно уметь зарегистрироваться и восстановить доступ, даже когда оно ещё не доказало свою идентичность или потеряло обычные разрешения.

После успешного prove минимальный путь не исчезает. После блокировки устройства он также остаётся свойством сетевой политики. Соответственно, блокировка NAC прекращает индивидуально выданный доступ, но не означает полного отключения машины от VPN, Wi-Fi или минимальных служб.

8.4. Повторное использование IP и MAC-привязки#

На Ethernet-сегменте шлюз наблюдает соседей и закрепляет MAC за адресом действующей сессии. Привязка передаётся в POST /v1/dataplane/bindings/ и сохраняется брокером, чтобы после перезапуска шлюз получил её обратно, а не научился адресам заново.

Если IP начинает отвечать с другого MAC, шлюз убирает прежнее разрешение локально и сообщает изменение брокеру. Брокер закрывает сессии адреса и перестаёт выдавать их разрешения. Новому устройству нужно собственное подтверждение.

Это дополнительная защита от наследования чужого разрешения при выдаче старого IP другому устройству. Она не является криптографической аутентификацией Ethernet: одновременная подмена IP и MAC требует защиты на коммутаторе, а за промежуточным маршрутизатором шлюз видит MAC маршрутизатора. На L3-туннеле Ethernet-привязки неприменимы; защиту от подмены адреса обеспечивает VPN-инфраструктура.

8.5. Ограничения сетевого контура#

  • Выдаваемые разрешения используют только IPv4. В режиме применения IPv6 не получает индивидуального доступа; на пересылаемом пути сохраняется разрешение для отслеживаемого ответного трафика, а остальной IPv6 отклоняется. Полноценной dual-stack-политики нет. Брокер не исключает IPv6-адреса сессий при пустом enforces шлюза. Такое разрешение попадает в наборы ipv4_addr и может сорвать всю транзакцию обновления, после чего разрешения сегмента истекут. Поэтому IPv4-компиляция сама по себе не является безопасным фильтром входных IPv6-адресов.
  • Фильтруется forward, поэтому доступ к сервисам самого шлюза через input должен защищаться отдельно.
  • Обратное направление опирается на conntrack. Одновременная работа нескольких маршрутизирующих шлюзов с асимметричными маршрутами не является поддержанным сценарием отказоустойчивости.
  • Набор ресурсов — сетевое разрешение, а не роль внутри приложения. Например, имя prod_ro не делает соединение с сервисом доступом «только для чтения»: это обязанность самого приложения.

9. Требования к подключаемой сети#

Работающий брокер и успешный prove ещё не доказывают, что сеть правильно применяет NAC. Следующие условия относятся к инфраструктуре и должны проверяться при интеграции.

Требование Зачем оно нужно Последствие нарушения
Сохранять адрес источника между устройством, брокером и шлюзом. По наблюдаемому IP брокер связывает идентичность с пакетами. NAT объединяет устройства под одним адресом или выдаёт разрешение не тому адресу.
Направлять контролируемые назначения через шлюз NAC. Правила работают только на пути фактического трафика. Ресурс остаётся доступным по обходному маршруту независимо от решения NAC.
Предоставить путь к брокеру до подтверждения. Без него нельзя зарегистрироваться и продлить доступ. Замкнутый отказ: устройство не получает разрешение, потому что не может запросить его.
Не допускать подмену адреса источника. Разрешение привязано к адресу пакета. Чужой IP позволяет претендовать на чужое разрешение; MAC-привязка покрывает только часть сценариев.
Изолировать клиентов, обменивающихся трафиком в обход L3-шлюза. Межклиентский трафик может не попадать в forward. Прямой обмен в L2-сегменте или внутри VPN обходит NAC.
Согласовать путь prove с путём к ресурсам. У устройства одна текущая адресная привязка. Разрешение ставится для интерфейса, которым корпоративный трафик не пользуется.
Разместить наблюдение MAC на обслуживаемом сегменте. Нужен MAC устройства, а не промежуточного роутера. Защита от передачи адреса другому владельцу теряет различающую способность.
Учесть IPv4 и служебный доступ отдельно. DHCP, локальный DNS и службы самого шлюза могут не проходить через эту цепочку. Часть базовых служб недоступна либо оказывается вне правил NAC.

Для VPN это означает сохранение исходного адреса клиента на пути к брокеру и ресурсам, проверку адресов клиентов самим VPN и отсутствие обходного межклиентского пути. Для офисной сети — контролируемую маршрутизацию, защиту источника и изоляцию на коммутаторах или AP. NAC не настраивает эти свойства автоматически.

Единый адресный план#

broker_endpoints содержит все адреса одного брокера, доступные из обслуживаемых сетей. Этот список используется в трёх местах:

  1. Агент выбирает подходящий адрес брокера.
  2. Компилятор добавляет адреса в минимальный разрешённый путь.
  3. policy routes формирует назначения для внешней настройки маршрутов VPN или DHCP.

Агент использует также enforced_from и enforced_to из ответа, сопоставляет маршруты к корпоративным назначениям с маршрутом к выбранному брокеру и сравнивает локальный адрес обращения с наблюдаемым сервером. Эти проверки помогают обнаружить ошибочную привязку, но не доказывают отсутствие обходного шлюза: два маршрута могут иметь один адрес источника.

При одновременном офисном подключении и VPN нельзя рассчитывать на независимые разрешения для обеих сетей у одного device_uuid. План маршрутов должен обеспечить единую рабочую привязку для контролируемого трафика.

10. Хранение данных, отказы и эксплуатация#

10.1. Модель данных и аудит#

Сущность Основные данные
EnrollmentToken Секрет регистрации, владелец, теги, enforces, срок действия, использование и отзыв.
Device UUID, владелец, теги, статус, отпечаток ключа, платформа, аппаратный отпечаток, заявленная и проверенная защита, закреплённые EK/AK и состояние загрузки.
DeviceCertificate Выданный сертификат, серийный номер, сроки действия и продления, причина выпуска и отметка отзыва.
Session Устройство, адрес, MAC-привязка, состояние, результат posture, разрешения, сработавшие правила и временные границы.
AuditEvent Событие, UUID устройства, описание, адрес источника и уровни защиты ключа.

Сессии позволяют ответить на вопрос «какое устройство использовало адрес в указанный момент». Это запись наблюдаемой привязки, а не полный журнал потоков и не история каждого изменения политики внутри одной сессии.

События аудита хранятся в PostgreSQL. Настройте доступ и сроки хранения БД и резервных копий с учётом сведений о владельцах и истории сетевых адресов, токенов и состояния незавершённых проверок.

Истёкшие сессии закрываются при обработке запросов и командой session reap; поставляемый systemd-таймер запускает её каждые 5 минут. Отдельный prune-таймер предназначен для удаления старых закрытых сессий, аудита и завершённых токенов. Сроки хранения задаёт оператор; по умолчанию автоматическое удаление этих данных отключено.

10.2. Поведение при отказах#

Событие Поведение системы
Брокер или его БД недоступны Новые решения не выдаются. Шлюз не продлевает разрешения из старого ответа; установленные элементы заканчиваются по таймерам.
Агент устройства перестал подтверждаться Серверная сессия истекает; при следующем актуальном состоянии шлюз удаляет её разрешения.
TPM-доказательство непрерывности не прошло, mTLS работает Проверенный уровень понижается; политика заново определяет доступ.
Закрытый ключ утрачен Устройство не проходит mTLS. Требуется повторная регистрация, а не простое продление.
Новый файл политики ошибочен или нечитаем Уже загруженная политика сохраняется, ошибка записывается в журнал. После перезапуска процесса этот кеш не сохраняется.
Ни одна политика ещё не загружена Брокер возвращает policy_unavailable, а не изображает обычный отказ по политике.
Применение nftables завершилось ошибкой Шлюз сообщает ошибку и повторно запрашивает полное состояние; прежние таймеры не превращаются в бессрочные разрешения.
Устройство заблокировано Аутентифицированные операции запрещены; разрешения исчезают из актуального состояния шлюза.
Несколько устройств претендуют на один адрес Разрешения конфликтующего адреса не выдаются; конфликт возвращается шлюзу и фиксируется в аудите.

Нужно различать сохранность решения в БД, успешный ответ шлюзу и фактическую работу правил ядра. Для приёмки важны проверки трафиком: разрешённое назначение доступно, запрещённое закрыто, сокращение прав прерывает действующий поток и непродлённое разрешение истекает.

10.3. Отказоустойчивость и защита сервера#

Текущий рабочий сценарий — один маршрутизирующий шлюз на сегмент. Сохранённые MAC-привязки позволяют восстановить их после перезапуска или передать резервному шлюзу, но не означают готовую синхронизацию conntrack, выбор активного узла или бесшовный перенос соединений.

Эти свойства описывают шлюз с загруженными правилами. До первого успешного получения состояния после холодной загрузки защита зависит от базового firewall и настройки forwarding. Приёмка должна включать перезагрузку шлюза при недоступном брокере: одни таймеры не проверяют это окно.

Работа брокера предполагает единственный активный источник конфигурации. Несколько процессов с общей БД сами по себе не синхронизируют YAML-политику, ключи CA и конфигурацию и не координируют переключение.

Брокер предназначен для размещения внутри частной сети с nginx перед ним. Клиентский сертификат nginx запрашивает опционально, чтобы регистрация без него была возможна; на остальных операциях брокер требует результат проверки SUCCESS. Представленный недоверенный сертификат nginx отклоняет ещё до передачи запроса.

Поставляемая конфигурация ограничивает размер тела до 16 KiB и раздельно ограничивает частоту обычных запросов и частого опроса шлюзов. Эти ограничения должны соответствовать периодичности агентов: ограничение шлюза по норме регистрации может остановить обновление доступа целого сегмента.

Ключ CA доступен процессу брокера. Компрометация этого контура позволяет выпускать идентичности устройств, изменять политику и состояние доступа. HSM и отдельный сервис подписи не входят в эту схему. Размещение внутри частной сети не устраняет этот риск.

11. Обновление агента#

Обновление связано с доступом: неисправный агент перестаёт подтверждать сессию, а минимальная версия в posture-политике может закрыть доступ отстающим устройствам. Поэтому выпуск пакета, доставка и восстановление после ошибки должны рассматриваться вместе.

Брокер читает манифест из agent_release_file и в ответе на prove может вернуть agent_update. Он выбирает пакет по платформе, архитектуре и формату установки, а устройство — по устойчивой когорте, вычисленной из UUID. Увеличение доли share расширяет когорту без случайного перераспределения уже включённых устройств. Для role:enforcer используется отдельная доля enforcer_share, по умолчанию нулевая.

Предложение содержит Ed25519-подпись, сделанную ключом выпуска релизов. Подпись покрывает версию, ОС, архитектуру, формат и SHA-256 пакета. Адрес загрузки и доля раскатки не подписываются: они определяют место доставки и участников, но не разрешённое содержимое пакета. Брокер может задержать предложение или доставку, но без ключа релизов не может авторизовать подменённый пакет.

Агент проверяет предложение, загружает пакет, сверяет digest и вызывает установщик платформы. Применение по умолчанию включено для проверенных предложений и требует доверенного ключа релизов. На macOS установку из пользовательского агента выполняет отдельный привилегированный помощник.

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

Если агент не может подтвердить сессию из-за несовместимой версии контракта или неразбираемого ответа, он получает то же подписанное предложение через стабильный GET /v1/device/update/. Этот эндпоинт требует сертификат устройства и не проверяет версию контракта (протокол, §4d).

Предложение более старой версии не является разрешением на откат. Для него требуется подписанное поле rollback_from, ограничивающее самую новую версию, которую разрешено заменить. Возможность установки назад также зависит от платформенного установщика; подпись не отменяет ограничений MSI или других форматов.

Оператор управляет расширением и остановкой раскатки через release status и сведения о версиях устройств. Перед повышением обязательной версии в политике нужно обеспечить доставку обновления и путь восстановления; один параметр at_least не заменяет раскатку.

Подробные процедуры находятся в руководстве по обслуживанию и документации агента.

12. Навигация по коду и связанным документам#

Задача изучения Источник
Найти действующие HTTP-маршруты routes.py
Проследить аутентификацию, регистрацию и решения controllers.py
Разобрать хранение устройств и сессий models.py
Проверить подпись CSR, выдачу сертификата и TPM-доказательства ca.py, attestation.py
Изучить формат, загрузку и принятие решения по политике model.py, source.py, decide.py
Проследить оценку состояния и компиляцию nftables posture.py, compile.py
Разобрать условные запросы шлюза dataplane.py
Проверить настройки TLS и доверенные заголовки конфигурация nginx
Найти значения конфигурации и CLI config.py, cli.py
Разобрать предложения обновлений release.py
Проследить применение правил и установку пакетов internal/enforce, internal/update
Сверить контракт и примеры сообщений Протокол, эталонные сообщения
Подготовить установку и проверить её результат Развёртывание, проверки, особенности macOS