Перейти к основному содержимому

Как устроено управление файрволом в qf

Этот обзор показывает, как объекты qf превращаются в правила фаервола на хосте. Сначала лейблы связывают хост с политикой, затем CP объединяет и упорядочивает правила, а агент применяет их в eBPF-датапасе. В конце приведён сквозной пример.

qf — централизованный фаервол: политики задаются в Control Plane и доставляются агентам, которые применяют их в ядре через eBPF. После установки агента правки политик не требуют ручной настройки на каждом хосте.


Пять объектов связаны лейблами

Управление строится на пяти объектах; лейблы служат атрибутами хостов и групп. Поток идёт сверху вниз: лейблы определяют назначение политики, а её правила фильтруют трафик.

HOST машина с агентом. Носит LABELS (пары key=value).
│ лейблы приходят двумя путями: из enrollment-токена и от групп.

HOST GROUP ярлык на пачке хостов. Даёт своим членам общие LABELS.
│ (лейбл самого хоста перекрывает групповой при конфликте ключа)

▼ Эффективные лейблы хоста = объединение(лейблы хоста + лейблы всех его групп)

POLICY SELECTOR + список RULES.
│ selector ← сопоставляется с эффективными лейблами хоста → «кого касается»
│ rules ← что делать с трафиком на этих хостах

RULE direction (ingress/egress) + action (allow/deny) + match (порты/proto/CIDR)

OBJECT GROUP переиспользуемый набор: ipset (CIDR) / portset (порты) / hostset.
правило ссылается на него по UUID вместо ручного списка адресов/портов.
ОбъектЧто этоЗачем
HostМашина с установленным агентомОбъект защиты; носит лейблы
LabelПара key=value на хостеПо ним политика находит свои хосты
Host GroupИменованная группа хостов с общими лейбламиУправлять лейблами пачки хостов в одном месте
PolicyСелектор + набор правилСвязывает «кого» (селектор) и «что» (правила)
RuleОдно действие allow, deny или logФильтрация или регистрация трафика
Object GroupПереиспользуемый набор IP/портов/хостовНе дублировать списки адресов в правилах

Ключевая идея: политика находит хосты по лейблам, а не по именам машин. Селектор env=prod назначает политику текущим и будущим хостам с этим лейблом. Идентификатор хоста нужен только для точечного назначения.


Эффективные лейблы

Хост получает лейблы из двух источников:

  1. Enrollment-токен — при подключении хоста к флоту токен «штампует» на него заданные лейблы (например role=web, env=prod). Это основной путь.
  2. Host Group — если хост состоит в группе, он наследует лейблы группы.

Итоговый набор, по которому работают селекторы, — эффективные лейблы:

эффективные лейблы = лейблы всех групп хоста ⊕ собственные лейблы хоста
(при конфликте ключа собственный лейбл хоста побеждает)

Именно эффективные лейблы, а не «сырые», сопоставляются с селектором политики.


Как политика находит хост (selector)

Селектор политики — это условие на лейблы. Хост попадает под политику, если его эффективные лейблы удовлетворяют селектору.

  • Все лейблы сразу (AND)matchLabels. Селектор {role=web, env=prod} выбирает хост только при наличии обоих лейблов.
  • Любой из вариантов (OR) — несколько блоков (anyOf). В UI собирается неявно: добавили несколько групп/хостов в «Host selector» → получаете OR.
  • Конкретная машина — по идентификатору; в консоли она выбирается по имени.
  • Все машины — match-all; UI требует подтверждения (защита от случайного применения на весь флот).

Пустой Host selector означает весь парк, а не отсутствие назначения. Консоль потребует подтверждение. Чтобы через API временно не выбирать ни одного хоста, используется {"anyOf":[]}.

Подробно — selector.md.


Порядок правил: first-match-wins и default-ALLOW

На одном хосте может действовать много правил (из одной или разных политик). Для каждого пакета правила проверяются по порядку:

  1. Политики: меньше Priority = раньше (главнее).
  2. Внутри политики: правила по своему Priority; при одинаковом Priority сохраняется их порядок в редакторе. Rule ID и этот порядок не меняются от повторного PUT.
  3. Первое подходящее правило сработало → остальные для этого пакета не смотрятся.
  4. Не подошло ни одно правило → пакет пропускается (default-ALLOW).

Default ALLOW означает, что фаервол блокирует только трафик, совпавший с явным deny. Непокрытый правилами трафик проходит.

⚠️ deny без match блокирует весь поддерживаемый трафик. Агент сохраняет исходящие соединения к IPv4-адресам Control Plane, разрешённым при его старте, но это не защищает SSH и другие административные каналы. Перед широким запретом нужны разрешающие правила для них, проверка зоны влияния черновика и этап наблюдения с действием log. Для обычной сегментации безопаснее ограничивать deny портами и адресами.

ℹ️ Enforcement применяется к L4 = TCP / UDP / ICMP / ICMPv6. Прочие протоколы (SCTP, GRE, ESP/IPsec, OSPF и т.п.) датапас не парсит — по умолчанию они проходят без правил (даже дефолтный deny к ним не применяется). Опциональный agent-флаг QF_DENY_UNKNOWN_PROTO направляет такой трафик в текущий default action вместо безусловного пропуска. Подробнее — ops-runbook.md → §8.4 «Неподдержанные L4».

Подробно про правила, приоритеты, версии/откат — policy-management.md.


Object Groups — переиспользуемые наборы

Чтобы не вписывать одни и те же списки адресов/портов в каждое правило, их выносят в именованный набор, на который правило ссылается:

ТипСодержитПример
ipsetCIDR/IP10.0.0.0/16, 203.0.113.5
portsetПорты и диапазоны443, 8080-8090
hostsetСелектор → динамически резолвится в IP подходящих хостов«IP всех role=db»

Правка набора пересчитывает все политики, где он используется. Набор, на который ссылается правило, нельзя удалить (защита от «висячих» ссылок). Подробно — fleet-management.md.

ipset и portset не могут быть пустыми. Динамический hostset может временно разрешиться в пустое множество; в этот момент CP не трактует его как ANY и не отправляет новый bundle — хост остаётся на last-good до восстановления membership.


Сквозной пример: закрыть порт на всех prod-web

Задача: запретить входящие подключения на TCP-8080 на всех web-серверах окружения prod.

  1. Лейблы на хостах. Убедиться, что у нужных машин есть лейблы role=web и env=prod. Штатно они приезжают из enrollment-токена при подключении хоста; либо их даёт Host Group (см. шаг 2).
  2. (если нужно) Host Group. Host Groups → New group → имя prod-web, лейблы role=web, env=prod → добавить машины. Члены группы наследуют эти лейблы.
  3. Политика. Policies → New policy → имя, например close-8080.
  4. Host selector. Задать условие по лейблам: role=web и env=prod. Политика будет действовать на все подходящие хосты — и на будущие тоже.
  5. Правило. Add rule: Direction ingress, Action deny, Protocol tcp, Dst ports 8080.
  6. Сохранение. При создании политика применяется сразу. Поэтому сначала безопаснее сохранить правило с действием log и проверить события в Verdicts.
  7. Переход к блокировке. Изменить действие на deny, зафиксировать изменение как черновик, проверить список хостов и различия правил в Зоне влияния, затем применить черновик. CP отправит правила подходящим подключённым хостам. Офлайн-хост получит их при следующем подключении. Новая машина с лейблами role=web и env=prod также попадёт под политику.

Разбор «почему не идёт трафик»: на странице хоста — вкладка Ruleset (что реально применено), Verdicts (сработавшие log/deny), Counters (рост счётчика правила). См. раздел «Разбор инцидента» в operator-guide.md.


Куда дальше

ХочуЧитать
Пройти основные операции в UI по шагамoperator-guide.md
Понять правила, match-поля, приоритеты, версииpolicy-management.md
Разобраться, кому применяется политика (лейблы, AND/OR)selector.md
Управлять большим парком, токены, группы, IaCfleet-management.md
Понять статусы хоста (active/pending/degraded/stale)host-statuses.md

Частые заблуждения

  • «Оставил Host selector пустым, поэтому политика не действует.» Наоборот: пустой selector выбирает весь парк. Консоль потребует подтверждение такого назначения.
  • «Селектор проверяет имя хоста.» Нет — он проверяет эффективные лейблы. Имя нужно только для точечного исключения на одну машину.
  • «deny не срабатывает.» Выше по приоритету стоит allow, который ловит трафик первым (first-match-wins). Разбирается по Priority.
  • «Забыл правило — машина отрежется.» Наоборот: default-ALLOW, непокрытый трафик проходит. Отрезает только явный deny.
  • «Обычный токен заведёт хост в группу.» Нет — токен задаёт только лейблы. Членство в группе — отдельный шаг (или bulk-токен с target_group_id).