Статья несет исключительно ознакомительный характер. Автор не несет ответственность за применение информации государством или иными самоуправляющими органами в своих корыстных, личных и прочих целях.
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 AND 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
Кроме того, 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 в качестве DPI.
Для написания статьи использовалась информация с блога одного из разработчиков Suricata и официальная Wiki.
Автор: kay