Добрый день.
В предыдущей публикации я рассказывал как, легко и непринужденно, можно настроить сбор метаданных сетевого трафика на маршрутизаторах Микротик в базу данных.
Теперь настало время научить наш сервер делать элементарный анализ получаемых данных и отправлять команды обратно.
Цель: Динамическое управление правилами фаервола Микротик для пресечения сетевых атак с перебором пароля.
Средства: Свежий дистрибутив Linux с rsyslogd v8, crond, СУБД mariadb и собственно сам маршрутизатор Микротик.
Механика: С помощью назначенного задания, выполняется SQL запрос в БД с накопленными и пополняемыми данными трафика и возвращает список исходящих ip-адресов, запускаемый кроном bash скрипт формирует команды Микротика и с помощью ssh соединения, пополняет список адресов для имеющихся правил блокировки.
Речь пойдет о защите открытых TCP портов. Это могут быть входящие на Микротик и пробрасываемые в локальную сеть порты.
Для начала обозначим где могут быть слабые места:
- Управляющие протоколы маршрутизатора ssh, telnet, web, winbox
- Почтовые службы smtp, pop, imap
- Любые веб сервисы предоставляемые наружу
- Удаленный рабочий стол MS RDP, VNC и т.д.
- Что-либо другое, на ваше усмотрение
Пишем запрос SQL для поиска брутфорсера
В нашей организации есть терминальные серверы открытые наружу по не приоритетным портам.
В DNAT Микротика я включил логгирование необходимых правил добавив префикс RDP_DNAT. По этому префиксу мы и будем производить поиск:
MariaDB [traflog]> select src,dport,count(dport) as 'попытки подключения' from traffic where datetime>now() - interval 1 day and logpref='RDP_DNAT' group by src having count(dport)>50;
+-----------------+-------+---------------------------------------+
| src | dport | попытки подключения |
+-----------------+-------+---------------------------------------+
| 185.156.177.58 | 12345 | 118 |
| 185.156.177.59 | 12345 | 267 |
| 193.238.46.12 | 12345 | 318 |
| 193.238.46.13 | 12345 | 319 |
| 193.238.46.99 | 12345 | 342 |
| 194.113.106.150 | 12345 | 67 |
| 194.113.106.152 | 12345 | 167 |
| 194.113.106.153 | 12345 | 190 |
| 194.113.106.154 | 12345 | 192 |
| 194.113.106.155 | 12345 | 190 |
| 194.113.106.156 | 12345 | 216 |
| 194.113.106.158 | 12345 | 124 |
+-----------------+-------+---------------------------------------+
12 rows in set (0.06 sec)
Этот запрос показывает ip адрес (с которого идет атака), порт на который происходит подключение (номер порта изменен) и количество попыток подключения, с предварительной группировкой по src и выборкой строк, с количеством попыток более 50 за прошедшие, от текущего момента, сутки.
В моем случае, эти адреса можно смело банить, так как количество подключений у «хороших» клиентов меньше, не более 5-10 в сутки с одного ip.
Запрос работает нормально, быстро, но он длинноват. Для дальнейшего использования я предлагаю сделать представление (view), что бы в будущем меньше копипастить:
MariaDB [traflog]> create or replace view rdp_brute_day as select src, dport, count(dport) from traffic where datetime>now() - interval 1 day and logpref='RDP_DNAT' group by src having count(dport)>50;
Query OK, 0 rows affected (0.23 sec)
Проверим как работает вьюшка:
MariaDB [traflog]> select src,count(dport) from rdp_brute_day;
+----------------+--------------+
| src | count(dport) |
+----------------+--------------+
| 185.156.177.58 | 11 |
+----------------+--------------+
1 row in set (0.09 sec)
Отлично.
Добавляем пользователя Микротик с авторизацией по ключу dsa
В консоли linux генерируем ключ dsa, под пользователем, от имени которого будет запускаться назначенное задание, я делал из под root:
root@monix:~# ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/root/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_dsa.
Your public key has been saved in /root/.ssh/id_dsa.pub.
...
Passphrase назначать не надо. Публичный ключ /root/.ssh/id_dsa.pub копируем на Микротик любым доступным способом. Я вывел его командой cat, скопировал текст из окна putty в текстовый файл, сохранился и перетащил в окно winbox files.
Не знаю почему, но при выполнении следующих операций через интерфейс winbox что-то пошло не так. При подключении с сервера через ssh, Микротик запрашивал у меня еще и пароль. После того, как удалил созданного пользователя и выполнил все операции через консоль, подключение по dsa заработало. Делал примерно, как описано тут.
В общем я получил желанный вход без пароля по ключу dsa и выполнил проверочную команду:
root@monix:/# ssh rsyslogger@192.168.0.230 /system resource print
uptime: 2w1d5h22m43s
version: 6.43.2 (stable)
...
Хорошо.
Пишем bash скрипт
Скрипт получился не сложный:
mikrotik_cmd_list(){
brute_src_list=$(mysql --skip-column-names traflog -e 'select src from rdp_brute_day')
for src in $brute_src_list
do
echo "ip firewall address-list add address=$src list=rdp_banlist timeout=1d"
done
}
mikrotik_cmd_list | ssh rsyslogger@192.168.0.230
Для того чтобы передать все команды в рамках одного ssh соединения, мне понадобилось описать функцию mikrotik_cmd_list(), в которой сначала выполняется запрос с сохранением ip адресов в переменную brute_src_list, далее в цикле эта переменная последовательно формирует команды для Микротика. После вызова функции, вывод направляется через трубу в ssh.
Не забываем закрыть права доступа к скрипту всем кроме root и делаем файл исполняемым.
Команда которую генерирует скрипт, добавит ip адрес в rdp_banlist на 1 день, по истечении этого времени он сам удалится из списка. Если хотите оставить его навсегда, уберите опцию timeout.
Добавляем правило в фаервол
Я придумал два варианта, как использовать список rdp_banlist:
Вариант первый: добавить список rdp_banlist с восклицательным знаком в правила NAT имеющие префикс RDP_DNAT.
add action=dst-nat chain=dstnat comment="..." dst-address=1.2.3.4 dst-port=12345 log=yes log-prefix=RDP_DNAT protocol=tcp src-address-list=
!rdp_banlist to-addresses=192.168.200.181 to-ports=3389
Примерно так. То есть днатим все, кроме того, что есть в rdp_banlist.
В этом варианте есть плюс и минус.
Плюс в том, что подключения тут же прекратятся.
Минус в том, что больше этот ip не будет попадать в БД traflog и по истечении суток, когда пройдет таймаут хранения в блэклисте, он снова начнет гадить.
Вариант второй: добавить список rdp_banlist с восклицательным знаком в правило firewall цепочки forward, где мы разрешаем прохождение трафика на TCP 3389, аналогично тому, как это сделали в первом способе.
add action=accept chain=forward comment="..." dst-port=3389 log=yes log-prefix=ACCEPT_RDP protocol=tcp src-address-list=
!rdp_banlist to-ports=3389
Примерно так. Разрешаем все, кроме того, что в банлисте.
Тут тоже плюс и минус.
Плюс. В БД traflog будут продолжать сыпаться логи с префиксом RDP_DNAT, по которым мы определяем признак атаки. В результате, когда закончится таймаут бана определенного хоста, продолжающего попытки брутфорса, он вновь будет добавлен в банлист после очередного запуска назначенного задания.
Минус в том, что он продолжает гадить в таблицу DSTNAT, каждым своим подключением создавая новую запись, пусть и временную.
В общем решение за вами, я выбрал оба :) (на самом деле, в таком случае работает только первый), так как второй у меня был включен раньше и механика там была другая, основанная на последовательной записи в списки stage1, stage2, stage3, banlist… ну вы поняли. Старый и не очень надежный фокус, может легко забанить «хороших» клиентов и при этом пропустить «плохих», вежливо расчитавших таймаут stage1.
Назначенное задание crontab
Осталось добавить назначенное задание в кронтаб:
root@monix:/root# echo '12 * * * * root /usr/share/traflog/scripts/rdp_brute.sh >/dev/null 2>&1' >> /etc/crontab
Такая запись будет запускать скрипт каждый час в 12 минут.
Надо признаться, я только сегодня закончил работу над этой механикой и с большой долей вероятности, что-то может пойти не так. По обстоятельствам буду дополнять и исправлять ошибки. Хочется пить спать спокойно в новогодние праздники, потому и тороплюсь закончить.
Вот пожалуй и все.
Всем спасибо за внимание и с наступающим Новым Годом!
Список литературы:
Документация по mysql
Документация по Mikrotik firewall
Спасибо Андрею Смирнову за статью про подключение по ключу dsa.
Автор: sergio_sd