0

mikrotik

Мой MikroTik – моя цифровая крепость (часть 3)

Статья является продолжением первой и второй частей, посвящённых организации практической безопасности сетей, построенных на оборудовании MikroTik. Ранее были рассмотрены общие рекомендации, безопасность уровней L1, L2 и L3. Настало время показать варианты реализации централизованного логирования. Поехали!

9. Централизованное логирование Rsyslog

Регулярный анализ логов – важная задача в поддержании должного уровня информационной безопасности. Каждый раз заходить на MikroTik-и и просматривать, что же там новенького, с учётом удаления старых записей, совсем неинтересно, поэтому важно собирать всё в едином месте. Со стороны RouterOS это делается просто:

/system logging
add action=remote topics=critical
add action=remote topics=error
add action=remote topics=info
add action=remote topics=warning
/system logging action set 3 remote=10.0.0.10

«3» означает формат отправляемых сообщений Syslof facility daemon (бывает ещё auth, authpriv, cron, daemon, ftp, kern, local0, local1, local2, local3, local4, local5, local6, local7, lpr, mail, news, ntp, syslog, user, uucp), 10.0.0.10 – это адрес лог коллектора. В качестве него будем использовать Rsyslog, системные требования минимальны. Здесь остановимся подробнее и немного отвлечёмся от темы. С учётом того, что сетевая инфраструктура может быть мультивендорная, то, возможно, в качестве первичного коллектора нельзя будет выбрать устройство за пределами вашей LAN: либо не будет необходимых протоколов VPN или служб логирования, либо сложности с маршрутизацией. Поэтому для начала сделаем так:

apt install rsyslog
vi /etc/rsyslog.conf

#provides UDP syslog reception
module(load="imudp")
input(type="imudp" port="514")

if $fromhost-ip == '192.168.1.1' then {
        /var/log/mikrotik.log
		*.*    @192.168.15.29:2000
}

if $fromhost-ip == '192.168.1.14' then {
        /var/log/cisco.log
		*.*    @192.168.15.29:2001
}

В качестве транспортного протокола выбран не шифрованный UDP, порт 514. Сообщения от роутера MikroTik (IP адрес 192.168.1.1) будут сохраняться на коллекторе в файле /var/log/mikrotik.log, а также ретранслироваться по UDP на коллектор второго уровня на порт 2000. Сообщения от роутера, например, Cisco (IP адрес 192.168.1.14) будут сохраняться на коллекторе в файле /var/log/cisco.log, а также ретранслироваться по UDP на коллектор второго уровня на порт 2001. Гонять логи по открытому каналу – плохая идея, ведь по ним можно установить полную карту вашей сети, найти в ней слабые места или даже изъяны в информационной безопасности. Поэтому передачу вложим в закрытый VPN туннель. Особых требований к ресурсам сервера не предъявляются, поэтому для тестов можно использовать самый простой VPS:

Коллектор второго уровня будет собирать логи со всей администрируемой сети и ориентироваться по доменному имени устройства, сохранённого коллектором первого уровня:

vi /etc/rsyslog.conf

module(load="imudp")
input(type="imudp" port="514")
$UDPServerAddress 192.168.15.41

if $source == 'cisco.lan' then {
        /var/log/cisco.log
}

if $source == 'router.lan' then {
        /var/log/mikrotik.log
}

systemctl restart rsyslog

В качестве переменных можно использовать:

  • msg – тело сообщения;
  • hostname – имя хоста, отправившего сообщение;
  • source – алиас hostname (как показано в примере);
  • fromhost – имя хоста, от которого было получено сообщение;
  • fromhost-ip – то же самое, что и fromhost, только всегда ip-адрес;
  • programname – имя программы;
  • syslogfacility – источник лог сообщения в форме цифры;
  • syslogfacility-text – источник лог сообщения в текстовой форме;
  • syslogseverity – уровень важности в цифровом виде;
  • syslogseverity-text – уровень важности в текстовом виде;
  • pri – источник и приоритет в виде числа;
  • pri-text – источник и приоритет в текстовом формате;
  • timegenerated – время, когда сообщение было получено.

Это скелет нашей модели, настало время нарастить его мышцами. Гонять открытые логи даже по шифрованному VPN туннелю тоже не стоит, ведь и его кто-то где-то может прослушивать. Поэтому организуем передачу по TLS протоколу, вместо применяемого ранее UDP. Первым делом подготовим ключи и сертификаты:

apt install gnutls-bin rsyslog-gnutls

Центр сертификации:

certtool --generate-privkey --outfile /var/keys/ca-key.pem
certtool --generate-self-signed --load-privkey /var/keys/ca-key.pem --outfile /var/keys/ca.pem
Common name: ca
The certificate will expire in (days): 3650
Does the certificate belong to an authority? (y/N): y
Will the certificate be used to sign other certificates? (y/N): y
Is the above information ok? (Y/N): y

Клиентский ключ:

certtool --generate-privkey --outfile /var/keys/rslclient-key.pem --bits 2048
We will generate now the certification request ---> TLS CLIENT
Common name: client.log.your_dns_name.ru
Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): N
Is this a TLS web client certificate? (y/N): y
Is this also a TLS web server certificate? (y/N): y

Клиентский сертификат:

certtool --generate-request --load-privkey /var/keys/rslclient-key.pem --outfile /var/keys/request.pem
Common name: client.log.your_dns_name.ru
Does the certificate belong to an authority? (y/N): n
Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): N
Is this a TLS web client certificate? (y/N): y
Is this also a TLS web server certificate? (y/N): y

Подпись клиентского сертификата:

certtool --generate-certificate --load-request /var/keys/request.pem --outfile /var/keys/rslclient-cert.pem --load-ca-certificate /var/keys/ca.pem --load-ca-privkey /var/keys/ca-key.pem
The certificate will expire in (days): 365
Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): N
Is this a TLS web client certificate? (y/N): y
Is this also a TLS web server certificate? (y/N): y
rm /var/keys/request.pem

Серверный ключ (2048 бит нам вполне хватит):

certtool --generate-privkey --outfile /var/keys/rslserver-key.pem --bits 2048

Серверный сертификат:

certtool --generate-request --load-privkey /var/keys/rslserver-key.pem --outfile /var/keys/request.pem
Common name: log.your_dns_name.ru
Enter a dnsName of the subject of the certificate: log.your_dns_name.ru
Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): N
Is this a TLS web client certificate? (y/N): y
Is this also a TLS web server certificate? (y/N): y

Подпись серверного сертификата:

certtool --generate-certificate --load-request /var/keys/request.pem --outfile /var/keys/rslserver-cert.pem --load-ca-certificate /var/keys/ca.pem --load-ca-privkey /var/keys/ca-key.pem
The certificate will expire in (days): 365
Enter a dnsName of the subject of the certificate: log.your_dns_name.ru
Will the certificate be used for signing (DHE and RSA-EXPORT ciphersuites)? (Y/n): N
Is this a TLS web client certificate? (y/N): y
Is this also a TLS web server certificate? (y/N): y
rm /var/keys/request.pem

chmod 644 /var/keys/*
chmod 400 /var/keys/ca-key.pem

Правим конфиг для первичного коллектора. Принимает сообщения от роутеров так же по UDP (может оказаться единственным универсальным решением для всего зоопарка), сохраняем в локальные файлы mikrotik.log и cisco.log и ретранслируем уже по TLS за пределы охраняемого нами периметра на сервер log.your_dns_name.ru:

vi /etc/rsyslog.conf

module(load="imudp")
input(type="imudp" port="514")

$DefaultNetstreamDriver gtls
$DefaultNetstreamDriverCAFile /var/keys/ca.pem
$DefaultNetstreamDriverCertFile /var/keys/rslclient-cert.pem
$DefaultNetstreamDriverKeyFile /var/keys/rslclient-key.pem
$ActionSendStreamDriverPermittedPeer log. your_dns_name.ru
$ActionSendStreamDriverMode 1
$ActionSendStreamDriverAuthMode x509/name

if $fromhost-ip == '192.168.1.1' then {
 /var/log/mikrotik.log
*.* @@log.your_dns_name.ru:514
}

if $fromhost-ip == '192.168.1.14' then {
/var/log/cisco.log
*.* @@log.your_dns_name.ru:514
}

Вносим изменения на вторичном сервере логирования log.your_dns_name.ru:

vi /etc/rsyslog.conf	

$ModLoad imtcp
$DefaultNetstreamDriver gtls
$DefaultNetstreamDriverCAFile /var/keys/ca.pem
$DefaultNetstreamDriverCertFile /var/keys/rslserver-cert.pem
$DefaultNetstreamDriverKeyFile /var/keys/rslserver-key.pem

$InputTCPServerStreamDriverAuthMode anon
$InputTCPServerStreamDriverMode 1
$ActionSendStreamDriverAuthMode x509/name
$ActionSendStreamDriverPermittedPeer *
$ActionSendStreamDriverMode 1
$InputTCPServerRun 514
$MaxOpenFiles 2048

if $source == 'cisco.lan' then {
        /var/log/cisco.log
}

if $source == 'router.lan' then {
        /var/log/mikrotik.log
}

systemctl restart rsyslog

Здесь уже, возможно, понадобится траблшутинг для обоих коллекторов. Для этого можно воспользоваться анализатором сетевых пакетов tcpdump, попробовать подключиться в нашему серверу извне по TLS, а также просмотреть запущенные демоны и прослушиваемые ими сетевые интерфейсы и порты:

tcpdump -i eth0 -n "dst port 514"
openssl s_client -connect graylog.your_dns_name.ru:514
netstat –tlnp

Подведём промежуточный итог. Программное обеспечение настроили. Логи собираем в два этапа. Коллектор первого уровня работает внутри защищаемого периметра, коллектор второго уровня отвечает за всю сеть в целом. Логи просматриваем примерно так:

cat /var/log/mikrotik.log | grep "login failure"
Apr 20 18:21:18 192.168.15.13 system,error,critical login failure for user admin from 192.168.15.5 via winbox

Результат есть, но админу работать так не хочется, поэтому пойдём ещё дальше и прикрутим в нашу историю красивый, удобный и функциональный интерфейс, а именно развернём решение на базе Graylog.

10. Централизованное логирование Graylog

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

Самым простым сервером здесь не обойдёшься, рекомендуемый минимум выйдет 1828 рублей в месяц. Важно отметить, что для развёртывания необходимо использовать архитектуру процессора AMD64:

Приступим к установке и настройке. База данных:

apt install apt-transport-https openjdk-11-jre-headless uuid-runtime pwgen dirmngr gnupg wget
wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | apt-key add -
echo "deb http://repo.mongodb.org/apt/debian buster/mongodb-org/4.2 main" | tee /etc/apt/sources.list.d/mongodb-org-4.2.list
apt update
apt install -y mongodb-org
systemctl restart mongod

Elasticsearch:

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -
echo "deb https://artifacts.elastic.co/packages/oss-7.x/apt stable main" | tee -a /etc/apt/sources.list.d/elastic-7.x.list
apt update && apt install elasticsearch-oss
tee -a /etc/elasticsearch/elasticsearch.yml > /dev/null <<EOT
cluster.name: graylog
action.auto_create_index: false
EOT
systemctl restart elasticsearch

Graylog:

wget https://packages.graylog2.org/repo/packages/graylog-4.0-repository_latest.deb
dpkg -i graylog-4.0-repository_latest.deb
apt update
apt install graylog-server graylog-enterprise-plugins graylog-integrations-plugins graylog-enterprise-integrations-plugins
vi /etc/graylog/server/server.conf

password_secret	= verySTRONGsecret!! 	#pwgen -N 1 -s 96
root_username = RUVDS
root_password_sha2 = 2ce2e630e2…..a81521d0f77efa3fe9bc017
#echo -n verySTRONGpassword!! | shasum -a 256
http_bind_address = our_IP_address:9000
http_publish_uri = https://graylog.your_dns_name.ru:9000/
root_timezone = Europe/Moscow
http_enable_tls = true
http_tls_cert_file = /var/keys/graylog_cert.pem
http_tls_key_file = /var/keys/graylog_pkcs8.pem

Генерируем ключи для доступа к web интерфейсу по TLS:

vi openssl-graylog.cnf

[req]

distinguished_name = req_distinguished_name x509_extensions = v3_req prompt = no

[req_distinguished_name]

C = US ST = Some-State L = Some-City O = My Company OU = My Division CN = graylog. your_dns_name.ru

[v3_req]

extendedKeyUsage = serverAuth subjectAltName = @alt_names

[alt_names]

IP.1 = our_IP_address DNS.1 = graylog. your_dns_name.ru openssl req -x509 -days 365 -nodes -newkey rsa:2048 -config /root/openssl-graylog.cnf -keyout /var/keys/graylog_pkcs5.pem -out /var/keys/graylog_cert.pem openssl pkcs8 –in /var/keys/graylog_pkcs5.pem -topk8 -nocrypt -out /var/keys/graylog_pkcs8.pem chmod 644 /var/keys/graylog_pkcs8.pem cp -a “${JAVA_HOME}/jre/lib/security/cacerts” /vat/keys/cacerts.jks cp -a /usr/share/elasticsearch/jdk/lib/security/cacerts /var/keys/cacerts.jks keytool -importcert -keystore /var/keys/cacerts.jks -storepass changeit -alias graylog-self-signed -file /var/keys/graylog_cert.pem keytool -keystore /var/keys/cacerts.jks -storepass changeit -list | grep graylog-self-signed -A1 vi /etc/default/graylog-server GRAYLOG_SERVER_JAVA_OPTS=”… -Djavax.net.ssl.trustStore=/var/keys/cacerts.jks” systemctl restart graylog-server
Если всё прошло корректно, то можно будет увидеть такой вот web интерфейс, протокол HTTPS (graylog.your_dns_name.ru:9000):

На сайте получаем бесплатную лицензию и вставляем ее в своё приложение (this Graylog cluster ID is 674E8B34-224…):

Чтобы получать сообщения от первичного коллектора по UDP, необходимо настроить вводы нашего Graylog, примерно так:

У нас уже всё готово для общения по TLS, поэтому просто выбираем соответствующий режим и заполняем необходимые поля. Как совет, не пытайтесь перенести веб-морду на 443 порт (ни NAT-ом, ни с помощью прокси), столкнётесь с проблемами на уровне API. В результате просматривать логи стало гораздо приятнее:

В конечном итоге мы рекомендуем вкладывать получение сообщений от первичного коллектора по TLS в VPN канал, тогда открытый TCP порт не будет светиться в интернет, и не будет сохраняться флуд, вроде такого:

Здесь нужно дополнительно рассказать не только о важности и способе, хранении и анализе логов, но так же и о такой вещи, как развёртывание «черного ящика», который будет собирать информацию обо всех сетевых соединениях. Это поможет восстановить полную хронологию событий, в случае компрометации системы. Мы рекомендуем использовать для этого протокол netflow.

Активируем его в RouterOS и указываем IP адрес коллектора:

/ip traffic-flow set enabled=yes interfaces=bridge
/ip traffic-flow target add dst-address=192.168.15.1 port=1234 version=5

Настраиваем принимающую сторону – netflow коллектор:

mkdir /var/log/flow
vi /etc/flow-tools/flow-capture.conf

-w /var/log/flow -n 275 -N 3 192.168.15.1/0/1234

systemctl restart flow-capture

Просмотрим получаемую статистику:

flow-cat /var/log/flow/2020/2020-10/*/ft-* | flow-stat
Total Flows                     : 324
Total Octets                    : 59866191
Total Packets                   : 42896
Total Time (1/1000 secs) (flows): 3029440
Duration of data  (realtime)    : 290
Duration of data (1/1000 secs)  : 340200
Average flow time (1/1000 secs) : 9350.1230
Average packet size (octets)    : 1395.6124
Average flow size (octets)      : 184772.2031
Average packets per flow        : 132.3951
Average flows / second (flow)   : 0.9529
Average flows / second (real)   : 1.1172
Average Kbits / second (flow)   : 1408.6162
Average Kbits / second (real)   : 1651.4812

Непосредственно результаты накопления можно увидеть таким образом:

flow-cat /var/log/flow/2020/2020-10/2020-10-31/ft-v05.2020-10-31.122757+0300 | flow-export -f 2
1604136477,821825000,103238050,192.168.15.5,1,60,103221520,103221520,0,0,17.248.150.106,192.168.2.254,192.168.2.254,11,10,443,65448,6,104,18,0,0,0,0
1604136477,821825000,103238050,192.168.15.5,17,9395,103219730,103222300,0,0,17.248.150.51,192.168.2.254,192.168.2.254,11,10,443,65446,6,104,18,0,0,0,0
1604136480,821818000,103241050,192.168.15.5,20,8786,103221270,103224760,0,0,17.248.15

Сохраняемые объёмы выходят небольшими. Своего рода биллинг сетевых соединений, проходящих через маршрутизатор.

11. Заключение

На этом все. В нашем распоряжении полноценный графический анализатор логов, который уже можно стилизовать под свои задачи, вкусы и предпочтения. Функционала для этого предостаточно: Search, Streams, Alerts, Dashboards и Enterprise функции. Настало время добавить в нашу сеть полноценную систему обнаружения вторжений, но про это в следующей и завершающей части.

P/S
Часть 1. Настройка оборудования и вопросы безопасности L1 и L2 уровней
Часть 2. Настройка протокола Dot1X и работа Firewall
Часть 3. Варианты реализации централизованного логирования
Часть 4. Развертывание IDS и ее интеграция в инфраструктуру RouterOS

Свежие комментарии

Подписка

Лучшие статьи


Fatal error: Uncaught Error: Call to a member function have_posts() on null in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php:398 Stack trace: #0 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/widget.php(257): fox56_blog_grid(NULL, Array) #1 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/widgets/latest-posts/register.php(33): include('/home/host18670...') #2 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/class-wp-widget.php(394): Wi_Widget_Latest_Posts->widget(Array, Array) #3 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/widgets.php(845): WP_Widget->display_callback(Array, Array) #4 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(418): dynamic_sidebar('sidebar') #5 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(136): fox56_single_sidebar() #6 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/single.php(7): fox56_single_inner() #7 /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/single.php(23): fox56_single() #8 /home/host1867038/the-devops.ru/htdocs/www/wp-includes/template-loader.php(106): include('/home/host18670...') #9 /home/host1867038/the-devops.ru/htdocs/www/wp-blog-header.php(19): require_once('/home/host18670...') #10 /home/host1867038/the-devops.ru/htdocs/www/index.php(17): require('/home/host18670...') #11 {main} thrown in /home/host1867038/the-devops.ru/htdocs/www/wp-content/themes/fox/inc/blog.php on line 398