Настройка механизма фильтрации трафика¶
Механизм фильтрации трафика на базе nftables управляет доступом к узлам и сервисам, развёрнутым с помощью Kolla Ansible. Для контейнеров Podman с сетью типа bridge можно настроить отдельные правила. При использовании сетей типа host правила фильтрации для контейнеров не применяются.
Параметры фаервола задаются в globals.yml или globals.d/firewall.yml репозитория региона.
При каждом применении конфигурации фаервола правила полностью пересоздаются.
Включение фаервола¶
При использовании Podman управление фаерволом включено по умолчанию.
Чтобы изменить параметры фаервола выполните следующие действия:
Откройте веб-интерфейс GitLab.
Перейдите в репозиторий региона project_k / deployments / <имя региона>.
Откройте файл
globals.ymlили создайте файлglobals.d/firewall.yml.Укажите необходимые параметры. Ниже приведены значения по умолчанию:
firewall_allow_mgmt_outgoing: "yes" firewall_enable_trailing_drop: "no"
firewall_allow_mgmt_outgoing— разрешает исходящий трафик черезapi_interface— интерфейс, через который сервисы OpenStack принимают API-запросы и взаимодействуют внутри кластера. Как правило, это интерфейс управляющей сети. Доступ необходим для подключения к базам данных, очередям сообщений и другим компонентам кластера.firewall_enable_trailing_drop— добавляет правилоdropв конец цепочек: трафик, не разрешённый явными правилами, отбрасывается. Значение"no"отключает завершающее правило (см. Режим наблюдения).
Предупреждение
Правила
firewall_rulesможно сужать, но только в режимеenforcing: falseс выключеннымfirewall_enable_trailing_drop.Сохраните изменения и примените их по инструкции в разделе Применение и проверка конфигурации.
При включении фаервола автоматически применяются правила по умолчанию для трёх типов трафика:
management— доступ к management IP-адресу каждого узла;external— доступ к внешнему VIP-адресу (kolla_external_vip_address);internal— доступ к внутреннему VIP-адресу (kolla_internal_vip_address).
Также автоматически создаётся тип keystack, который разрешает межузловую коммуникацию внутри кластера. Подробнее — в разделе Тип правил по умолчанию.
Секция firewall_rules¶
Секция firewall_rules предназначена для задания правил доступа к VIP-адресам или другим точкам подключения. Она дополняет правила, связанные с контейнерами, и применяется отдельно.
Правила по умолчанию заданы в двух местах:
ansible/group_vars/all.ymlв Kolla Ansible — переменнаяfirewall_rulesс блокамиmanagement,externalиinternal;ansible/roles/firewall/defaults/main.yml— переменнаяdefault_firewall_rulesс блокамиexternal,internalиvrrp. Блокvrrpразрешает трафик протоколаfirewall_vrrp_protocolк адресу224.0.0.18.
Ниже приведён набор firewall_rules из ansible/group_vars/all.yml. Копировать его в конфигурацию региона без изменений не требуется:
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иvrrp;поверх него рекурсивно накладывается ваш
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: - keystack - podman_override - management - external - internal
При переопределении этой переменной также укажите
firewall_enable_trailing_drop: "no"(см. ограничение в разделе Тип правил по умолчанию — KeyStack).
Тип правил по умолчанию — KeyStack¶
Роль автоматически добавляет тип правил keystack первым в firewall_traffic_types. Этот тип обеспечивает межузловую коммуникацию внутри кластера и работает следующим образом:
При каждом применении фаервола роль собирает IP-адреса всех узлов из inventory-группы
firewall— по интерфейсуapi_interface.Для текущего узла создаётся правило, разрешающее входящий трафик с этих адресов на его management IP-адрес.
Благодаря этому все узлы кластера могут взаимодействовать друг с другом, что обеспечивает корректную работу OpenStack-сервисов.
Тип keystack нельзя удалить из конфигурации. Однако его можно явно указать в firewall_traffic_types, чтобы изменить порядок применения относительно других правил:
firewall_enable_trailing_drop: "no"
firewall_traffic_types:
- management
- keystack
- external
- internal
Предупреждение
При переопределении firewall_traffic_types укажите firewall_enable_trailing_drop: "no". При включённом завершающем правиле drop правила по умолчанию в цепочке keystack могут не примениться, что нарушит взаимодействие узлов региона. Это ограничение относится к переопределению порядка правил, а не к режиму наблюдения: явные правила deny продолжают блокировать трафик.
Добавление внешних узлов в 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, который обеспечивает восстановление конфигурации после перезагрузки.
Примеры настройки правил¶
Ограничение доступа из контейнера toolbox к Cinder API¶
В примере запрещается исходящий трафик из контейнера kolla_toolbox на порт 8776/tcp, используемый Cinder API. Правило применяется только при использовании контейнером сети типа bridge.
Откройте веб-интерфейс развёрнутого GitLab.
Перейдите в репозиторий project_k / deployments / <имя региона>.
Откройте или создайте файл
globals.d/firewall.yml.Добавьте группу правил
toolboxв секциюfirewall_containers:firewall_containers: toolbox: deny: - "0.0.0.0/0" destination_ports: - "8776" containers: - "kolla_toolbox"
toolbox— произвольное имя группы правил. Значение0.0.0.0/0задаёт все IPv4-адреса, аcontainers— контейнер, к исходящему трафику которого применяется ограничение.Сохраните изменения и примените их по инструкции Применение и проверка конфигурации.
Ограничение доступа по SSH с гипервизора¶
В примере запрещаются входящие SSH-соединения с выбранного гипервизора на порт 22/tcp узлов региона. Запрещающее правило должно применяться раньше разрешающего правила keystack.
Откройте веб-интерфейс развёрнутого GitLab.
Перейдите в репозиторий project_k / deployments / <имя региона>.
Откройте или создайте файл
globals.d/firewall.yml.Добавьте конфигурацию:
firewall_enable_trailing_drop: "no" firewall_rules: hypervisor_ssh: deny: - "<hypervisor_ip>/32" destination_ports: - "22" firewall_traffic_types: - hypervisor_ssh - keystack
Вместо
<hypervisor_ip>укажите IP-адрес гипервизора без угловых скобок. Суффикс/32ограничивает правило одним IPv4-адресом.hypervisor_ssh— имя группы правил, которое должно совпадать вfirewall_rulesиfirewall_traffic_types.Если в
firewall_rulesуже заданы другие группы, сохраните их и добавьтеhypervisor_ssh. При необходимости укажите остальные используемые типы вfirewall_traffic_types, сохранивhypervisor_sshпередkeystack.При переопределении порядка правил обязательно укажите
firewall_enable_trailing_drop: "no". Явное правилоdenyпри этом блокирует SSH-соединения.Сохраните изменения и примените их по инструкции Применение и проверка конфигурации.
Применение и проверка конфигурации¶
Откройте веб-интерфейс GitLab и перейдите в репозиторий региона project_k / deployments / <имя региона>.
Создайте новый пайплайн: .
Оставьте ветку по умолчанию, соответствующую установленному релизу.
В переменной
KOLLA_ANSIBLE_DEPLOY_ACTIONукажите значениеreconfigure.В переменной
KOLLA_ARGSукажите значение--tags firewall.Запустите пайплайн, нажав кнопку New pipeline.
Дождитесь завершения задач на этапе setup.
Запустите задачу deploy на этапе deploy и дождитесь её успешного завершения.
Подключитесь к узлу, на котором применялись правила, по SSH и проверьте текущую конфигурацию nftables:
$ sudo nft list ruleset
Проверьте, что заданные правила присутствуют, разрешённые соединения устанавливаются, а запрещённые блокируются.
Просмотрите записи о фильтрации в журнале ядра:
$ sudo journalctl -k --grep='FW-DROP|FW-PERMIT'
Изменения, внесённые вручную командой nft, будут заменены при следующем применении конфигурации фаервола. Для сохранения правил задавайте их в репозитории региона.