qf хостовый firewall на eBPF
файрвол как код (firewall as code)

Политики как код: label-селекторы, каскад, dry-run

Одна декларативная политика описывает разграничение доступа между серверами (сегментацию) на всём парке Linux. Хосты выбираются label-селекторами, а не IP-списками; изменение каскадно пересчитывается на затронутые хосты, а предпросмотр (dry-run) показывает результат до применения.

что это

Файрвол как код для парка Linux

Политики как код — это декларативные правила файрвола на каждом сервере (host-firewall), которые описывают, кто с кем может общаться, через метки хостов, а не через IP-адреса. Управляющий сервер (control plane) компилирует политику в данные BPF-карт и рассылает подписанные пакеты политики (бандлы) агентам. Одна политика управляет всем парком вместо ручного iptables на каждой машине.

Хост попадает под правило по своим меткам, а не по адресу: селектор matchLabels требует совпадения всех указанных меток (AND), anyOf — любой из перечисленных (OR). Когда в парк добавляется хост с подходящими метками, он получает нужные правила автоматически, без правки самой политики.

из чего состоит политика

Четыре части политики

Селекторы выбирают хосты, object-группы описывают адреса и порты, каскад раскатывает изменения, dry-run проверяет их до применения.

01 · селекторы

Label-селекторы

Хосты выбираются метками через matchLabels (совпадение всех меток, AND) или anyOf (любая из меток, OR). Правило следует за меткой, а не за IP: новый хост с подходящими метками подхватывает правила сам.

02 · object-группы

Object-группы

Переиспользуемые наборы адресов и портов: ipset (LPM-префиксы CIDR), portset (диапазоны портов) и hostset (группы хостов). Одна группа подставляется в несколько правил: адреса и порты заданы в одном месте.

03 · каскад

Каскадный пересчёт

Изменение политики или object-группы запускает пересчёт только затронутых хостов, а не всего парка. Каждому хосту собирается новый бандл с инкрементной генерацией и рассылается его агенту по mTLS gRPC.

04 · dry-run

Dry-run до применения

Предпросмотр показывает, какие хосты и правила изменятся до того, как политика уйдёт в парк. Никакого «проверю сразу на проде»: сначала diff затронутых хостов и правил, потом осознанное применение.

жизненный цикл изменения

От правки политики до применения в ядре

  1. 01

    Описать политику

    Декларативно: label-селекторы для хостов, object-группы для адресов и портов. Никаких per-host правил — одна политика на весь парк.

  2. 02

    Прогнать dry-run

    Предпросмотр возвращает diff: какие хосты попадают под изменение и какие правила добавятся или уберутся. Проверка до применения, а не после.

  3. 03

    Каскадно пересчитать

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

  4. 04

    Подписать и раскатать

    Бандл подписывается Ed25519 (аутентичность политики) и рассылается агентам по mTLS gRPC. Агент компилирует его в BPF-карты и энфорсит в ядре.

Наблюдаемый трафик — на странице хоста

Dry-run отвечает на вопрос «какие хосты и правила изменятся». Реальный трафик и вердикты правил смотрятся отдельно, на вкладках Counters и Verdicts конкретного хоста, а не внутри предпросмотра.

числа

Пределы и масштаб раскатки

5–15 с
каскадная раскатка на 500 хостов
30–90 с
раскатка на 5000 хостов (последовательно)
≤ 2048
правил на хост на ядрах ≥ 5.17
5000+
агентов на один управляющий сервер

До 32 правил на ядрах 5.15–5.16 и до 2048 на ≥5.17. Один управляющий сервер тянет более 5000 агентов.

границы покрытия

Что остаётся вне правил

Правила работают на L3/L4. Непарсимый L4 (SCTP, GRE, ESP) проходит мимо правил и не попадает под режим «запрещать по умолчанию» (default-deny); L7/DPI нет; разграничение по IPv6-CIDR не энфорсится (v6 по умолчанию отбрасывается целиком). Граница проходит здесь: qf ограничивает горизонтальный доступ (east-west) между серверами на IPv4 L3/L4, а не «любой трафик».

поведение по умолчанию

Управляемый поэтапный переход к default-deny

По умолчанию qf работает в режиме fail-open (трафик не рвётся при потере связи): забытое правило не отрежет хост от сети, а при разрыве связи с управляющим сервером хост продолжает работать по последним применённым правилам. Сегментацию включают поэтапно и под наблюдением: сначала режим log, потом разбор трафика, затем deny. «Default-deny из коробки» qf сознательно не включает: на большом парке безопаснее выкатывать запрет постепенно.

вопросы

Частые вопросы

Чем label-селекторы лучше IP-списков?

Правило следует за меткой хоста, а не за его адресом. matchLabels требует совпадения всех меток (AND), anyOf — любой из них (OR). Новый хост с подходящими метками автоматически подхватывает нужные правила, без правки самой политики и без ручного добавления IP.

Что делает dry-run перед применением?

Предпросмотр показывает, какие хосты попадут под изменение и какие правила добавятся или уберутся, до того как политика уйдёт в парк. Наблюдаемый трафик и вердикты правил смотрятся отдельно, на вкладках Counters и Verdicts конкретного хоста.

Пересчитывается ли весь парк при каждом изменении?

Нет. Каскад пересчитывает только затронутые хосты, а не весь парк. Каждому собирается бандл с инкрементной генерацией и рассылается его агенту. На 500 хостов раскатка занимает 5–15 с, на 5000 — 30–90 с (последовательно).

Как откатить неудачную политику?

Каждое применение — новое поколение бандла; предыдущие версии политики и поколения бандлов сохраняются, а журнал аудита фиксирует «было → стало». Откат — это возврат к прошлой версии политики, а не отдельная кнопка «мгновенного отката».

Как политика доезжает до хоста в безопасном виде?

Управляющий сервер компилирует политику в данные BPF-карт, подписывает бандл ключом Ed25519 (аутентичность политики) и рассылает по mTLS gRPC. Агент проверяет подпись, компилирует бандл в BPF-карты и энфорсит его в ядре на TC-хуке.

Разграничение доступа как код