惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
Engineering at Meta
Engineering at Meta
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
B
Blog RSS Feed
GbyAI
GbyAI
P
Proofpoint News Feed
aimingoo的专栏
aimingoo的专栏
MyScale Blog
MyScale Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recorded Future
Recorded Future
美团技术团队
The Register - Security
The Register - Security
V
Visual Studio Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Tailwind CSS Blog
爱范儿
爱范儿
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
T
The Blog of Author Tim Ferriss
博客园 - 司徒正美
量子位
B
Blog
F
Fortinet All Blogs
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
雷峰网
雷峰网
大猫的无限游戏
大猫的无限游戏
J
Java Code Geeks
L
LangChain Blog
Latest news
Latest news
S
SegmentFault 最新的问题
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
F
Full Disclosure
C
Cisco Blogs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
W
WeLiveSecurity
T
Tenable Blog
T
Tor Project blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Suricata IPS NFQueue with nDPI. Часть V
Gandalf_the_ · 2026-05-18 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение22 мин

Охват и читатели305

Туториал

Часть I содержит: общие сведения о suricata; требования к железу; описание режимов работы; описание, характеристики и возможности nDPI; описание движков.

Часть II содержит: установка suricata из исходных кодов.

Часть III содержит: подготовка к запуску и запуск suricata.

Часть IV содержит: примеры просмотра данных eve.json в консоли; просмотр лога, алертов и дропов через web-интерфес; простой пример использования suricata - блокировка торрентов; контроль работоспособности и используемых ресурсов.

В части V будет рассмотрено:

12. Подготовка к использованию.

12.1 Исключение легитимного трафика из проверок.

12.2 Исключение доверенных сайтов из проверок.

12.3 Исключение правил проверок IP-адресов.

12.4 Создание задания на обновление правил.

12. Подготовка к использованию.

Необходимо правилами nftables исключить из проверки трафик от клиентов локальной сети на роутер и обратно для ssh, http и других локальных сервисов, как описано в части III в пункте «7.10 Перенаправление трафика в suricata».

12.1 Исключение легитимного трафика из проверок.

Правила загружаются в том порядке, в котором они указаны в файлах. Но обрабатываются они в порядке указанном в параметре ‘action-order’, который определяет приоритет действий при обработке трафика. Если пакет попадает под условия сразу нескольких правил (например, одно говорит «пропустить», а другое — «заблокировать»), движок выберет то действие, которое стоит выше в этом списке. Проверьте не изменен ли в вашем конфиг-файле порядок обработки правил. Если параметра 'action-order' в suricata.yaml нет, то порядок обработки будет установлен по умолчанию: 'pass', 'drop', 'reject', 'alert', как нам и надо. Данная очередность обработки означает следующее:

  • Первым делом пришедшие данные проверяются правилами с действием ‘pass’. Это своего рода «белый список». ‘pass’ применяется ко всему потоку (flow). Если правило сработало на первом пакете, остальные пакеты этого соединения пройдут без проверки. Данные проверяются до первого совпадения. Если данные попали под условие в правиле ‘pass’, то они пропускаются и остальные проверки над данными не выполняются. По умолчанию правила ‘pass’ не генерируют записи в fast.log или eve.json в секции alerts, так как они считаются «безопасными» (оповещение не выводится).

  • Если совпадений с правилами ‘pass’ не было, то данные проверяются правилами с действием ‘drop’. Данные проверяются до первого совпадения. Если данные попали под условие в правиле ‘drop’, то они уничтожаются и больше проверки над данными не выполняются. Оповещение выводится.

  • Для правил с действиями ‘reject’ выполняется все тоже самое что и для правил с действиями ‘drop’ плюс отправителю данных отправляется ответный пакет (ICMP Port Unreachable или TCP RST), сообщающий, что соединение закрыто.

  • Если данные не попали под все предыдущие действия, то для них выполняются проверки правилами с действиями ‘alert’. Данные проверяются на совпадение с каждым правилом ‘alert’. Оповещения выводятся на каждое совпадение. Однако максимальное количество оповещений, которые могут быть сгенерированы для проверяемого пакета данных, ограничивается параметром 'packet-alert-max' в suricata.yaml .

Порядок (pass -> drop -> reject -> alert) является стандартным и самым безопасным для режима IPS (предотвращение вторжений). Он позволяет сначала исключить доверенный трафик, затем убить вредоносный и только потом логировать всё остальное. Для исключения трафика из проверок мы будем использовать действие ‘pass’.

Убедитесь, что в вашем конфиг-файле suricata.yaml файл /etc/suricata/rules/local.rules указан первым:

rule-files:
  - /etc/suricata/rules/local.rules
  - /var/lib/suricata/rules/suricata.rules

Нет смысла проверять всеми правилами suricata трафик, вызывающий доверие. Такой трафик целесообразно исключить из проверок.

Посмотрите какие протоколы у вас используются чаще всего:

jq -r 'select(.ndpi.proto != null) | .ndpi.proto' /var/log/suricata/eve.json | 
  sort | uniq -c | sort -nr | head -n 20

Создайте правила для обхода проверок легитимных протоколов в файле /etc/suricata/rules/local.rules. Следите, чтобы номера правил (sid) были уникальными. Список nDPI протоколов приведен в части I в пункте «4. Описание, характеристики и возможности nDPI». Например:

pass ip any any -> any any (msg:"Windows Update Protocol"; ndpi-protocol:WindowsUpdate; sid:1000003; rev:1;)
pass ip any any -> any any (msg:"Microsoft Protocol"; ndpi-protocol:Microsoft; sid:1000004; rev:1;)
pass ip any any -> any any (msg:"Google Protocol"; ndpi-protocol:Google; sid:1000005; rev:1;)
pass ip any any -> any any (msg:"GoogleServices Protocol"; ndpi-protocol:GoogleServices; sid:1000006; rev:1;)
pass ip any any -> any any (msg:"Yandex Protocol"; ndpi-protocol:Yandex; sid:1000007; rev:1;)

Протестируйте приведенные изменения и перезагрузите новые правила:

sudo suricata -T --user suricata --group suricata
suricatasc -c ruleset-reload-nonblocking

Если сомневаетесь и хотите убедиться, что написанные правила действительно определят необходимые вам протоколы, то измените действие 'pass' на 'alert', поскольку действие 'pass'не выводит оповещений. И посмотрите полученные оповещения в evebox или в консоли:

tail -f /var/log/suricata/fast.log

12.2 Исключение доверенных сайтов из проверок.

Нет смысла проверять всеми правила suricata трафик, с сайтов вызывающих доверие. Не может быть никаких угроз на сайтах microsoft, nvidia, suricata, debian и т.д, поэтому проверка трафика с данных сайтов будет пустой тратой ресурсов.

Реализовать исключение сайтов из проверок можно направив трафик на данные сайты через прокси, и исключить из проверок трафик отправляемый на прокси и обратно. Примеры настройки прокси и iptables/nftables для решения такой задачи можно легко найти в сети. Поэтому данные настройки я описывать не буду.

Для пропуска проверок доверенных сайтов я приведу пример использования возможностей самой suricata - механизм 'datasets', реализованный разработчиками для работы с огромными списками данных (десятками и сотнями тысяч элементов), без существенного замедления системы. Использование данного механизма позволяет выполнить исключение из проверок содержимого набора данных одним правилом.

Существует 2 вида наборов данных:

  • Статические. Определяются с помощью параметра 'load'. При старте программы или перезагрузке правил загружаются из файла. Предполагается, что они не будут изменяться во время выполнения. Для изменения набора необходимо изменить данные содержащиеся в файле. Для применения изменений необходимо перезагрузить правила. Прав на чтение файла с набором данных достаточно для работы suricata.

  • Динамические. Определяются с помощью параметров 'state' или 'save'. При старте программы загружаются из файла. При перезагрузке правил динамические наборы данных не изменяются. Операции изменения набора данных выполняются через сокет управления и применяются немедленно. Измененный набор записывается в файл при нормальном завершении работы suricata или по команде 'dataset-dump'. Suricata должна иметь права на чтение и запись в файл набора данных.

Будем использовать динамический набор, т.к. это будет гораздо удобнее - изменения будут применяться немедленно и не нужно будет перезагружать правила.

Добавьте в конфиг-файл /etc/suricata.yaml определение и настройки нашего набора данных в существующий параметр 'datasets:':

datasets:
  domains-wl:
    type: string
    state: domains_wl.b64

domains-wl: - определяет имя набора данных.

type: string - определяет тип набора данных. Для типа 'string' каждый элемент данных должен быть представлен в виде хэша base64 а не строки! (Оцените юмор разработчиков.)

state: domains_wl.b64 - определяет файл с набором данных. Будет создан при запуске, обычно в /var/lib/suricata/data.

Создайте 2 файла:

sudo -u suricata -g suricata touch /var/lib/suricata/data/domains.txt
sudo -u suricata -g suricata touch /var/lib/suricata/data/domains_black.txt

domains.txt - будет содержать те же самые домены, которые добавлены в domains_wl.b64 только в строковом виде (облегчит управление).

domains_black.txt - будет содержать домены, в благонадежности которых вы сомневаетесь (черный список) или не можете их проверить сейчас (анализ отложен на потом).

Хоть suricata и не дает добавлять в набор дублирующие записи, но эти файлы значительно облегчат управление набором данных и избавят от лишней работы.

Добавьте в самое начало файла /etc/suricata/rules/local.rules правила для пропуска трафика:

pass tls any any -> any any (msg:"TLS Whitelist Domain Detected"; tls.sni; domain; dataset:isset, domains-wl; sid:1000008; rev:1;)
pass quic any any -> any any (msg:"QUIC Whitelist Domain Detected"; quic.sni; domain; dataset:isset, domains-wl; sid:1000009; rev:1;)
pass http any any -> any any (msg:"HTTP Whitelist Domain Detected"; http.host; domain; dataset:isset, domains-wl, type string; sid:1000010; rev:1;)

tls, quic, http - будем анализировать данные этих протоколов на совпадение с именами доменов.

tls.sni, quic.sni, http.host - буферы соответствующих протоколов. Предоставляют данные доменного имени.

dataset:isset, domains-wl - проверять данные предоставленные буфером протокола на присутствие в наборе domains-wl.

domain - специальный механизм преобразования (Transformations), который изменяет доменное имя, предоставленное буфером протокола, так, чтобы осталось только имя основного домена, например: "mail.ru". (Т.е. удаляет поддомены). Благодаря этому преобразованию правило «поймает» трафик не только от mail.ru, но и от всех его поддоменов. Без использования механизма domain пришлось бы прописывать в наборе данных все имена поддоменов, поскольку suricata требует строгого соответствия при сравнении.

Протестируйте приведенные изменения и перезагрузите suricata:

sudo suricata -T --user suricata --group suricata
sudo systemctl restart suricata

Посмотрите топ 10 адресов доменов к которым чаще всего обращались пользователи:

jq -r 'select(.event_type=="tls" or .event_type=="quic" or .event_type=="http") | 
  (.tls.sni // .quic.sni // .ndpi.domainame)' /var/log/suricata/eve.json{,.1} | 
  grep -vE '^[0-9.]+$|^[0-9a-f:]+$' | grep -v null | rev | 
  cut -d'.' -f1-2 | rev | sort | uniq -c | sort -nr | head -n 10

Для записи имен доменов в набор данных используйте правильную команду:

неправильно:  echo mail.ru  | base64 # bWFpbC5ydQo= - включает символ перевода строки 
                                                      и никогда не даст совпадения.
правильно: echo -n mail.ru  | base64 # bWFpbC5ydQ==

Добавьте в набор данных domains-wl записи для доменов, которым вы доверяете, например, mail.ru:

d="mail.ru"; suricatasc -c "dataset-add domains-wl string `echo -n $d | base64`"; \
  echo $d >> /var/lib/suricata/data/domains.txt

Посмотреть наличие записи для домена в наборе данных:

suricatasc -c "dataset-lookup domains-wl string `echo -n mail.ru | base64`"

Удалить элемент из набора данных:

d="mail.ru"; suricatasc -c "dataset-remove domains-wl string `echo -n $d | base64`"; \
  sed -i "/^$d$/d" /var/lib/suricata/data/domains.txt

Сохранить данные набора в файл. Выполняйте всегда после окончания изменений набора данных.

suricatasc -c "dataset-dump domains-wl"

Проверить, что в dataset столько же строк что и в файле с именами доменов.

wc -l /var/lib/suricata/data/domains.txt /var/lib/suricata/data/domains_wl.b64

Декодировать записи набора данных из /var/lib/suricata/data/domains_wl.b64:

while read line; do echo "$line" | base64 -d; echo; done < /var/lib/suricata/data/domains_wl.b64 | sort

Не записывайте хэши имен доменов в файл /var/lib/suricata/data/domains_wl.b64, т.к. suricata перезапишет его при завершении работы. Если вы хотите воспользоваться чьим-то готовым файлом, то вы должны: остановить suricata; скопировать файл; установить владельца suricata; дать права на чтение и запись; запустить suricata.

Для облегчения добавления данных в набор предлагаю воспользоваться скриптами:

suricata_domains_get - Запускается первым. Получает данные о именах доменов всех посещенных пользователями сайтов, сортирует их по количеству посещений и записывает в /tmp/domains_tmp.txt. Затем из файла domains_tmp.txt выбирает только те записи, которых нет в файлах /var/lib/suricata/data/domains.txt и /var/lib/suricata/data/domains_black.txt и записывает их в /tmp/domains.txt. Ваша задача оставить в файле /tmp/domains.txt только те записи, которые будут добавлены в набор. (Цифры удалять не нужно. В файле должно остаться 2 колонки.) Если вы сомневаетесь в добропорядочности каких-то доменов или не можете их проверить сейчас, то перенесите их имена в файл domains_black.txt и удалите их из файла /tmp/domains.txt. Или просто удалите, тогда они опять будут помещены в /tmp/domains.txt в следующий раз.

suricata_domains_put - Запускается вторым. Скрипт записывает имена доменов из файла /tmp/domains.txt в /var/lib/suricata/data/domains.txt (текст) и в используемый dataset (base64). Может записывать в статический dataset /etc/suricata/rules/domains_wl.b64 или в динамический через сокет. Выберите в какой dataset будете сохранять имена доменов. Вывод в другой dataset отключите.

suricata_domains_get
#!/usr/bin/bash
# 20260429
# В файле /var/lib/suricata/data/domains.txt хранятся в текстовом формате
# имена доменов добавленных в dataset domains-wl по 1 имени на строку.
# В файле /var/lib/suricata/data/domains_black.txt хранятся в текстовом формате
# имена сомнительных доменов или тех с которыми некогда разбираться.
# Скрипт записывает в /tmp/domains.txt домены, которых нет в файлах
# /var/lib/suricata/data/domains.txt и /var/lib/suricata/data/domains_black.txt
#
# После отработки скрипта отредактируйте /tmp/domains.txt -
# оставьте в файле только те домены, которым доверяете.
# Поместите в /var/lib/suricata/data/domains_black.txt сомнительные
# домены или те с которыми нет времени разбираться и удалите
# их из /tmp/domains.txt.
#
# В /tmp/domains.txt должны остаться только те домены, которые будут
# добавлены в dataset domains-wl.
#

/usr/bin/jq -r 'select(.event_type=="tls" or .event_type=="quic") |
(.tls.sni // .quic.sni // .ndpi.domainame)' /var/log/suricata/eve.json{,.1} |
/usr/bin/grep -vE '^[0-9.]+$|^[0-9a-f:]+$' | /usr/bin/grep -v null |
/usr/bin/rev | /usr/bin/cut -d'.' -f1-2 | /usr/bin/rev | /usr/bin/sort |
/usr/bin/uniq -c | /usr/bin/sort -nr > /tmp/domains_tmp.txt

> /tmp/domains.txt

if [ ! -s "/var/lib/suricata/data/domains.txt" ]; then
/usr/bin/touch /var/lib/suricata/data/domains.txt
#/usr/bin/chown suricata:suricata /var/lib/suricata/data/domains.txt
fi

if [ ! -s "/var/lib/suricata/data/domains_black.txt" ]; then
/usr/bin/touch /var/lib/suricata/data/domains_black.txt
#/usr/bin/chown suricata:suricata /var/lib/suricata/data/domains_black.txt
fi

# Читаем /tmp/domains_tmp.txt, берем вторую колонку и проверяем
while read -r line; do
    # Извлекаем домен (второе слово в строке)
    domain=$(/usr/bin/echo "$line" | /usr/bin/awk '{print $2}')

    # Если домена НЕТ в /var/lib/suricata/data/domains.txt и в /var/lib/suricata/data/domains_black.txt
    if ! /usr/bin/grep -qxF "$domain" /var/lib/suricata/data/domains.txt &&
       ! /usr/bin/grep -qxF "$domain" /var/lib/suricata/data/domains_black.txt; then
        /usr/bin/echo "$line" >> /tmp/domains.txt
    fi
done < /tmp/domains_tmp.txt

/usr/bin/cat /tmp/domains.txt
suricata_domains_put
#!/usr/bin/bash
# 20260429
# Выберите в какой dataset будете сохранять домены.
# Вывод в другой dataset отключите.
#
# Скрипт записывает все домены из файла /tmp/domains.txt
# в /var/lib/suricata/data/domains.txt (текст) и
# в используемый dataset (base64).
#

/usr/bin/awk '{print $2}' /tmp/domains.txt | while read domain; do
        # Сохраняем в текстовый файл.
        /usr/bin/echo "$domain" >> /var/lib/suricata/data/domains.txt

        # Сохраняем в файл статического dataset.
        # /usr/bin/echo -n "$domain" | /usr/bin/base64 >> /etc/suricata/rules/domains_wl.b64

        # Отправляем через сокет в динамический dataset.
        /usr/bin/suricatasc -c "dataset-add domains-wl string `echo -n $domain | base64`" > /dev/null

        /usr/bin/echo "Добавлено: $domain"
done

/usr/bin/sleep 1

# Отключите если используете /etc/suricata/rules/domains_wl.b64
# Делаем сброс данных из dataset в файл, чтобы при некорректном завершении
# работы suricata данные не потерялись.
/usr/bin/suricatasc -c "dataset-dump domains-wl"

# Сортируем файл с именами доменов для удобства.
/usr/bin/sort -u /var/lib/suricata/data/domains.txt -o /var/lib/suricata/data/domains.txt

# Проверяем, что файлы соответствуют по количеству записей.
/usr/bin/wc -l /var/lib/suricata/data/domains.txt /var/lib/suricata/data/domains_wl.b64

> /tmp/domains.txt

12.3 Исключение правил проверок IP-адресов.

Suricata использует правила от различных составителей. Составители объединяют правила в логические группы, указывая это в поле 'msg' правила. Например, "ET CINS" - правила от источника ET/OPEN, группа CINS. Некоторые группы правил содержат проверки доступа к неблагонадежным IP-адресам и диапазонам IP-сетей:

Источник - et/open:

"ET CINS" - содержит 299 правил, включающих 14902 IP-адресов. Список известных вредоносных IP-адресов, сформированный на основе данных сообщества и систем обнаружения вторжений.

"ET CNС" - 5 правил, 5 IP-адресов. Список IP-адресов с признаками работы вирусов, троянов и бэкдоров.

"ET COMPROMISED" - 13 правил, 390 IP-адресов. Список ресурсов, которые были взломаны злоумышленниками. Содержит легитимные серверы и сайты, на которых размещено вредоносное ПО или которые используются как C2-серверы (командные центры). Список очень динамичный. Как только владелец очищает свой сервер, IP удаляется из списка.

"ET DROP" - 65 правил, 1295 диапазонов сетей. Список диапазонов вредоносных сетей от старейшего источника spamhaus.org, составленный на основе репутации и данных отчетов безопасности. Вот как описывают данный список владельцы ресурса: «Список DROP содержит диапазоны IP‑адресов, настолько опасные для пользователей интернета, что spamhaus предоставляет его любому желающему бесплатно». И рекомендуют «отбрасывать весь трафик, содержащий указанные диапазоны IP‑адресов». Обновляет свои данные не чаще, чем 1 раз в час. Блокирует назойливых клиентов, которые скачивают список чаще необходимого.

"ET Threatview.io" - 22 правила, 1052 IP-адресов. Список IP-адресов, связанных с конкретными хакерскими группировками.

Источник - etnetera/aggressive:

"ETN AGGRESSIVE" - 14 правил, 416 IP-адресов. Список IP-адресов от проекта Emerging Threats (ET Open). Выделен в отдельный источник для suricata-update. Содержит адреса, которые были замечены в агрессивном поведении: сканировании портов, попытках подбора паролей или активном распространении вредоносного ПО в последние часы или дни. Это очень динамичный список. IP-адрес попадает туда быстро и так же быстро удаляется, если агрессия прекратилась.

Итого: 418 правил с проверками 18060 адресов и сетей. Значения могут меняться, так как данные изменяются, и приведены для понимания количества адресов и сетей используемых для блокировки.

Такое большое количество адресов в правилах создаст большую нагрузку на ресурсы сервера при проверке трафика. Самым дешевым способом блокировки, по используемым ресурсам, будет использование nftables. Поскольку списки вредоносных адресов и сетей создаются и контролируются заслуживающими доверия организациями, то я предпочитаю их заблокировать, а потом уже, при необходимости, разбираться. Если вы придерживаетесь другого мнения, то можете оставить все как есть и пропустить данный пункт.

Чтобы использовать nftables для блокировки вредоносных адресов и сетей необходимо создать таблицу, цепочки, набор для данных и правила блокировки. Cамый эффективный способ блокировки черных списков - размещение блокировки в цепочке ingress таблицы netdev. Тогда блокировка срабатывает сразу после того, как пакет поступил с сетевой карты и ещё до того, как ядро начнет тратить ресурсы на обработку IP-стека. Это обеспечивает максимальную производительность - пакет сбрасывается на самом раннем этапе и экономию ресурсов - ядро не тратит время на поиск маршрута, проверку таблиц conntrack или работу с IP-заголовками.

Вы можете не выполнять приведенные команды, а взять вывод команды 'sudo nft -s list table netdev filter', выполненный после создания всего необходимого и поместить в /etc/nftables.conf. Затем обязательно протестируйте полученную конфигурацию: 'sudo nft -cf /etc/nftables.conf'.

Создадим таблицу:

sudo nft create table netdev filter

Создадим цепочки:

sudo nft add chain netdev filter ingress_wan { type filter hook ingress device "wan" priority -500 \; policy accept \; }
sudo nft add chain netdev filter ingress_lan { type filter hook ingress device "lan" priority -500 \; policy accept \; }

Создадим набор 'blacklist' для IP-адресов v4 (type ipv4_addr), в который могут записываться диапазоны IP-адресов (flags interval) и с возможностью автоматического объединения ядром смежных/перекрывающихся элементов множества (auto-merge). Без 'auto-merge' появление дублирующего IP-адреса или IP-адреса принадлежащего интервалу IP-адресов или наличие смежных/перекрывающихся диапазонов IP-адресов вызовет ошибку при тестировании набора и его загрузке.

sudo nft add set netdev filter blacklist { type ipv4_addr\; flags interval\; auto-merge\; }

Создаем правила, блокирующие IP-адреса, входящие в набор 'blacklist', со счетчиком, показывающим сколько раз была выполнена блокировка данных (counter) и выдачей сообщения о блокировке в журнал (log prefix NFT_BL):

sudo nft add rule netdev filter ingress_wan iifname "wan" ip saddr @blacklist counter log prefix NFT_BL drop
sudo nft add rule netdev filter ingress_lan iifname "lan" ip daddr @blacklist counter log prefix NFT_BL drop

Проверяем что получилось:

sudo nft -s list table netdev filter

table netdev filter {
        set blacklist {
                type ipv4_addr
                flags interval
                auto-merge
        }

        chain ingress_wan {
                type filter hook ingress device "wan" priority -500; policy accept;
				iifname "wan" ip saddr @blacklist counter log prefix "NFT_BL " drop
        }

        chain ingress_lan {
                type filter hook ingress device "lan" priority -500; policy accept;
                iifname "lan" ip daddr @blacklist counter log prefix "NFT_BL " drop
        }
}

Сохраняем текущие настройки nftables в конфиг-файл /etc/nftables.conf:

sudo mv -i /etc/nftables.conf /etc/nftables_`date +%Y%m%d-%H%M`.conf
sudo sh -c '/usr/bin/echo "#!/usr/sbin/nft -f" > /etc/nftables.conf'
sudo sh -c '/usr/bin/echo "flush ruleset" >> /etc/nftables.conf'
sudo sh -c '/usr/sbin/nft -s list ruleset >> /etc/nftables.conf'
sudo /usr/bin/chmod +x /etc/nftables.conf

Редактируем /etc/nftables.conf и вставляем в наборе 'blacklist' после 'auto-merge' новую строку 'include "/etc/nftables/blacklist.ip"'. Это позволит при старте nftables загружать список адресов и сетей из файла '/etc/nftables/blacklist.ip' и не засорять ими основной конфиг-файл nftables. Должно получиться:

set blacklist {
                type ipv4_addr
                flags interval
                auto-merge
                include "/etc/nftables/blacklist.ip"
        }

Создаем файл /etc/nftables/blacklist.ip и конфиг-файл /etc/nftables/blacklist.conf. Помещаем в /etc/nftables/blacklist.conf настройки набора ‘blacklist’. Это облегчит тестирование и загрузку созданного набора.

sudo mkdir /etc/nftables
sudo touch /etc/nftables/blacklist.ip
sudo nano /etc/nftables/blacklist.conf

В /etc/nftables/blacklist.conf должно быть определение набора 'blacklist' один в один как в конфиг-файле /etc/nftables.conf плюс определение таблицы в которой он создан:

table netdev filter {
        set blacklist {
                type ipv4_addr
                flags interval
                auto-merge
                include "/etc/nftables/blacklist.ip"
        }
}

Проверяем конфиг-файлы /etc/nftables/blacklist.conf и /etc/nftables.conf на отсутствие ошибок:

sudo nft -c -f /etc/nftables/blacklist.conf
sudo nft -c -f /etc/nftables.conf

Создание списка вредоносных адресов и сетей и его загрузку в nftables будем выполнять с помощью скрипта suricata_ip_to_nft. Скрипт скачивает данные напрямую с сайтов, которые их предоставляют, а если это невозможно, то берет их из правил. Скрипт снабжен подробными комментариями и вы можете изменить его под свои нужды. Не запускайте его слишком часто, некоторые сайты блокируют отдачу данных для слишком назойливых адресов. Не прерывайте выполнение скрипта не дождавшись результата, у меня он выполняется примерно минуту.

suricata_ip_to_nft
#!/usr/bin/bash
# 20260429
# примеры просмотра сета и таблицы:
# nft list set netdev filter blacklist | more
# nft list table netdev filter
# для работы скрипта требуются: dig, aggregate, grepcidr, proxychains4, jq

URL_ET_CINS="https://cinsscore.com/list/ci-badguys.txt"
URL_SPAMHAUS="https://www.spamhaus.org/drop/drop_v4.json"
URL_ET_THREATVIEW="https://threatview.io/Downloads/High-Confidence-CobaltStrike-C2%20-Feeds.txt"
URL_ETN_AGGRESSIVE="https://security.etnetera.cz/feeds/etn_aggressive.txt"
# конфиг сета blacklist
BLACKLIST_CONF="/etc/nftables/blacklist.conf"
# содержимое сета blacklist
BLACKLIST_IP="/etc/nftables/blacklist.ip"
OUT_DIR="/tmp/blacklist"

#sudo -u suricata /usr/bin/suricata-update -q > /dev/null

if [ -d "$OUT_DIR" ]; then
  /usr/bin/rm -f $OUT_DIR/*
else
/usr/bin/mkdir $OUT_DIR
fi

# получаем ip адреса, содержащиеся в правилах "ET CINS", с $URL_ET_CINS
/usr/bin/curl --connect-timeout 10 --max-time 60 -Ls $URL_ET_CINS -o $OUT_DIR/badguys
if [ ! -s "$OUT_DIR/badguys" ]; then
    /usr/bin/echo "Пиндосы не отдают данные с cinsscore.com. Получаю ip адреса из правил."
    /usr/bin/grep 'msg:"ET CINS ' /var/lib/suricata/rules/suricata.rules | /usr/bin/grep -Po '\[\K[^\]]+' | /usr/bin/tr ',' '\n' > $OUT_DIR/et_cins
fi

# получаем ip адреса из правил "ET CNС"
/usr/bin/grep 'msg:"ET CNC ' /var/lib/suricata/rules/suricata.rules | /usr/bin/grep -Po -- '->\s+\[?\K[^\]\s]+' > $OUT_DIR/et_cnc

# получаем ip адреса из правил "ET COMPROMISED"
/usr/bin/grep 'msg:"ET COMPROMISED ' /var/lib/suricata/rules/suricata.rules | /usr/bin/grep -Po '\[\K[^\]]+' | /usr/bin/tr ',' '\n' > $OUT_DIR/compromised

# получаем диапазоны ip адресов, содержащиеся в правилах "ET DROP", со www.spamhaus.org
/usr/bin/curl --connect-timeout 10 --max-time 60 -Ls $URL_SPAMHAUS -o $OUT_DIR/drop_v4.json
if [ ! -s "$OUT_DIR/drop_v4.json" ]; then
    /usr/bin/echo "Пиндосы не отдают данные со spamhaus.org. Получаю диапазоны сетей из правил."
    /usr/bin/grep 'msg:"ET DROP ' /var/lib/suricata/rules/suricata.rules | /usr/bin/grep -Po '\[\K[^\]]+' | /usr/bin/tr ',' '\n' > $OUT_DIR/nets.txt
else
/usr/bin/jq -r 'select(.cidr != null) | .cidr' "$OUT_DIR/drop_v4.json" > $OUT_DIR/nets.txt
fi

# получаем ip адреса, содержащиеся в правилах "ETN AGGRESSIVE", с $URL_ETN_AGGRESSIVE
/usr/bin/curl --connect-timeout 10 --max-time 60 -Ls $URL_ETN_AGGRESSIVE -o $OUT_DIR/aggressive.txt
if [ ! -s "$OUT_DIR/aggressive.txt" ]; then
    /usr/bin/echo "Пиндосы не отдают данные с etnetera.cz. Получаю ip адреса из правил."
    /usr/bin/grep 'msg:"ETN AGGRESSIVE ' /var/lib/suricata/rules/suricata.rules | /usr/bin/grep -Po '\[\K[^\]]+' | /usr/bin/tr ',' '\n' | /usr/bin/grep -v ":" > $OUT_DIR/aggresive
else
/usr/bin/cat $OUT_DIR/aggressive.txt | /usr/bin/grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' > $OUT_DIR/aggresive
fi

# получаем списки известных вредоносных ip адресов, содержащихся в правилах "ET Threatview.io", с $URL_ET_THREATVIEW
# нужен рабочий прокси, т.к. не отдают для России напрямую.
/usr/bin/proxychains4 -q /usr/bin/curl --connect-timeout 10 --max-time 60 -Ls $URL_ET_THREATVIEW -o $OUT_DIR/feeds.txt

if [ ! -s "$OUT_DIR/feeds.txt" ]; then
    /usr/bin/echo "Пиндосы не отдают данные с threatview.io. Получаю ip адреса из правил."
    /usr/bin/grep 'msg:"ET Threatview.io ' /var/lib/suricata/rules/suricata.rules | /usr/bin/grep -Po '\[\K[^\]]+' | /usr/bin/tr ',' '\n' > $OUT_DIR/et_threatview
else
    # обрабатываем файл со списками ip адресов от "ET THREATVIEW"
    /usr/bin/echo "Обрабатываю сложный файл со списками ip адресов от \"ET THREATVIEW\". ЖДИТЕ!!!"
    /usr/bin/grep -v '^#' $OUT_DIR/feeds.txt | /usr/bin/cut -d',' -f1 | while read -r host; do
        if [[ $host =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
            /usr/bin/echo "$host"
        else
            # Резолвим домен, берем только IPv4 и подавляем ошибки, если домен сдох
            /usr/bin/dig @8.8.8.8 +short A "$host" 2>/dev/null
        fi
    done | /usr/bin/grep -E '^[0-9.]+$' >> $OUT_DIR/feeds
fi

# убираем пересекающиеся диапазоны сетей из списка www.spamhaus.org
/usr/bin/cat $OUT_DIR/nets.txt | /usr/bin/aggregate -p 32 -m 32 -o 32 -t -q > $OUT_DIR/nets_opt.txt

# собираем все ip адреса в один файл
if [ -s "$OUT_DIR/blacklist.txt" ]; then
    /usr/bin/echo -n "" > $OUT_DIR/blacklist.txt
fi

if [ -s "$OUT_DIR/badguys" ]; then
    /usr/bin/cat $OUT_DIR/badguys >> $OUT_DIR/blacklist.txt
fi

if [ -s "$OUT_DIR/et_cins" ]; then
    /usr/bin/cat $OUT_DIR/et_cins >> $OUT_DIR/blacklist.txt
fi

if [ -s "$OUT_DIR/feeds" ]; then
    /usr/bin/cat $OUT_DIR/feeds >> $OUT_DIR/blacklist.txt
fi

if [ -s "$OUT_DIR/et_threatview" ]; then
    /usr/bin/cat $OUT_DIR/et_threatview >> $OUT_DIR/blacklist.txt
fi

/usr/bin/cat $OUT_DIR/et_cnc $OUT_DIR/compromised $OUT_DIR/aggresive >> $OUT_DIR/blacklist.txt

# сортируем и избавляемся от дубликатов
/usr/bin/cat $OUT_DIR/blacklist.txt | /usr/bin/sort -h | /usr/bin/sort -u  > $OUT_DIR/blacklist_sort.txt

# находим ip адреса непринадлежащие диапазонам сетей от www.spamhaus.org
/usr/bin/grepcidr -v -f $OUT_DIR/nets_opt.txt $OUT_DIR/blacklist_sort.txt > $OUT_DIR/blacklist

# добавляем адреса сетей к тем адресам, которые не принадлежат данным сетям
/usr/bin/cat $OUT_DIR/nets_opt.txt >> $OUT_DIR/blacklist

# выводим адреса в конфиг-файл set-а nftables
/usr/bin/echo "elements = {" > "$BLACKLIST_IP"
/usr/bin/cat $OUT_DIR/blacklist | /usr/bin/sed 's/$/,/' >> "$BLACKLIST_IP"
/usr/bin/sed -i '$ s/,$//' "$BLACKLIST_IP"
/usr/bin/echo "}" >> "$BLACKLIST_IP"

# проверяем корректность набора blacklist
if ! /usr/sbin/nft -c -f "$BLACKLIST_CONF" 2>"$OUT_DIR/nft_error.log"; then
    /usr/bin/echo "Ошибка при проверке набора blacklist! Выход."
    /usr/bin/cat $OUT_DIR/nft_error.log
    exit
fi

/usr/bin/echo -n `/usr/bin/date` "Загружаю новые данные в набор blacklist."
/usr/sbin/nft flush set netdev filter blacklist
if ! /usr/sbin/nft -f "$BLACKLIST_CONF" 2>"$OUT_DIR/nft_error.log"; then
    /usr/bin/echo " Ошибка! Выход."
    /usr/bin/cat $OUT_DIR/nft_error.log
    exit
fi
/usr/bin/echo " Успех!"
/usr/bin/echo "Всего загружено" `/usr/bin/cat $OUT_DIR/blacklist | /usr/bin/wc -l` "элементов (адресов и диапазонов сетей)."

# удаляем промежуточные результаты
#/usr/bin/rm -rf $OUT_DIR

Чтобы скрипт мог получать данные из правил "ETN AGGRESSIVE", если сайт источника будет недоступен, включим использование источника 'etnetera/aggressive' (предполагается, что источник 'et/open' у вас уже используется) и обновим списки правил:

sudo -u suricata suricata-update enable-source etnetera/aggressive
sudo -u suricata suricata-update --no-reload 

Убедимся, что новые правила выключены (закомментированы). Команда выведет не закомментированные правила которые содержат "ETN AGGRESSIVE":

grep "ETN AGGRESSIVE" /var/lib/suricata/rules/suricata.rules | grep -vE "^#"

Установите необходимые программы для работы скрипта:

sudo apt install dnsutils aggregate grepcidr proxychains4 jq

Необходимо настроить /etc/proxychains4.conf, чтобы получать списки "ET THREATVIEW", т.к. их не отдают для пользователей из России. Если вы не можете настроить proxychains4, то просто закомментируйте строку, где она используется, тогда программа возьмет данные из списка правил. Но это не очень хорошее решение, потому что составители правил берут адреса из тех же самых источников и на изменение правил требуется время, т.е. адреса появляются в правилах с задержкой. Плюс в правила их всегда почему-то включают не полностью.

Запускаем скрипт:

sudo suricata_ip_to_nft
sudo cat /etc/nftables/blacklist.ip | more
sudo nft list set netdev filter blacklist | more
sudo nft list table netdev filter | more

Проверяем что получилось в итоге:

sudo cat /etc/nftables/blacklist.ip | more
sudo nft list set netdev filter blacklist | more
sudo nft list table netdev filter | more

Проверить были ли блокировки адресов, содержащихся в наборе 'blacklist' (смотрите на показания счетчика 'counter'):

sudo nft list chain netdev filter ingress_wan
sudo nft list chain netdev filter ingress_lan

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

sudo journalctl | grep NFT_BL | awk '{ print $1, $2, $3, $6, $9, $10, $17, $18, $19 }' | more

Или только для вывода IP адресов:

sudo journalctl | grep NFT_BL | awk '{ print $6, $9, $10 }' | sort -u

Используйте скрипт suricata_ip_check чтобы посмотреть под какое правило блокировки попал IP-адрес или какому списку он принадлежит:

suricata_ip_check
#!/usr/bin/bash
#20260430
OUT_DIR="/tmp/blacklist"

if [ -z "$1" ]; then
    /usr/bin/echo "Использование: $0 <IP_адрес>"
    exit 1
fi

if /usr/bin/grep -qF "$1" "/var/lib/suricata/rules/suricata.rules"; then
/usr/bin/echo "Найдено в правилах:"
/usr/bin/grep "$1" /var/lib/suricata/rules/suricata.rules | grep -Po 'msg:"\K[^"]+'
fi

if /usr/bin/grep -qxF "$1" "$OUT_DIR/et_cins"; then
/usr/bin/echo "$1 найден в списке \"ET CINS\""
fi
if /usr/bin/grep -qxF "$1" "$OUT_DIR/et_cnc"; then
/usr/bin/echo "$1 найден в списке \"ET CNC\""
fi
if /usr/bin/grep -qxF "$1" "$OUT_DIR/et_compromised"; then
/usr/bin/echo "$1 найден в списке \"ET COMPROMISED\""
fi
if /usr/bin/grep -qxF "$1" "$OUT_DIR/et_threatview"; then
/usr/bin/echo "$1 найден в списке \"ET Threatview.io\""
fi
if /usr/bin/grep -qxF "$1" "$OUT_DIR/etn_aggressive"; then
/usr/bin/echo "$1 найден в списке \"EТN AGGRESSIVE\""
fi
if /usr/bin/echo "$1" | /usr/bin/grepcidr -f /tmp/blacklist/et_drop >/dev/null; then
/usr/bin/echo "$1 найден в списке подсетей \"EТ DROP\""
fi

Выполните на роутере:

suricata_ip_check 150.171.109.100

Затем на клиенте локальной сети, чтобы понять какой процесс пытался получить доступ к заблокированному IP-адресу (команды PowerShell для windows):

> netstat -ano -p tcp | select-string "150.171.109.100"
TCP    192.168.124.1:57736    150.171.109.100:443    SYN_SENT        9892
> Get-Process -Id 9892 | Select-Object Name, Parent, Path

Либо используйте «Диспетчер задач» для поиска процесса с указанным ID.

Если вдруг окажется, что вам все-таки нужен доступ к какому-то IP-адресу из черного списка, то создайте правила для пропуска трафика:

sudo nft insert rule netdev filter ingress_wan iifname "wan" ip saddr 1.1.1.1 accept
sudo nft insert rule netdev filter ingress_lan iifname "lan" ip daddr 1.1.1.1 accept

Посмотрите результат:

sudo nft list chain netdev filter ingress_wan
sudo nft list chain netdev filter ingress_lan

Теперь, чтобы не включать список адресов набора ‘blacklist’ в основной конфигурационный файл nftables и не засорять его, сохраняйте текущие настройки nftbles скриптом:

nftables_save
#!/usr/bin/bash
/usr/bin/mv -i /etc/nftables.conf /etc/nftables_`date +%Y%m%d-%H%M`.conf
/usr/bin/echo "#!/usr/sbin/nft -f" > /etc/nftables.conf
/usr/bin/echo "flush ruleset" >> /etc/nftables.conf
/usr/sbin/nft -st list ruleset >> /etc/nftables.conf
/usr/bin/sed -i '/auto-merge/a \\t\tinclude "/etc/nftables/blacklist.ip"' /etc/nftables.conf
/usr/bin/chmod +x /etc/nftables.conf
/usr/sbin/nft -cf /etc/nftables.conf 2>/dev/null && /usr/bin/echo "Конфиг /etc/nftables.conf протестирован без ошибок." || 
 { /usr/bin/echo "Ошибка тестирования /etc/nftables.conf"; exit 1; }

Убедитесь, что строка 'include "/etc/nftables/blacklist.ip"' вставлена после 'auto-merge' именно в набор 'blacklist'.

Не забудьте, что правила содержащие "ET CINS", "ET CNС", "ET COMPROMISED", "ET DROP", "ET Threatview.io", "ETN AGGRESSIVE" никогда не должны быть активированы.

13.4 Создание задания на обновление правил.

Создадим лог-файл и назначим ему необходимые права и владельцев:

sudo touch /var/log/suricata_ip_to_nft.log
sudo chown root:suricata /var/log/suricata_ip_to_nft.log
sudo chmod 664 /var/log/suricata_ip_to_nft.log

Используйте скрипт suricata_ip_to_nft для обновления правил и списка вредоносных адресов и сетей. Разрешите в нем запуск suricata-update (строка 18) и закомментируйте все не важные для вас команды вывода сообщений. Создайте запись запуска скрипта в crontab с перенаправлением выводимой информации в лог-файл. Также необходимо создать запись для обновления источников правил. Не забудьте, что файл crontab должен завершаться пустой строкой.

Откройте планировщик командой 'sudo crontab -e' и добавьте строки:

1 */2 * * * /root/scripts/suricata_ip_to_nft >> /var/log/suricata_ip_to_nft.log 2>>/var/log/suricata_ip_to_nft.log
1 1 * * MON /usr/bin/sudo -u suricata /usr/bin/suricata-update update-sources > /dev/null 2>>/var/log/suricata_ip_to_nft.log

Посмотрите результат:

sudo crontab -l

Запуск suricata_ip_to_nft и 'suricata-update update-sources' не должны пересекаться. Источники правил должны обновляться не реже, чем 1 раз в 2 недели.