Всем привет! Меня зовут Артем, я занимаюсь информационной безопасностью и иногда автоматизирую задачи, в которых ручная проверка требует слишком много времени и внимания.
В одном из проектов такой задачей стал анализ политики NGFW: правил много, связанных объектов ещё больше, а определить, какие настройки действительно требуют внимания, нужно было без автоматического изменения конфигурации. Так появилась read-only утилита, которая получает данные через API, приводит их к единому виду, выполняет набор проверок и собирает результаты в удобный Excel-отчёт для администратора.
В статье расскажу, как устроен анализ, какие проверки оказались полезными на практике, с какими особенностями представления правил пришлось столкнуться и что показал запуск утилиты на реальной конфигурации.
Небольшое введение

У каждого межсетевого экрана есть временное правило. Его создают на пару дней — проверить интеграцию, пустить подрядчика, срочно восстановить сервис. Потом задача закрывается, автор переключается на следующий проект, а правило остаётся.
Через несколько лет оно выглядит почти как археологическая находка. Описание уже мало что объясняет, владелец неизвестен, срабатываний почти нет. Но удалить его всё равно страшно: вдруг именно на нём держится что-то важное.
С такой ситуацией мы столкнулись у заказчика, использовавшего UserGate NGFW. Политика работала и выполняла свою задачу, но со временем в ней накопились правила, которые требовали ревизии. Проверить их по одному можно. Понять состояние всей политики целиком — уже значительно сложнее.
Сразу оговорюсь: речь не о поиске уязвимостей в самом UserGate и не об оценке всей защищённости NGFW. Задача была проанализировать то, как в конкретной инсталляции настроена политика firewall, и найти правила, которым требуется дополнительное объяснение.
Так появилась идея утилиты, которая не меняет конфигурацию и не пытается принимать решения вместо администратора. Она собирает правила, статистику и связанные объекты, после чего задаёт каждому правилу несколько неудобных вопросов.
Например: когда ты в последний раз срабатывало? Почему разрешаешь управляющий порт для широкой сети? А логи где, Лебовски? Кто тебя согласовал?
1. Нельзя просто взять и проверить все правила

Web-интерфейс UserGate хорошо подходит для повседневного администрирования: создать правило, изменить объект, проверить конкретный доступ. Но аудит всей политики — немного другая задача.
Одно правило может ссылаться на зоны, отдельные IP-адреса, сетевые списки, сервисы, группы сервисов, пользователей и группы пользователей. При этом часть данных хранится не в самом правиле, а в отдельных справочниках. Статистика срабатываний тоже приходит отдельно, а в кластере — ещё и по нескольким узлам.
В результате администратор видит правило, но для ответа на простой вопрос «что именно оно разрешает?» ему приходится переходить между несколькими сущностями и держать контекст в голове.
Когда правил несколько десятков, это терпимо. Когда их сотни, ручная ревизия превращается в экспедицию:
-
найти все потенциально неиспользуемые правила;
-
проверить, какие из них включены;
-
сопоставить ссылки с реальными сетями и сервисами;
-
выяснить, где спрятались SSH, RDP и другие управляющие порты;
-
проверить описания и связанные заявки;
-
не перепутать
Anyс действительно пустым значением; -
записать результат так, чтобы работу можно было продолжить завтра или передать коллеге.
Проблема была не в отсутствии данных. Данные существовали — просто не рядом и не в формате, который удобен для массового анализа.
Общее число правил firewall в политике заказчика — 1000+, связанных объектов — 4500+. Даже первичная ручная оценка такого объёма займёт достаточно много времени. Масштаб был не запредельным, но уже достаточным, чтобы точечные проверки перестали давать представление о политике целиком.
2. Смотреть можно, трогать нельзя
Первое требование к утилите сформулировалось быстро: никаких автоматических исправлений.
Неиспользуемое правило не обязательно является ненужным. Оно может быть резервным, аварийным или предназначенным для редкого регламентного процесса. Широкая сеть может быть архитектурно обоснована. Отсутствие логирования иногда является осознанным компромиссом между наблюдаемостью и объёмом событий.
Поэтому инструмент должен был не удалять и не изменять правила, а собирать аргументы для ручного решения. Все обращения к UserGate — только читающие. Ошибка анализа в худшем случае создаст лишнюю красную строку в отчёте, но не лишнее изменение в боевой политике.
Остальные требования выросли из этого же принципа:
-
выгрузить правила firewall и статистику их срабатываний;
-
получить зоны, сети, URL-списки, сервисы, пользователей и группы;
-
заменить внутренние идентификаторы понятными именами;
-
сохранить исходное состояние в JSON-снапшот;
-
повторно запускать анализ и собирать отчёт из снапшота без повторного сбора информации с UserGate;
-
объяснять причину каждого срабатывания проверки;
-
оставить окончательный вердикт администратору.
Иными словами, мы автоматизировали сбор доказательств, но не вынесение приговора.
3. Одиннадцать неудобных вопросов
Проверки в утилите независимы друг от друга, но в данному случае, я объединю их по смыслу.
Ты ещё работаешь?
Первая группа касается жизненного цикла правил.
Анализатор ищет правила, у которых последнее срабатывание было слишком давно, а также включённые правила с количеством срабатываний ниже заданного порога. Отдельно отмечаются давно выключенные и давно не обновлявшиеся правила.
Пороговые значения настраиваются. Для одной организации тридцать дней без трафика — достаточный повод начать проверку. Для другой правило может штатно использоваться раз в квартал.
Сама проверка намеренно проста: здесь нет попытки угадать бизнес-контекст. Она лишь говорит, что правило включено, но используется редко или не используется вовсе. Теперь неплохо бы выяснить почему.
Ты не слишком гостеприимное?
Вторая группа ищет потенциально широкие доступы:
-
любые IP-адреса источника и назначения вместе с любыми сервисами;
-
сети с маской шире установленного порога;
-
правила, затрагивающие управляющие порты;
-
сервисы и группы сервисов, внутри которых скрываются нужные порты.
Особенно интересен пустой список сервисов. В пользовательском интерфейсе пустота легко воспринимается как «ничего не выбрано». В семантике правила это означает Any: правило затрагивает любой сервис, включая SSH, RDP, SNMP, LDAP и порты администрирования баз данных.
Упрощённо ключевая часть проверки выглядит так:
# пустой список сервисов в UserGate означает Any, а значит там есть управляющиеif not rule.services: findings.append( RuleFinding(rule, {"matched_ports": "Any (services пусты)"}) ) continue# получение всех портовall_ports = set()for ref in rule.services: all_ports |= resolve_service_ports(ref, catalog)# фильтрация только по управляющим портамmatched = sorted(all_ports & management_ports)
Само собой, наличие управляющего порта ещё не делает правило некорректным. Доступ может быть ограничен зонами, пользователями и адресами. Но это хороший повод проверить правило.
У нашего firewall просто широкая душа. Анализатор нужен, чтобы эта широта не противоречила архитектурной схемы.
Если что-то случится, мы это увидим?
Следующий момент — наблюдаемость.
Утилита отмечает блокирующие правила drop и reject, у которых выключено логирование. Иногда это сделано специально, например для очень шумного трафика. Но иногда отсутствие событий означает, что расследовать происходящее придётся по косвенным признакам.
Отдельная проверка находит правила, которые включены в политике, но в данный момент неактивны из-за временных ограничений. Состояние «включено, но не работает» заслуживает как минимум пояснения.
А кто тебя согласовал?
Последняя группа связана с другими моментами политики:
-
пустое описание;
-
описание без ссылки на заявку или изменение;
-
несколько правил с одинаковой сигнатурой.
Проверка описаний проводится регулярным выражением. Например, можно требовать, чтобы в описании правил присутствовал номер CR, TASK, REQ или другие ключевые слова, которые будут ссылаться на задачу. Это не делает правило безопаснее, зато сохраняет связь между техническим доступом и причиной его появления.
Правило с описанием test_final_v2 может быть совершенно корректным. Просто доказать это через три года будет немного сложнее.
4. Any — это не пустота

Прежде чем задавать правилам вопросы, пришлось научиться читать ответы UserGate.
API возвращает не готовую таблицу с человеческими именами, а набор связанных сущностей. Адреса, сервисы и пользователи внутри правила представлены типизированными значениями: тип ссылки вместе с идентификатором. Один list_id в поле адресов ведёт к сетевому списку, а такой же тип в поле сервисов — к группе сервисов.
Зоны приходят отдельными идентификаторами. Пользователь может быть локальным или находиться в LDAP. Сетевой список может содержать CIDR, диапазон или ссылку на другой список. Некоторые системные списки не отдают содержимое через API вовсе и просмотреть их через web-интерфейс невозможно.
Для адресных полей действует важная логика отрицаний:
-
пустой список без negate означает
Any; -
непустой список с negate означает
NOT (...); -
пустой список с negate фактически описывает пустое множество.
В нормализаторе это различие сводится к небольшой функции:
def render_field(items, negate, *, any_label="Any"): # пустой список без отрицания — Any # пустой список с отрицанием — пустое множество if not items: return "∅" if negate else any_label # для непустого списка сохраняем обычный или инвертированный перечень body = ", ".join(str(item) for item in items) return f"NOT ({body})" if negate else body
Кода здесь немного, но именно он сохраняет смысл исходной конфигурации. Если потерять эти различия при парсинге, анализатор начнёт находить очень красивые, убедительные и полностью выдуманные проблемы.
Поэтому сырые ответы сначала преобразуются в промежуточную модель. Все ссылки становятся объектами одного вида Reference(kind, ref_id), даты приводятся к единому формату, а статистика связывается с правилом по GUID.
Для кластера счётчики суммируются по узлам, самое раннее срабатывание выбирается first hit, самое позднее — last hit. Также сохраняется число узлов, которые отдали статистику. Это позволяет отличить реальное отсутствие данных от неполного ответа части кластера.
5. От XML-RPC до красной ячейки
Архитектура данного решения получилась линейной:
UserGate XML-RPC API ↓правила, статистика и справочники ↓нормализованная модель ↓snapshot.json ↓проверки ↓Excel-отчёт и ручные вердикты
Часть базовой заготовки XML-RPC-клиента я адаптировал из статьи “Как автоматизировать рутинные задачи с API UserGate”, где автор разобрал основные методы API UserGate. В своей версии я добавил загрузку связанных справочников, нормализацию ссылок, агрегацию статистики, сохранение снапшота, проверки правил и формирование Excel-отчёта.
Клиент API ничего не знает о проверках и возвращает сырые структуры. Нормализатор ничего не знает об Excel. Анализатор работает с моделью, а генератор отчёта получает уже готовые результаты.
Такое разделение оказалось полезным по нескольким причинам.
Во-первых, обращение к API можно выполнить один раз. После этого менять пороги срабатываний, добавлять проверки и пересобирать отчёт можно из сохранённого снапшота. На большой инсталляции это экономит время. Например, самое медленное место — получение содержимого многочисленных сетевых и URL-списков отдельными вызовами. Один из списков выгружался около 9 минут.
Во-вторых, новый анализ не требует менять клиент UserGate. Проверка возвращает стандартную структуру: идентификатор, заголовок, уровень важности, дополнительные колонки и список сработок. Генератор отчёта создаёт для неё отдельный лист автоматически.
В-третьих, снапшот фиксирует состояние политики на момент аудита. Если через месяц результаты изменятся, можно сравнивать не воспоминания администратора, а конкретные наборы данных. Само сравнение версий пока не автоматизировано, но основа для него уже есть.
Главная особенность реализации оказалась не в какой-то одной эвристике. Данные можно получить один раз, проверки — запускать независимо, а результаты — обсуждать в одном отчёте, не теряя связи с исходными объектами. Поэтому утилита не осталась одноразовым скриптом под конкретную выгрузку.
P.S. Полные исходники переданы заказчику и хранятся в его контуре. Для статьи согласована публикация отдельных обезличенных фрагментов.
6. Следствие ведёт Excel
На выходе хотелось получить не JSON и не ещё один сервис, который нужно разворачивать и поддерживать. Результаты должны были попасть в привычный инструмент, пригодный для совместного разбора.
Так появился навигируемый Excel-отчёт.
Первый лист — сводка: общее количество правил, число включённых и выключенных правил, распределение по действиям и число сработок каждой проверки.

Следом идёт матрица «правила × проверки». Строка соответствует правилу, столбец — одному анализу. Красный плюс означает, что правило попало в выборку, зелёный минус — что не попало. Матрица позволяет быстро найти правила, у которых одновременно несколько подозрительных признаков.

Основной лист содержит все правила и человекочитаемые имена связанных объектов. Из правила можно перейти к сети, сервису, пользователю или развёрнутому индексу связей. Каждая проверка также получает собственный лист с причиной попадания правила в выборку.

Наконец, у правила есть ручной вердикт:
-
не проверено;
-
ОК;
-
требует внимания;
-
нарушение;
-
ложное срабатывание;
-
исключение.
Это разные исходы: при ложном срабатывании критерий не описал конкретное правило корректно, а в случае исключения признак обнаружен верно, но сам доступ обоснован и должен остаться в политике.
Редактируется вердикт только на основном листе правил. На остальных листах он подтягивается формулой по GUID. Поэтому одно решение не приходится переносить вручную во все выборки, где встретилось правило.
Можно было разработать web-интерфейс, добавить базу данных, роли и очередь задач. Но заказчику требовалось разобрать правила, а не принять на сопровождение ещё одну информационную систему.
Максимальная угроза утилиты для боевого UserGate — покрасить ячейку красным.
7. Что показал первый допрос
Первый прогон всей политики занял около 24 минут. За это время утилита получила и связала доступные через API сведения о правилах и связанных объектах.
В итоговом отчёте:
-
хотя бы по одному критерию было отмечено примерно 39% всех правил;
-
среди отмеченных правил около 52% имели сразу несколько признаков.
Это не означало, что все отмеченные правила нарушают политику безопасности. Отчёт сформировал очередь для разбора: сначала правила с несколькими признаками и потенциально широкими доступами, затем редко используемые и плохо документированные. Вместо последовательного просмотра всей политики администратор получил ограниченную выборку для подробной проверки.
Сначала проверили проверяющего
Отчёт не стали сразу принимать за источник истины. После первого прогона из него выбрали правила с разными сочетаниями условий и вручную сопоставили их с web-интерфейсом UserGate: проверили исходные поля, ссылки на сетевые списки и группы сервисов, трактовку Any, состояния правил и статистику срабатываний. Это позволило убедиться, что нормализатор не потерял смысл конфигурации, а причины попадания в выборки можно проследить.
Только после такого сопоставления отчёт использовали как рабочую очередь для ревизии политики.
На разбор сформированной выборки ушло около 4-5 суток со стороны заказчика. Дальнейшие проценты рассчитаны относительно правил, прошедших ручную проверку. По её результатам:
-
изменения в конфигурации потребовались примерно для 19% проверенных правил;
-
около 6% отключили или удалили;
-
около 14% дополнили описаниями и ссылками на заявки;
-
примерно 3% признали обоснованными исключениями.
Категории могут пересекаться: одно правило могли одновременно сузить и дополнить ссылкой на заявку.
Часть сработок оказалась обоснованными исключениями, которых не было в исходных критериях проверки. Такие правила не стали исправлять только ради зелёной ячейки, а просто для них зафиксировали контекст и согласованный вердикт. При этом значительная часть выборки привела к реальным изменениям — правила отключали, сужали и дополняли недостающими обоснованиями.
Главным результатом стал не список «плохих» правил, а воспроизводимый процесс проверки политики. Вместо попытки обсудить всю политику сразу команда получила ограниченные выборки, понятные причины и место для фиксации решений.
8. Что анализатор оставляет человеку
Анализатор умеет собирать факты и расставлять приоритеты, но не знает бизнес-контекст систем.
Низкое количество срабатываний не доказывает ненужность правила. Время последнего изменения не показывает, когда именно правило выключили. Широкая подсеть может быть обоснована архитектурой. Блокирующее правило без логирования может быть настроено так намеренно.
Важно помнить, что анализатор охватывает политику firewall и связанные с ней объекты, а не всю безопасность NGFW.
Анализатор хорошо сортирует подозреваемых. Выносить приговор должен администратор, который знает архитектуру, назначение систем и требования организации.
Вместо заключения
Автоматизация не сообщила нам, какие правила нужно безусловно удалить. Она сделала более полезную вещь: собрала факты, связала их с конкретными объектами и превратила большую ручную ревизию в последовательную очередь решений.
Для каждого доступа теперь можно задать три базовых вопроса:
-
Кто и зачем его запросил?
-
Насколько широко он настроен?
-
Используется ли он до сих пор?
Если на эти вопросы есть ответы, даже сложная политика остаётся управляемой. Если ответов нет, самое время познакомить firewall с красной ячейкой в Excel.
А временное правило из начала статьи теперь уже не затеряется в политике: отчёт покажет его признаки, а администратор зафиксирует решение.
ссылка на оригинал статьи https://habr.com/ru/articles/1067374/