понедельник, 18 июля 2016 г.

Ускорение анализатора сетевого трафика Snort при помощи библиотеки Hyperscan.

Осенью прошлого года компания Intel открыла исходники библиотеки быстрого поиска совпадений для регулярных выражений Hyperscan. Проект был куплен двумя годами ранее. Предназначением этого удачного стартапа было ускорение DPI приложений за счёт использования SIMD compiler intrinsics. Использование новых наборов инструкций позволяет добиться значительного прироста производительности в самом узком месте анализаторов трафика: в поиске совпадений по образцу.  Snort  - самое известное DPI-приложение с открытым кодом - получил поддержку Hyperscan только в начале этого лета. Представленный патч предназначен для версии Snort 2.9.8.2 но без проблем накладывается на 2.9.8.3 и может быть портирован и на предыдущие релизы Snort. В статье описывается установка зависимостей и сборка снорт на дистрибутивах Gentoo и Ubuntu.
Данные шаги не должны вызывать сложностей у администраторов при использовании других дистрибутивов Linux.

Сборка

Для сборки Hyperscan сборочное окружение должно содержать  Boost версии >= 1.57 и компилятор ragel.  В библиотеке используется система сборки cmake. Сложности, если можно их назвать сложностями, вызывает только Boost: данной версии всё ещё нет в болшинстве дистрибутивов на момент июня 2016, поэтому скорее всего придётся собираться локально. Но это несложно и не очень долго. Что касается ragel и cmake, то они уже имеются в пакетных репозитариях Gentoo, Ubuntu, CentOS в достаточно свежих версиях.

Boost 

Нужен Boost выше 1.57. В наиболее ожидаемом случае, если версия в используемом дистрибутиве ниже, то надо будет установить более свежую копию. Для этого надо скачать актуальную версию и установить её локально.
tar xf ~/tmp/boost_1_61_0.tar.bz2
cd  boost_1_61_0
./bootstrap.sh -prefix=$HOME/opt/boost/
./b2 --ignore-site-config  install
--ignore-site-config требуется для устранения потенциальных конфликтов с системной версией Boost: дл игнорирования текущих настроек при сборке локальной версии буста в домашней директории пользователя.

Ragel

Далее нужен ragel, этот компилятор доступен в стандартных репозитариях всех распространённых дистрибутивов. Поэтому инсталляция проста:
emerge ragel

или же apt-get install ragel, yum install ragel итп итд

HyperScan

Сборка библиотеки стандартна для проектов использующих cmake:
tar xf ~/tmp/hyperscan-4.2.0.tar.gz
cd hyperscan-4.2.0/
mkdir build
cd build
cmake .. -DBOOST_ROOT=$HOME/opt/boost/ -DCMAKE_INSTALL_PREFIX=$HOME/opt/hp
make install
Предполагается, что будет использован локальный буст, установленный в $HOME/opt/boost.  Все переменные сборки можно проверить и перезадать при помощи `ccmake .` или же через аргументы cmake. В случае использования системного буста указывать -DBOOST_ROOT не следует.

Snort

Подходит кодовая база Snort любой из  2.9.8.* версий: 2.9.8.0, 2.9.8.2, в статье используется последний стабильный релиз: 2.9.8.3. Добавление поддержки HyperScan производится патчем версии v1: snort-2982-hyperscan-v1.tar_0.gz

 распаковываем исходники Snort:
tar xf ~/tmp/snort-2.9.8.3.tar.gz
cd snort-2.9.8.3/
накладываем патч:
 tar xf ~/tmp/snort-2982-hyperscan-v1.tar_0.gz
 gunzip -c snort-2982-hyperscan-v1/snort-2982-hyperscan-v1.patch.gz |patch -p2
На всех трёх доступных мне машинах с CentOS, Gentoo, Ubuntu этого было недостаточно для сборки: при линковке snort возникали ошибки вида
 /opt/hp/lib/libhs.a(mpvcompile.cpp.o): In function `operator--':
/usr/include/c++/4.8/bits/stl_tree.h:204: undefined reference to `std::_Rb_tree_decrement(std::_Rb_tree_node_base*)'
/opt/hp/lib/libhs.a(mpvcompile.cpp.o): In function `__gnu_cxx::new_allocator<ue2::raw_puff>::deallocate(ue2::raw_puff*, unsigned long)':
/usr/include/c++/4.8/ext/new_allocator.h:110: undefined reference to `operator delete(void*)'

то есть потребовалось ещё добавление -lstdc++  к списку библиотек в configure.in. Поэтому открываем любимым редактором файл configure.in, ищем в нём строчку, где задаётся  -lhs и  заменяем на -lhs -lstdc++:
 -    LIBS="${LIBS} -lhs"
+    LIBS="${LIBS} -lhs -lstdc++"
Собираем Snort:
autoreconf -fi
 ./configure --enable-intel-hyperscan --with-intel-hyperscan-includes=$HOME/opt/hp/include/hs --with-intel-hyperscan-libraries=$HOME/opt/hp/lib --prefix=$HOME/usr/opt298hp
make install

 Настройка

Для ускорения детектирования необходимо задать движок hyperscan в опции  config detection конфигурационного файла snort.conf:

config detection: search-method hyperscan 

Если использовать актуальный большой набор правил, например от Emerging Threats, то начальная загрузка снорта значительно замедлится. Чтобы избежать этого без особых потерь в ускорении можно использовать опцию split-any-any, таким образом результирующая строка config detection будет выглядеть следующим образом:

config detection: search-method hyperscan split-any-any

При этом будет наблюдаться выигрыш как в производительности, так и по использованию памяти; снорт будет использовать где-то на 10 процентов меньше памяти, точные данные зависят от набора правил. Без этой опции снорт будет анализировать трафик с максимальной скоростью, но будет гораздо дольше стартовать и более заметен в потреблении памяти системы.
 Таким образом, для сравнения получаются 4 системы с одним набором правил от ET:
  •  чистый Snort 2.9.8.3 без модификаций
  • Snort, собранный с Hyperscan, без изменений конфигурации, то есть использующий библиотеку только для простого поиска контента
  • Snort с Hyperscan и включённым движком детектирования hyperscan
  • Snort с включенным движком hyperscan и опцией split-any-any

Результаты

Скорость проще всего оценивается по времени обработки pcap-файлов. Результирующее ускорение зависит от новизны CPU. Так, на старом одноядерном Celeron M560, выигрыш будет в районе считанных процентов: с гиперсканом дамп будет обрабатываться за 300 секунд, без гиперскана за 310. Всё становится гораздо интереснее на более современных Intel(R) Core(TM) i7-2600:

Время обработки 100+ pcap файла  без hyperscan:

Run time for packet processing was 39.578298 seconds
Время обработки 100+ pcap файла  c hyperscan:

Run time for packet processing was 35.190397 seconds


Время обработки 100+ pcap файла  с движком hyperscan + split-any-any:

Run time for packet processing was 24.616165 seconds
Время обработки 100+ pcap файла  с движком hyperscan:

Run time for packet processing was 22.323232 seconds

2 комментария:

  1. может вам дать сервер с новым ядром для тестов. таки на i7-2600 нет avx2 - а эта фича должна еще ускорить ?

    ОтветитьУдалить
    Ответы
    1. В случае, если под ядром понимать cpu, не версию ядра линукс. Думаю, что разница между результатами должна усилиться при использовании более свежего железа, ожидаю дальнейший рост производительности.
      Хотя есть и негативный опыт в очень похожей задаче поиска символа в строке, тут http://cebka.blogspot.ru/2015/04/how-fast-is-your-memchr.html. Вкратце люди на своём коде наблюдали равную производительность при использовании sse и avx2, но всё-таки более примитивная задача, это влияет.

      Удалить