Поднимаем IDS/NMS: Mikrotik и Suricata c web-интерфейсом

  • Tutorial
У меня, видимо, такая карма: как ни возьмусь за реализацию какого-нибудь сервиса на опенсорсе, так обязательно найду кучу мануалов, каждый по отдельности из которых в моем конкретном случае не сработает, готовое решение толком не заведется или не понравится, случится еще какая-нибудь неудобоваримость, и в итоге приходится самому пробиваться к результату.

В этот раз все мануалы были на ELK5 или еще старше, а мне не очень хотелось ставить софтину пред-предыдущих версий. Мне хотелось взять софтину с наиболее перспективными сроками поддержки: желательно самое свежее из стабильного.

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

Итак, сегодня Mikrotik (RouterOS), Suricata 4.1, Elasticsearch+Filebeat+Kibana 6.5.

Вместо вступления


Условия:

  • Mikrotik на i386 в виртуальной машине на хосте А. Все интерфейсы на Mikrotik'е раскиданы по VLAN'ам, хост имеет один физический сетевой интерфейс.
  • Свободные ресурсы для IDS/IPS/NMS на хосте Б с единственным физическим сетевым интерфейсом.
  • 20-мегабитный канал наружу.
  • Желание получать аналитику о проходящем через внешний интерфейс Mikrotik'а трафике.
  • Бюджет в хрен рублей и фиг копеек.
  • Некоторое количество свободного от хлопот времени.

Я не стану рассказывать здесь, что такое IDS/IPS/NMS, зачем оно нужно и какое оно бывает. Все это знают и без меня, а кто не знает, тот нагуглит.

Так же я не стану обосновывать свой выбор между Snort и Suricata в пользу последнего. Это дело вкуса.

Зато поверхностно объясню, как это работает:

Suricata неким образом получает трафик. Вариантов три: а) пропускать его через себя в inline-режиме, б) получать копию трафика с порта коммутатора и в) анализировать дампы с трафиком. Полученный трафик Suricata подвергает анализу и на основе проведенного анализа выдает данные о том, что же она там в этом трафике нашла.

Данные Suricata может выдавать в JSON'е. Соответственно, имея структурированные данные, их можно скормить какой-нибудь системе для обработки, систематизации, анализа и визуализации.
Для анализа и визуализации данных, на сколько я понял, не являясь специалистом в этой области, прекрасно подходит ELK-стек. ELK-стек первоначально состоял из Elasticsearch, Logstash, Kibana. Сейчас к нему добавился Beat (семейство программ-интерфейсов, выступающих посредником между источником данных и Logstash'ем или Elasticsearch'ем). Забегая вперед, скажу, что обошлось без Logstash'а, поскольку Beat прекрасно отдает данные напрямую в Elasticsearch, а Elasticsearch отлично их кушает. Скушанные данные Elasticsearch передает Kibana — веб-интерфейсу для всего ELK-стека. Kibana, используя шаблоны, переданные ему Filebeat'ом, предоставляет пользователю визуализацию данных, так называемые Dashboard'ы. Учитывая тот факт, что Elasticsearch, Logstash, Beat и Kibana плод трудов одного производителя, все это хозяйство неплохо увязывается друг с другом, и процесс связывания неплохо документирован (по опенсорсным меркам, конечно).

Таким образом, исходя из вышесказанного, задачу можно описать так: получить копию трафика с порта маршрутизатора, передать ее в Suricata, получить от Suricata данные в JSON-формате, передать их в Filebeat, чтобы тот, в свою очередь, передал их в Elasticsearch и помог Kibana создать их визуальное отображение.

Mikrotik RouterOS


Если бы маршрутизатор Mikrotik у меня был аппаратный, то вопрос зеркалирования порта (port mirroring) не стоял бы вообще. Все решилось бы включением зеркалирования трафика, проходящего через внешний интерфейс, на любой свободный порт самого Mikrotik'а. Если бы не было свободного порта на Mikrotik'е, можно было бы включить зеркалирование порта на коммутаторе. Но в моем случае Mikrotik вообще не имел физических портов, а порт на коммутаторе получал трафик со всего хоста, на котором, кроме Mikrotik'а, было еще несколько виртуальных машин.

И тут я в очередной раз мысленно сказал: «Спасибо, Mikrotik!». Спасибо за встроенный в RouterOS сниффер. По традиции обходимся без скриншотов, одними лишь консольными командами.

Открываем терминал в WinBox'е и включаем сниффер:

/tool sniffer set filter-interface=if-out filter-stream=yes streaming-enabled=yes streaming-server=192.168.1.253
/tool sniffer start


Указываете вместо if-out имя интерфейса, трафик с которого планируете перехватывать, и вместо 192.168.1.253 — IP-адрес машины, куда по протоколу TZSP будет отправляться перехваченный трафик.

С Mikrotik'ом все.

Suricata


Вообще, я не очень линуксоголовый, поэтому больше всего люблю попсовые дистрибутивы. Ну, разве что больше люблю более аскетичный Debian. Вот и начал с него. Ну и, разумеется, в силу нелинуксоголовости ставить хотел бинарники и из репозитория. Сборка — это мне всегда лениво. Так вот, если будет возможность выбрать Debian, — не выбирайте. Я сейчас не вспомню, в каком именно месте у меня был затык в установке всего хозяйства под Debian'ом, но он был. И вся дальнейшая история об установке всего под Ubunta.

Была создана 4-ядерная виртуальная машина с 4 гигами оперативки, скачан и установлен на нее Ubuntu Server 18.04.1 LTS (x64)

Соглашение: все дальнейшие действия выполняются от имени superuser, поэтому или логиньтесь под root, или к каждой команде добавляйте sudo.

Поскольку на каждом этапе я делал снапшоты, а потом неоднократно к ним откатывался, в конце я прикурил изрядных глюков с рассинхроном времени в виртуалке с реальным временем.
Поэтому сразу выставляем правильный часовой пояс и синхронизацию по NTP:

systemctl start systemd-timesyncd
systemctl status systemd-timesyncd
dpkg-reconfigure tzdata


Для того, чтобы при установке Suricata не было проблем с зависимостями, добавляем репозитории universe в /etc/apt/sources.list:

nano /etc/apt/sources.list

deb archive.ubuntu.com/ubuntu bionic main universe
deb archive.ubuntu.com/ubuntu bionic-security main universe
deb archive.ubuntu.com/ubuntu bionic-updates main universe

Так же добавляем репозиторий, откуда будем брать Suricata:
add-apt-repository ppa:oisf/suricata-stable

Обновляем базу пакетов:
apt-get update

Устанавливаем Suricata:
apt-get install -y suricata

Следующий этап — установка правил для Suricata и их апдейта:
apt-get install -y python-pip
pip install pyyaml
pip install https://github.com/OISF/suricata-update/archive/master.zip


Запускаем обновление самого suricata-update:
pip install --pre --upgrade suricata-update

Запуск без дополнительного конфигурирования поставит нам Emerging Threats Open ruleset:
suricata-update

Чтобы посмотреть список источников, выполняем:
suricata-update list-sources

Обновление источников правил:
suricata-update update-sources

Посмотрим, что там наобновлялось в источниках, выполним повторно:
suricata-update list-sources

Включаем все бесплатные источники:
suricata-update enable-source ptresearch/attackdetection
suricata-update enable-source oisf/trafficid
suricata-update enable-source sslbl/ssl-fp-blacklist


И еще раз обновляем правила:
suricata-update

Suricata установлена.

Теперь надо получить трафик.

Trafr


Trafr — это приложение, написанное Mikrotik'ом для конвертации TZSP-трафика в pcap. Приложение 32-битное, поэтому для его запуска понадобится включить поддержку 32-битных приложений в 64-битной Ubunta:

dpkg --add-architecture i386
apt-get update && apt-get install -y libc6:i386


Скачиваем и распаковываем trafr:

wget http://www.mikrotik.com/download/trafr.tgz
tar xzf trafr.tgz


Проверяем, что трафик ловится:

./trafr -s

У меня после такого запуска в консоли виртуальной машины сломался символьный вывод в графическом режиме, пришлось перезагружаться. При удаленном подключении через ssh в PuTTY никаких проблем не было.

Если на экране видите беспорядочное мельтешение, значит трафик прилетает, и trafr его ловит. Раз так, переносим trafr на ПМЖ и запускаем его с передачей пойманного трафика через конвейер сразу в Suricata:

mv trafr /usr/local/bin/
/usr/local/bin/trafr -s | suricata -c /etc/suricata/suricata.yaml -r /dev/stdin


Сейчас проверяем, что трафик поступает в Suricata, для этого в соседнем терминале выполняем:

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

Должны увидеть шустрый скролл осмысленного текста — лог получения трафика сурикатой.

Так же не лишним будет убедиться, что Suricata трафик не только получает, но и анализирует:

tail -f /var/log/suricata/eve.json

Это как раз тот самый выход событий из Suricata в JSON-формате, который мы будем скармливать Filebeat'у.

Elasticsearch+Filebeat+Kibana 6.5


Устанавливаем PGP-ключ, необходимый для пользования репозиторием Elastic и устанавливаем необходимые зависимости:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
apt-get update && apt-get install -y openjdk-8-jre apt-transport-https wget nginx


Обратите внимание, что Java версии 8. Все, что выше 8 — не поддерживается. Поэтому, если успели ранее установить более свежую Java, сносите ее и ставьте 8.

Убеждаемся, что Java установилась как надо:

java -version

Получим примерно такой вывод:
java version «1.8.0_191»
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)

Создаем пользователя и пароль для доступа к Kibana. Вместо admin выберите что-то, что вам больше по вкусу:

echo "admin:`openssl passwd -apr1`" | sudo tee -a /etc/nginx/htpasswd.users

Поскольку ELK будет крутиться на localhost, настраиваем reverse proxy в nginx:

nano /etc/nginx/sites-available/kibana
server {
listen 80;

server_name suricata.server;

auth_basic «Restricted Access»;
auth_basic_user_file /etc/nginx/htpasswd.users;

location / {
proxy_pass localhost:5601;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

rm /etc/nginx/sites-enabled/default
ln -s /etc/nginx/sites-available/kibana /etc/nginx/sites-enabled/kibana


Перезапускаем nginx:

systemctl restart nginx

Ставим Elasticsearch:

apt-get install -y elasticsearch

Включаем автозапуск при загрузке ОС:

systemctl daemon-reload
systemctl enable elasticsearch.service


Запускаем:

systemctl start elasticsearch.service

Проверяем, поднялось ли:

curl -X GET "localhost:9200/"

В зависимости от производительности вашей железки, запуск ES может занять какое-то время. Если получаем connection refused, то просто повторяем запрос и ждем, пока в ответ не получим что-то вроде:
{
«name»: «lcZuxxm»,
«cluster_name»: «elasticsearch»,
«cluster_uuid»: «kmJHqJnlQe2Rk7F-CRi4EA»,
«version»: {
«number»: «6.5.1»,
«build_flavor»: «default»,
«build_type»: «deb»,
«build_hash»: «8c58350»,
«build_date»: «2018-11-16T02:22:42.182257Z»,
«build_snapshot»: false,
«lucene_version»: «7.5.0»,
«minimum_wire_compatibility_version»: «5.6.0»,
«minimum_index_compatibility_version»: «5.0.0»
},
«tagline»: «You Know, for Search»
}

Ставим Kibana:

apt-get install -y kibana

Включаем автозапуск при загрузке ОС:

systemctl daemon-reload
systemctl enable kibana.service


Запускаем:

systemctl start kibana.service

Теперь можно перейти на 192.168.1.253 (естественно, IP-адрес тот, что назначили вашей машине с сурикатой). Должна открыться титульная страница Kibana

Ставим Filebeat:

apt-get install -y filebeat

Включаем автозапуск при загрузке ОС:

systemctl daemon-reload
systemctl enable filebeat


Включаем модуль Suricata, входящий в набор модулей Filebeat:

filebeat modules enable suricata

Устанавливаем плагины для Suricata в Elasticsearch:

/usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-geoip
/usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-user-agent

Смотрите UPD от 22 мая 2019 года.

Перезапускаем Elasticsearch:

systemctl restart elasticsearch.service

Выполняем первоначальную настройку Filebeat, заодно выполнится загрузка шаблонов в Kibana:

filebeat setup -e

Проверяем, что Filebeat нашел /var/log/suricata/eve.json и обрабатывает его, для этого запускаем Filebeat в режиме вывода на экран данных с маркером publish:

filebeat -e -d "publish"

Первым пойдет json-форматированный вывод самого Filebeat'а, потом простой текстовый вывод его логов, и только спустя некоторое время вывод из Suricata, поэтому выждите и убедитесь, что все работает. После этого прервите Filebeat и вернитесь в bash.

Включаем автозапуск при загрузке ОС:

systemctl daemon-reload
systemctl enable filebeat.service


Запускаем Filebeat:

systemctl start filebeat.service

Переходим в Kibana, выбираем в меню слева Dashboard, выбираем индекс filebeat-*. Снова выбираем Dashboard, в списке выбираем [Suricata] Alert Overview и должны получить что-то вроде такого:

image

Факультативно


Не забудьте logrotate, а не то каким бы емким ни был жесткий диск, Suricata его забьет очень быстро:

nano /etc/logrotate.d/suricata
/var/log/suricata/*.log /var/log/suricata/*.json
{
weekly
rotate 3
missingok
nocompress
create
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/suricata.pid 2>/dev/null` 2>/dev/null || true
endscript
}

Кроме того, ходили слухи, что у кого-то регулярно сниффер в Mikrotik'е при статусе running перестает отдавать трафик. Тогда пишем скрипт для перезапуска сниффера и запускаем его по расписанию:

/tool sniffer stop
:delay 30s
/tool sniffer start


Заключение


Признаться, я не вполне доволен стабильностью приведенной выше связки. А именно: стоит перезагрузиться, и начинаются чудеса. Один раз у меня перестали обрабатываться правила все, кроме пары. Пришлось все переустанавливать. Во второй раз Elasticsearch вообще перестал получать данные от Filebeat, и пришлось откатываться к снапшоту состояния до перезагрузки.

Эти проблемы пока не решил.

Кроме того, в планах реализовать IPS на базе переданных в Mikrotik IP-адресов злодеев, выявленных Suricata.

UPD: Обвинения в нестабильности снимаются. Мой вывод о прекращении обработки правил был ошибочен. На самом деле, причина пустоты в Dashboard'е после перезагрузки связана с тем, что Filebeat'у и Elasticsearch'у требуется весьма заметное время, чтобы пропарсить многогигабайтный json-файл от сурикаты. Если открыть Dashboard с событиями за период, включающий в себя дату создания файла eve.json, то можно увидеть, как растут столбцы диаграммы по мере обработки файла. Вместе с обработанными событиями появляются и алерты в соответствующем Dashboard'е. Кроме того, сниффер в RouterOS на x86 не повис ни разу.

UPD от 22 мая 2019г: Начиная с версии Elasticsearch 6.7 плагины ingest-geoip и ingest-user-agent преобразованы в модули. Соответственно, пункт с их установкой пропускаем.

Так же, при обновлении получите ошибку запуска Elasticsearch. В логах будете видеть ошибку:

expected database [GeoLite2-ASN.mmdb] to not exist in [/etc/elasticsearch/ingest-geoip]

Для восстановления работоспособности выполняем:

/usr/share/elasticsearch/bin/elasticsearch-plugin remove --purge ingest-geoip

Комментарии 17

    0
    В дополнении скажу, что тема неплохо освещена на Московском MUMе 2018 года от Романа Козлова, также у него на канале есть более подробное видео с вебинара (не воспринимайте за рекламу, просто сам немного интересуюсь данной темой). Посмотрите, может что то новое для себя откроете. Также есть телеграмм канал, можно спросить там по вашим проблемам.
    А так статья хорошая, спасибо за труды.
      0
      Да, я просмотрел это видео. Мне оно показалось несколько поверхностным, оно скорее как источник вдохновения для реализации такой связки на базе готового решения SELKS. У меня SELKS5 тоже участвовал в ходе поиска решения, но мне его не удалось завести с trafr, видимо, потому что плохо старался). В итоге описанное в моей статье решение лично для меня оказалось более простым и понятным, хотя, как я отметил в заключении, и не лишенным недостатков.
      0
      Буквально на неделе завершил (надеюсь) создание стабильной сборки mikrotik + SELKS, трафр не идет на той сборке debian из за отсутствия архитектуры и библиотек (после доставления хорошо работает, оставил tzsp2pcap так как указывал дополнительно порт приема),
      на данный момент сборка принимает 400 мбит от порт мирроринга (микротик свитч) и под 100 от сниффера микротика роутера (c виртуального интефейса), суриката смотрит в 2 интерфейса, блеклист микротика заполняется из fast.log suricatы. Дальше дело за farewall.
        0
        fare-wall? Ну, удачи!

        Вообще, конечно, вопрос — насколько это все эффективно. Не удивительно, что функции файрволла тащат через dpdk в юзер спейс. Либо ставят отдельную коробку. Ибо все задыхается от недостатка производительности
        0
        А готового appliance нет?
          0
          Вы имеете в виду virtual appliance? Если его, то нет.
          Если имеете в виду готовое решение, то оно есть, но у меня не заработало по причине, указанной в комментарии выше:
          трафр не идет на той сборке debian из за отсутствия архитектуры и библиотек (после доставления хорошо работает<...>)

          Я говорю о SELKS.
          0
          А виртуализация какая? Оно не умеет, как ESXi, делать promisc-порты в нужном влане? Это позволило бы без trafr обойтись, а напрямую в сурикату копию WAN-трафика WAN отдать.
            0

            ESXi и есть. Если бы они были на одном хосте, то задача зеркалирования порта была бы решена силами vSwitch'а, да… Вообще, я сторонник принципа keep it simple, и если задачу можно решить минимумом привлеченных ресурсов, значит так ее и надо решать).

            0

            Чего не достаёт:


            • развертывание всего через docker'ы (изоляция сервисов — это прекрасно)
            • или хотя бы разворачивания через ansible (долой копипаст команд!!!)
            • второй" головы" для эластика (в режиме standalone он работает плохо)
            • установки trafr как сервиса (ну, нафига записать тулзу в nohup/screen, если можно написать systemd юнит)
            • настройки параметров джавы (ну, там Хип и пр.)
              Понимаю, что часть этого за скоупом статьи, но мы же делаем всё "по уму", не так ли?

            В остальном — большое спасибо, очень интересный опыт.

              0
              Вы меня заинтриговали). В чем выражается плохая работа ES, если он один? И что именно нужно подкрутить у джавы, и что будет, если этого не сделать?

              Касаемо второго пункта — это прекрасно, но чтобы создать пакет развертывания, сначала нужно, чтобы оно хотя бы заработало после установки ручками, и именно этот процесс я описал).
                0
                Кратко. По эластику — он, например, никогда не даст «зелёный» статус кластера в однонодовом режиме.
                Ну, как минимум, неаккуратненько. Я уж не говорю про отказоустойчивость, быстродействие и т.п.
                Кстати, очень не круто может быть, когда диск на ноде с эластиком будет кончаться место.
                По джава — ну, вопрос в том, что несколько сервисов на одной машине будут «давить» друг друга. Попробуйте залить много данных в эластик и сделать «злой» запрос в кибану. Дальше уже всякие xmx, xms и прочая фигня.

                Касательно разворачивания. Ну, да, наверное, можно сначала сделать «в черную».
                  0
                  Понял, спасибо.
              0
              Мне кажется прелесть Сурикаты как раз в работе как IPS, с его-то inline режимом и блокировкой только нежелательного трафика, а блокировать все IP только из за того, что они генерили алерты как-то грубовато.
                0
                IDS/NMS это только обнаружение и мониторинг.
                IPS это тема для отдельного разговора. И в этом разговоре, разумеется, не будет размахивания шашкой на каждый алерт.
                0

                У меня опыт с ELK равен 0, поэтому, возможно вопрос глупый. В куче статей, в том числе и на оф. сайте читал, что чуть ли не абсолютный минимум для Elasticsearch 12 Гб RAM. У вас, я так понимаю, получилось запустить весь стек на 4Гб?

                  0
                  Ну, как-то «получилось запустить» — это громко сказано… Установил и запустил без всякого конфигурирования, оптимизаций и прочего. Все шаги, что я выполнял — в статье. Никаких дополнительных действий не выполнял.
                  Правда, это не полноценный ELK, ибо Logstash отсутствует, Filebeat отдает данные напрямую в ES.
                  При этом типичное потребление ресурсов вот такое:
                  0
                  В принципе, можно заставить работать trafr в SELKS5. Для начала:
                  Скрытый текст
                  wget http://www.mikrotik.com/download/trafr.tgz
                  tar -xzf trafr.tgz
                  sudo dpkg --add-architecture i386
                  sudo apt-get update
                  sudo apt-get install libc6:i386
                  sudo mv trafr /usr/local/bin/

                  А после этого надо сделать что-то типа:
                  Скрытый текст
                  ip link add eth10 type dummy
                  ip link set eth10 up
                  /bin/systemctl stop suricata
                  rm -rf /var/run/suricata.pid
                  trafr -s | tcpreplay --topspeed -i eth10 - &
                  /bin/systemctl start suricata

                  из-под рута. Я больше застрял на том, как сделать, чтобы при перезапуске всё начинало само работать нормально (Debian 9, systemd).

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое