Практическое руководство, как сделать так, чтобы большинство портов выглядели «filtered», легитимный трафик проходил, а попытки разведки фиксировались в логах. Основной стек — iptables + Snort
Зачем это нужно
Сканирование портов — обязательный этап разведки перед атакой. Чем меньше информации отдаёт хост (статус «filtered» вместо «open/closed»), тем сложнее злоумышленнику. При этом нам важно не сломать доступ к легитимным сервисам и получать сигналы о подозрительной активности.
Цель статьи:
Скрыть по максимуму «поверхность» хоста от сканеров.
Ограничить «бурст» новых соединений.
Логировать и быстро замечать попытки скана.
Что используем: iptables (classic netfilter), nmap для проверки, Snort для детектирования.
Примечание: в ряде дистрибутивов по умолчанию уже стоит
nftables/firewalld. В этой статье — конфигурация наiptables. Если у вас nft, можно применить те же идеи эквивалентными правилами.
Исходные данные и допущения
Внешний интерфейс:
eth0Внутренний (опционально):
eth1Хост:
10.10.20.5Админский SSH слушает порт
2222/tcpВход в SSH разрешён только из офисной сети
203.0.113.0/24
Все значения взяты «с потолка» для примеров — подставьте свои.
Базовый профиль iptables
# Очистка текущих правил (осторожно!)
iptables -F
iptables -X
iptables -t nat -F
iptables -t mangle -F
# Политики по умолчанию — сначала осторожно ACCEPT, затем ужесточим по месту
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
# Разрешаем loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Разрешаем ответы на исходящие (ESTABLISHED, RELATED)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
# Отбрасываем «битый» трафик
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
Если хост роутирует трафик между интерфейсами (не всем нужно):
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Анти‑скан правила по TCP‑флагам
Блокируем «нестандартные» комбинации (NULL/FIN/XMAS и др.), которые любят использовать сканеры.
# NULL scan
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
# FIN+…
iptables -A INPUT -p tcp --tcp-flags FIN,ACK FIN -j DROP
iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
# Xmas scan (FPU)
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
# Комбинации SYN с RST/FIN (подозрительно)
iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
Ограничение скорости «новых» подключений
Снижаем частоту создания новых TCP‑сессий с одного источника — полезно против агрессивного сканирования.
# Помечаем все новые
iptables -A INPUT -p tcp -i eth0 -m state --state NEW -m recent --set
# Если от одного IP >6 новых коннектов за 20 сек — дропаем
iptables -A INPUT -p tcp -i eth0 -m state --state NEW -m recent --update \
--seconds 20 --hitcount 6 -j DROP
Числа 6/20 — пример. Подберите под свой профиль трафика.
Разрешения и запреты «пойнт‑ту‑пойнт»
Оставим доступ к SSH только из офисной сети, всё прочее — закрываем.
# Разрешаем SSH на порту 2222 из корпоративной сети
iptables -A INPUT -p tcp -s 203.0.113.0/24 --dport 2222 -i eth0 -j ACCEPT
# Остальным — нельзя
iptables -A INPUT -p tcp --dport 2222 -j DROP
Теперь ужесточаем политики по умолчанию:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
После смены политик проверьте, что не отрезали себя от сервера.
Проверяем себя nmap
С внешней машины (не с самого хоста):
nmap -Pn 10.10.20.5
nmap -sS 10.10.20.5
nmap -sX -p 2222 10.10.20.5 # Xmas
nmap -sN -p 2222 10.10.20.5 # Null
nmap -sF -p 2222 10.10.20.5 # Fin
Ожидания: большинство портов — filtered, SSH (2222/tcp) — open только для разрешённой подсети.
Сохранение правил после перезагрузки
Вариант A (Debian/Ubuntu): iptables-persistent
apt-get update && apt-get install -y iptables-persistent netfilter-persistent

netfilter-persistent save
netfilter-persistent reload
Вариант B: вручную
iptables-save > /etc/iptables/rules.v4
# …и затем подхватывать их в init/systemd (если настроено)
Для RHEL/Alma/Rocky можно выразить ту же логику через
firewalld/rich rulesили переключиться наnftables.
Детектирование сканов с помощью Snort
Установка (Ubuntu/Debian)
apt-get update && apt-get install -y snort
snort --version
Минимальные локальные правила
Создайте файл local.rules (путь зависит от сборки; часто /etc/snort/rules/local.rules или /usr/local/etc/rules/local.rules). Добавим базовые алерты на наш хост 10.10.20.5 и порт SSH 2222:
alert tcp any any -> 10.10.20.5 2222 (msg:"TCP Scan to SSH-alt"; flags:S; sid:1001001; rev:1;)
alert tcp any any -> 10.10.20.5 2222 (msg:"XMAS Scan"; flags:FPU; sid:1001002; rev:1;)
alert tcp any any -> 10.10.20.5 2222 (msg:"FIN Scan"; flags:F; sid:1001003; rev:1;)
alert tcp any any -> 10.10.20.5 any (msg:"Possible UDP Scan"; sid:1001004; rev:1;)
Запуск в консоль
snort -A console -q -c /etc/snort/snort.conf -i eth0
При срабатывании увидите сообщения в консоли/логах. Дальше можно настроить вывод в syslog и интеграции (см. ниже).
Оповещения: syslog → Telegram/Email
Snort пишет события в syslog/файл, небольшой скрипт читает лог и отправляет уведомления.
План такой:
Настроить Snort на вывод в
/var/log/snort/alertили syslog (/var/log/syslog).Использовать
tail -F+ небольшой Python/Bash‑скрипт‑парсер.Отправлять в Telegram (бот‑токен + chat_id) или email (sendmail/SMTP).
Ввести порог: например, не слать алерты, пока < 3 совпадений одного источника за 60 секунд.
Бонус: можно завести
fail2banфильтр, который по определённым алертам на короткий срок банит IP (аккуратно с false positive).
Альтернатива: Suricata
Если предпочтительнее YAML‑конфиг, многопоточность «из коробки» и формат EVE JSON — используйте Suricata. Логика та же.
Установка (Ubuntu/Debian)
apt-get update && apt-get install -y suricata
suricata --build-info
Пример 1: простое правило на сканы TCP к SSH‑порту 2222 /etc/suricata/rules/local.rules:
alert tcp any any -> 10.10.20.5 2222 (msg:"SURICATA TCP scan to SSH-alt"; flags:S; sid:2001001; rev:1;)
Перезапуск и проверка:
suricata -T -c /etc/suricata/suricata.yaml
systemctl restart suricata
# события ищите в /var/log/suricata/eve.json
Пример 2: алерт на XMAS‑скан
alert tcp any any -> 10.10.20.5 2222 (msg:"SURICATA XMAS scan"; flags:FPU; sid:2001002; rev:1;)
Suricata удобно интегрируется с SIEM (EVE JSON), легко писать jq‑парсеры и метрики в Prometheus/ELK.
Чек‑лист после внедрения
Вы не отрезали себе SSH (проверить из разрешённой подсети).
Легитимные сервисы (HTTP/HTTPS/VPN) доступны извне.
nmapизвне показываетfilteredдля ненужных портов.Правила переживают перезагрузку (проверить
netfilter-persistent).Snort/Suricata пишет в логи и вы получаете оповещения.
Есть резервная копия правил firewall и базовый план отката.
Частые проблемы
Перестарались с DROP: разбираем цепочки сверху вниз, временно ставим
-P INPUT ACCEPT, подключаемся по out‑of‑band доступу, правим правила, затем снова ужесточаем.Включили rate‑limit и «уронили» приложение: адаптируйте
--seconds/--hitcountпод свой профиль трафика или отключите матчинг-m recentдля нужного сервиса.Не вижу алертов: проверьте интерфейс (
-i eth0), пути к правилам, права на файлы, и что трафик действительно достигает хоста.
Вывод
Минимальный набор из iptables‑жёсткостей + Snort даёт хороший «порог боли» для порт‑сканеров и базовую наблюдаемость. Если удобнее YAML и EVE JSON — берите Suricata.
Ключевое — бережно тестировать, сохранять правила и держать под рукой план отката.
