Настройка механизма фильтрации трафика¶
Этот раздел описывает управление правилами фильтрации для узлов и сервисов, развёрнутых с помощью Kolla Ansible. Поддерживается фильтрация трафика на основании правил nftables, включая фильтрацию трафика в контейнерах, использующих интерфейсы типа bridge на базе Podman. При использовании сетей типа host правила фильтрации для контейнеров не применяются.
Параметры фаервола задаются в globals.yml или globals.d/firewall.yml репозитория региона.
При каждом запуске правила фаервола полностью пересоздаются.
Включение фаервола¶
По умолчанию управление фаерволом отключено (enable_firewall: "no"). Для включения:
Откройте веб-интерфейс GitLab.
Перейдите в репозиторий региона project_k / deployments / <имя региона>.
Перейдите в файл
globals.ymlили создайте файлglobals.d/firewall.yml. Добавьте в файл следующую конфигурацию:## Firewall options enable_firewall: "yes" ## Разрешение исходящего трафика firewall_allow_mgmt_outgoing: "yes" ## Добавление drop-правила в конце цепочек firewall_enable_trailing_drop: "yes"где:
enable_firewall: "yes"— включение управления фаерволом через nftables;
firewall_allow_mgmt_outgoing: "yes"— разрешение всего исходящего трафика черезapi_interface(сетевой интерфейс, через который OpenStack-сервисы принимают API-запросы и взаимодействуют внутри кластера; как правило, это интерфейс управляющей сети). Необходимо для подключений сервисов к базам данных, очередям сообщений и другим компонентам кластера. Значение по умолчанию —"yes". Переопределяйте только в том случае, если нужно ограничить исходящий трафик;
firewall_enable_trailing_drop: "yes"— добавление правилаdropв конец цепочек для блокировки всего трафика, не разрешённого явными правилами. Значение по умолчанию —"yes". Установите"no", если нужно сначала понаблюдать за трафиком, не блокируя его: неразрешённый трафик не будет отбрасываться (см. Режим наблюдения).
При включении фаервола автоматически применяются правила по умолчанию для трёх типов трафика:
management— доступ к management IP-адресу каждого узла;external— доступ к внешнему VIP-адресу (kolla_external_vip_address);internal— доступ к внутреннему VIP-адресу (kolla_internal_vip_address).
Также автоматически создаётся тип keystack, который разрешает межузловую коммуникацию внутри кластера. Подробнее — в разделе Тип правил по умолчанию.
Секция firewall_rules¶
Секция firewall_rules предназначена для задания правил доступа к VIP-адресам или другим точкам подключения. Она дополняет правила, связанные с контейнерами, и применяется отдельно.
Ниже приведены правила по умолчанию, которые применяются автоматически при включении фаервола:
firewall_rules:
management:
allow:
- "10.0.0.0/8"
- "172.16.0.0/12"
- "192.168.0.0/16"
deny:
- "224.0.0.0/4"
destination: "{{ hostvars[inventory_hostname].ansible_host | default(inventory_hostname) }}"
destination_ports:
- "22"
external:
allow:
- "0.0.0.0/0"
deny:
- "224.0.0.0/4"
destination: "{{ kolla_external_vip_address }}"
destination_ports:
- "80"
- "443"
- "1024:65535"
internal:
allow:
- "0.0.0.0/0"
deny:
- "224.0.0.0/4"
destination: "{{ kolla_internal_vip_address }}"
destination_ports:
- "80"
- "443"
- "1024:65535"
По умолчанию задано три блока:
management— разрешает доступ к management IP-адресу узла из приватных подсетей (RFC 1918: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) только на порт 22 (SSH). Ограничение по портам обязательно: на management IP-адресе слушают memcached, RabbitMQ, MariaDB и другие сервисы, поэтому безdestination_portsони оказались бы доступны с любого узла внутренних сетей. Узлы кластера получают полный доступ через типkeystack(см. ниже), операторам же нужен только SSH.external— разрешает доступ к внешнему VIP из любого источника на портах 80 и 443 (HTTP/HTTPS для доступа к OpenStack API через HAProxy) и в диапазоне 1024:65535 (эндпоинты OpenStack-сервисов, которые HAProxy маршрутизирует на внутренние порты). Если переопределить этот блок и не указать нужные порты, внешний API станет недоступен.internal— разрешает доступ на те же порты, что иexternal, но для внутреннего VIP, используемого для межсервисного взаимодействия компонентов OpenStack. В случае переопределения также важно сохранить доступ к нужным портам — иначе межсервисное взаимодействие с OpenStack нарушится.
Для каждого блока правил доступны следующие параметры:
allow— список разрешённых источников (CIDR);deny— список запрещённых источников (CIDR);destination— целевой IP-адрес (например, внешний или внутренний VIP);destination_ports— список портов или диапазонов (диапазон задаётся через двоеточие, например1024:65535);protocol— сетевой протокол (по умолчаниюtcp, если заданы порты);enforcing— режим работыdeny-правил:true(по умолчанию) — отбрасывать трафик;false— только логировать (см. Режим наблюдения).
Переопределение и объединение правил¶
Важно различать два механизма:
Переопределение переменной. Если задать
firewall_rulesвglobals.ymlрегиона, значение целиком заменяет набор по умолчанию из роли (приоритет переменных Ansible, без автоматического слияния). То же относится кfirewall_containers,firewall_inbound,firewall_traffic_typesиfirewall_ruleorder— они применяются как есть, без объединения.Объединение в роли. Только для
firewall_rulesроль выполняет одно явное рекурсивное слияние:базой служит набор
default_firewall_rulesиз роли — он содержит только блоки ``external`` и ``internal`` и гарантирует доступ к VIP-адресам;поверх него рекурсивно накладывается ваш
firewall_rules;последним добавляется блок
keystack.
При рекурсивном слиянии вложенные словари объединяются по ключам, а списки заменяются целиком (не дополняются). Например, задав firewall_rules.external.destination_ports, вы замените весь список портов, но сохраните allow/deny/destination из базового набора.
Предупреждение
Блока management в default_firewall_rules нет. Если вы переопределяете firewall_rules в globals.yml и не указываете в нём management, правило управляющего доступа (SSH) исчезнет, а трафик к management IP попадёт под завершающее drop-правило. Всегда явно перечисляйте все нужные блоки, включая management.
Секция firewall_containers¶
Правила задаются для каждого контейнерного сервиса через переменную firewall_containers. Раздел применяется только для контейнеров с сетями типа bridge — при использовании network_mode: host правила firewall_containers не действуют.
В примере ниже запрещается трафик от контейнеров cinder_scheduler и cinder_api на порт 22 (SSH). Это предотвращает инициирование SSH-соединений из этих контейнеров.
firewall_containers:
podman_override:
deny:
- "0.0.0.0/0"
destination_ports:
- "22"
containers:
- "cinder_scheduler"
- "cinder_api"
Здесь podman_override — произвольное имя группы правил. Одна группа может охватывать несколько контейнеров через параметр containers. Имена контейнеров должны соответствовать именам сервисов Kolla Ansible.
Поддерживаемые параметры:
allow— список разрешённых источников (CIDR);deny— список запрещённых источников (CIDR);destination_ports— список целевых портов;protocol— сетевой протокол (по умолчаниюtcp, если заданы порты);containers— применение правила на конкретные контейнеры.
Секция firewall_inbound¶
Сервисы с сетью типа bridge, опубликованные на management IP-адресе узла (memcached, mcrouter, MariaDB, Redis), при обращении к ним проходят через DNAT и не попадают в цепочку KEYSTACK. Без отдельной фильтрации они были бы доступны с любого узла, маршрутизируемого до контроллера. Секция firewall_inbound задаёт для таких сервисов фильтрацию до DNAT (в цепочке INBOUND_FILTER).
firewall_inbound:
memcached:
destination_ports:
- "{{ memcached_port }}"
mariadb:
destination_ports:
- "{{ database_port }}"
redis:
destination_ports:
- "{{ redis_port }}"
Для каждого сервиса достаточно указать destination_ports (и при необходимости destination — по умолчанию используется api_interface_address узла, и log_prefix). Список разрешённых источников формируется автоматически: адреса узлов кластера, записи firewall_keystack и подсеть firewall_container_subnet. Остальные источники отбрасываются с логированием FW-DROP inbound <сервис>.
Примечание
Правила firewall_inbound всегда работают в режиме блокировки — флаг enforcing для них не применяется. Чтобы открыть доступ к этим сервисам стороннему узлу (например, внешней системе мониторинга БД), добавьте его в firewall_keystack.
Порядок правил¶
Порядок правил настраивается через две переменные:
firewall_ruleorder— задаёт порядок применения правил внутри одного типа:firewall_ruleorder: - allow - deny
firewall_traffic_types— задаёт порядок применения типов правил относительно друг друга:firewall_traffic_types: - podman_override - management - external - internal
Тип правил по умолчанию — KeyStack¶
Роль автоматически добавляет тип правил keystack первым в firewall_traffic_types. Этот тип обеспечивает межузловую коммуникацию внутри кластера и работает следующим образом:
При каждом применении фаервола роль собирает IP-адреса всех узлов из inventory-группы
firewall— по интерфейсуapi_interface.Для текущего узла создаётся правило, разрешающее входящий трафик с этих адресов на его management IP-адрес.
Благодаря этому все узлы кластера могут взаимодействовать друг с другом, что обеспечивает корректную работу OpenStack-сервисов.
Тип keystack нельзя удалить из конфигурации. Однако его можно явно указать в firewall_traffic_types, чтобы изменить порядок применения относительно других правил:
firewall_traffic_types:
- management
- keystack
- external
- internal
Добавление внешних узлов в keystack¶
Чтобы предоставить узлу, не входящему в inventory-группу firewall (например, узлу развёртывания, CI или системе мониторинга), такой же доступ, как у узла кластера, добавьте его адрес в firewall_keystack:
firewall_keystack:
- interface: "{{ api_interface }}"
address: "10.220.68.3"
Адреса из firewall_keystack на интерфейсе api_interface попадают как в набор keystack_allow (полный доступ к management IP-адресу узла, все порты), так и в список разрешённых источников секции firewall_inbound. Это единственный способ открыть внешнему узлу доступ к сервисам с сетью типа bridge (MariaDB, Redis, memcached, mcrouter), которые фильтруются до DNAT.
Пустые адреса (например, незаданные переменные окружения) автоматически отбрасываются, поэтому такие записи безопасны.
Для доступа только по SSH добавлять узел в firewall_keystack не нужно — достаточно указать его подсеть в firewall_rules.management.allow.
Режим наблюдения¶
Перед включением блокировки можно запустить фаервол в режиме наблюдения: правила deny не отбрасывают трафик, а только логируют его. Это позволяет увидеть, что было бы заблокировано, не нарушая работу сервисов.
Режим включается двумя настройками:
firewall_enable_trailing_drop: "no"— отключает завершающееdrop-правило, поэтому трафик, не разрешённый явными правилами, не отбрасывается;enforcing: falseв нужных блокахfirewall_rules/firewall_containers— соответствующиеdeny-правила вместоdropлогируют трафик и пропускают его.
firewall_enable_trailing_drop: "no"
firewall_rules:
management:
allow: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
destination_ports: ["22"]
enforcing: false
external:
enforcing: false
internal:
enforcing: false
Заблокированный (или разрешённый в режиме наблюдения) трафик логируется в журнал ядра с префиксами:
FW-DROP— трафик отброшен (боевой режим,enforcing: true);FW-PERMIT— трафик пропущен, но был бы отброшен (режим наблюдения,enforcing: false).
Частота логирования ограничена переменной firewall_filter_log_rate (по умолчанию 10/minute), чтобы поток сообщений не переполнял журнал. Просмотреть записи можно командой grep -E 'FW-DROP|FW-PERMIT' /var/log/messages (или через journalctl -k).
Примечание
Флаг enforcing действует на блоки firewall_rules и firewall_containers. Правила секции firewall_inbound всегда блокируют трафик.
Сохранение настроек¶
Конфигурация сохраняется в файл, путь к которому зависит от базового дистрибутива:
Для дистрибутивов на базе RHEL (например, Rocky, SberLinux) используется путь
/etc/sysconfig/nftables.conf;Для других систем (например, Debian или Ubuntu) —
/etc/nftables.conf.
Также будет установлен и запущен системный сервис nftables-persist, который обеспечивает восстановление конфигурации после перезагрузки.