Предисловие
Печально видеть, что статьи о предупреждении или предотвращении вторжений на хабре столь непопулярны.
Курс молодого бойца: защищаемся маршрутизатором. Продолжение: IPS — 5 плюсов.
SNORT как сервисная IPS — 25 плюсов.
OSSEC: Большой Брат наблюдает за тобой — 13 плюсов.
Однако, огромной популярностью пользуются статьи по разбору последствий проникновения. Попробую вбросить очередную популяризацию информационной безопасности.
Описание Suricata

Система предотвращения вторжений (англ. Intrusion Prevention System) — программная или аппаратная система сетевой и компьютерной безопасности, обнаруживающая вторжения или нарушения безопасности и автоматически защищающая от них.
Системы IPS можно рассматривать как расширение Систем обнаружения вторжений (IDS), так как задача отслеживания атак остается одинаковой. Однако, они отличаются в том, что IPS должна отслеживать активность в реальном времени и быстро реализовывать действия по предотвращению атак. Возможные меры — блокировка потоков трафика в сети, сброс соединений, выдача сигналов оператору. Также IPS могут выполнять дефрагментацию пакетов, переупорядочивание пакетов TCP для защиты от пакетов с измененными SEQ и ACK номерами.
wiki
Suricata — open source IPS/IDS система. Основана разработчиками, которые трудились над IPS версией Snort. Основное отличие Suricata от Snort — возможность использования GPU в режиме IDS, более продвинутая система IPS, многозадачность, как следствие высокая производительность, позволяющая обрабатывать трафик до 10Gbit на обычном оборудовании, и многое другое, в том числе полная поддержка формата правил Snort. Лучше почитать обо всём на официальном сайте. Cегодня погорим об IPS.
В Suricata используется два режима IPS: NFQ и AF_PACKET
NFQ IPS режим работает следующим образом:
1) Пакет попадает в iptables
2) Правило iptables направляет его в очередь NFQUEUE, например iptables -I INPUT -p tcp -j NFQUEUE
3) Из очереди NFQUEUE пакеты могут обрабатываться на уровне пользователя, что и делает Suricata
4) Suricata прогоняет пакеты по настроенным правилам (rules) и в зависимости от них может вынести один из трех вердиктов: NF_ACCEPT, NF_DROP и самое интересное — NF_REPEAT.
5) Пакеты, попадающие в NF_REPEAT, могут быть промаркированы в системе, и направлены обратно в начало текущей таблицы iptables, что дает огромный потенциал для влияния на дальнейшую судьбу пакетов с помощью правил iptables.
Начиная с версии 1.4, Suricata умеет работать в качестве IPS, используя zero copy режим системы AF_PACKET, но с некоторыми ограничениями. Система должна работать в качестве шлюза с двумя сетевыми интерфейсами. Если пакет попадает под DROP правило, то он просто не пересылается на второй интерфейс. Плюсы zero copy — в скорости обработки пакетов, что несомненно понравится провайдерам, которые в случае бездействия рискуют нарваться на штрафы Роскомнадзора.
Установка Suricata на Ubuntu описана на официальной Wiki
Рассмотрим пример с NFQ на WEB сервере
Настраиваем первоначальное правило iptables:
# в очередь направляются пакеты, которые идут на 80-й порт и <b>НЕ</b> попадают под маску 0x1/0x1 для исключения бесконечного цикла
iptables -t mangle -I PREROUTING -p tcp -m tcp --dport 80 -m mark ! --mark 0x1/0x1 -j NFQUEUE --queue-num 0
Используем mangle, т.к. эта таблица является одной из первых на пути пакетов.
Опция --queue-bypass появилась в ядре 2.6.38 и позволяет пропускать все пакеты в очереди при отсутствии слушающего NFQUEUE приложения. Т.е. если Suricata не запущена, то все пакеты, попадающие под правила, пойдут дальше как ни в чем не бывало.
Опция --queue-num задаёт номер очереди.
-m mark! --mark 0x1/0x1 игнорирует все пакеты, которые уже были обработаны Suricata
Настраиваем Suricata в режиме IPS (относительно стандартной конфигурации, которая идет в пакете):
nfq:
mode: repeat
# настройка маски для обработанных пакетов
repeat-mark: 1
repeat-mask: 1
... ... ...
default-rule-path: /etc/suricata
rule-files:
- test.rules
# остальные правила можно закомментировать
Правило Suricata, которое реагирует на текст TEST в пакете (/etc/suricata/test.rules):
pass tcp any any -> any any (content: "TEST"; msg: "TEST was marked!"; nfq_set_mark:0x2/0xffffffff; sid:2455;)
sid должен быть уникальным
В совокупности с настройкой Suricata и правилом, маркировка и маска «плохого» пакета будут: 0x02/0xfe (0xff XOR 0x01 = 0xfe)
Запускаем Suricata:
suricata -q 0 -c /etc/suricata/suricata.yaml
Дальнейший разбор пакетов правилами iptables:
# детектируем пакет, на который сработало правило
iptables -t mangle -A PREROUTING -p tcp -m tcp --dport 80 -m mark --mark 0x2/0xfe -j LOG --log-prefix "TEST packet detected"
После выполнения на удаленном клиенте:
curl http://221.141.200.189/TEST
В /var/log/syslog появится запись вида:
Sep 9 14:23:06 server kernel: [ 2897.581561] TEST packet detectedIN=eth0 OUT= MAC=c5:d5:08:8f:2d:be:ce:df:3e:af:8c:06:08:00 SRC=97.17.34.191 DST=221.141.200.189 LEN=133 TOS=0x00 PREC=0x00 TTL=64 ID=57685 DF PROTO=TCP SPT=33949 DPT=80 WINDOW=115 RES=0x00 ACK PSH URGP=0 MARK=0x3
Не стоит забывать, что Suricata маркирует лишь пакеты. Чтобы правило сработало на всё соединение в целом, необходимо его промаркировать:
# Копируем маркировку пакетов в маркировку соединений
iptables -t mangle -A PREROUTING -m mark --mark 0x2/0xfe -j CONNMARK --save-mark
# детектируем соединение, на которое сработало правило
iptables -t mangle -A PREROUTING -m connmark --mark 0x2/0xfe -j LOG --log-prefix "TEST connection detected"
# И наоборот, копируем маркировку с соединения на все пакеты
iptables -t mangle -A PREROUTING -m connmark --mark 0x2/0xfe -j CONNMARK --restore-mark
Если обратить внимание на замечательное дополнение к iptables как RAW DNAT/SNAT, то при помощи Suricata можно направлять разные типы трафика на разные адреса назначения. Тут тоже кроются несколько нюансов как потеря целостности соединения, но это легко решить использованием проксирующего ПО, который сможет налету восстанавливать соединения.
Кроме того, Suricata умеет модифицировать пакеты «на лету». Например:
pass tcp any any -> any any (content: "TEST"; replace:"SETS"; msg: "TEST was marked!"; nfq_set_mark:0x2/0xffffffff; sid:2455;)
Заменит в пакете текст TEST на SETS, но при одном условии — заменяющие данные должны быть точно такого же размера, что и оригинал. В данном случае команда:
curl -v http://221.141.200.189/TEST
сохранит в лог WEB сервера:
97.17.34.191 - - [09/Sep/2013:14:51:04 +0400] "GET /SETS HTTP/1.1" 200 151 "-" "curl/7.26.0"
Рассмотрим пример с AF_PACKET на шлюзе
Здесь всё проще. Конфигурация suricata.yaml должна выглядеть приблизительно так:
af-packet:
- interface: eth0
threads: 1
defrag: yes
cluster-type: cluster_flow
cluster-id: 98
copy-mode: ips
copy-iface: eth1
buffer-size: 64535
use-mmap: yes
- interface: eth1
threads: 1
cluster-id: 97
defrag: yes
cluster-type: cluster_flow
copy-mode: ips
copy-iface: eth0
buffer-size: 64535
use-mmap: yes
Количество потоков обработчика должно быть не более единицы для ядер старше 3.6, иначе увеличение количества потоков вызовет бесконечный цикл.
MTU на обоих сетевых интерфейсах должно быть идентичным.
Запускаем Suricata:
suricata -c /etc/suricata/suricata.yaml --af-packet
Заключение
Suricata — гибкий инструмент по обработке пакетов, который позволяет менять маршруты в зависимости от содержания пакета, детектировать атаки и предотвращать попадание «плохих» пакетов в систему (например DROP'ать или подменять пакеты, пока они не дошли до WEB сервера). Возможно уже сейчас
Для написания статьи использовалась информация с блога одного из разработчиков Suricata и официальная Wiki.