Как устроено управление файрволом в 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 назначает политику текущим и будущим хостам с этим лейблом.
Идентификатор хоста нужен только для точечного назначения.
Эффективные лейблы
Хост получает лейблы из двух источников:
- Enrollment-токен — при подключении хоста к флоту токен «штампует» на него
заданные лейблы (например
role=web,env=prod). Это основной путь. - 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
На одном хосте может действовать много правил (из одной или разных политик). Для каждого пакета правила проверяются по порядку:
- Политики: меньше Priority = раньше (главнее).
- Внутри политики: правила по своему Priority; при одинаковом Priority сохраняется их порядок в редакторе. Rule ID и этот порядок не меняются от повторного PUT.
- Первое подходящее правило сработало → остальные для этого пакета не смотрятся.
- Не подошло ни одно правило → пакет пропускается (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 — переиспользуемые наборы
Чтобы не вписывать одни и те же списки адресов/портов в каждое правило, их выносят в именованный набор, на который правило ссылается:
| Тип | Содержит | Пример |
|---|---|---|
ipset | CIDR/IP | 10.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.
- Лейблы на хостах. Убедиться, что у нужных машин есть лейблы
role=webиenv=prod. Штатно они приезжают из enrollment-токена при подключении хоста; либо их даёт Host Group (см. шаг 2). - (если нужно) Host Group.
Host Groups → New group→ имяprod-web, лейблыrole=web,env=prod→ добавить машины. Члены группы наследуют эти лейблы. - Политика.
Policies → New policy→ имя, напримерclose-8080. - Host selector. Задать условие по лейблам:
role=webиenv=prod. Политика будет действовать на все подходящие хосты — и на будущие тоже. - Правило.
Add rule: Directioningress, Actiondeny, Protocoltcp, Dst ports8080. - Сохранение. При создании политика применяется сразу. Поэтому сначала безопаснее
сохранить правило с действием
logи проверить события в Verdicts. - Переход к блокировке. Изменить действие на
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 |
| Управлять большим парком, токены, группы, IaC | fleet-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).