Pull to refresh

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

Reading time 9 min
Views 47K
У меня, видимо, такая карма: как ни возьмусь за реализацию какого-нибудь сервиса на опенсорсе, так обязательно найду кучу мануалов, каждый по отдельности из которых в моем конкретном случае не сработает, готовое решение толком не заведется или не понравится, случится еще какая-нибудь неудобоваримость, и в итоге приходится самому пробиваться к результату.

В этот раз все мануалы были на 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
Tags:
Hubs:
+21
Comments 17
Comments Comments 17

Articles