Пролог. Я долго не решался написать эту статью. Потому как даже не являясь программистом понимаю, что приведенный код может быть проще и изящнее. Но надеюсь что статья поможет тем, кто столкнулся с такой же дилеммой, а может быть и побудит кого — то на написание более достойного скрипта. Итак, в одном городе, в некоторой компании появился джаббер сервер…
Сервис оказался нужным и востребованным, но вот беда, многие пользователи работают удаленно и VPN есть не у всех. Конечно открыть порты наружу не проблема, но так как джаббер привязан к почтовому LDAP, вопрос защиты приобретает критическую степень. Излазив конфиг ejabberd и увидев, что защиты не предусмотрено, я подумал: «А, ерунда какая. Сейчас настроим fail2ban.» И обломался. Ни про ejabberd, ни про openfire, ни про какой другой xmpp, fail2ban был не в курсе. «Фигня вопрос!» — снова подумал я. «Сейчас настроим». И полез смотреть лог ejabberd. И тут сложность задачи встала передо мной в полный рост. Складывалось такое впечатление, что лог сервиса специально создан так, чтобы fail2ban нельзя было на него настроить. Грубо говоря, сообщение о неудачном вводе пароля состоит из четырех строк:
1. =Дата, время====
2. Сообщение о подключении с ip адреса
3. =Дата, время====
4. Сообщение об ошибке.
Да еще в ip адресе в качестве разделителя используются запятые О_о.
А fail2ban анализирует логи по одной строке. Причем в строке должно быть минимум два значения — ip адрес злоумышленника и время. Гугление по запросу «Защита ejabberd» выдало крупицы полезной информации. Есть два модуля которые могут в этой ситуации помочь тут и тут Но! Не освоил я ejabberd настолько, чтобы суметь их установить. Первый требует установки патчей. А второй устанавливается, но в лог ничего не пишет. Видимо тоже необходим патч. В итоге «ниасилил», простите мне мой французский и загрустил.
Однако, если гора не идет к Магомету, то гору к Магомету несут. Напишем скрипт который читает лог джаббера и создает выборку с ошибочными конекшенами. Что я думаю по поводу моего творения я написал в самом начале. А код выглядит так.
#!/bin/bash
cp /dev/null /var/log/ejabberd/tofail.log #Можно заменить логротейтом, если есть необходимость хранить этот лог
log="/var/log/ejabberd/ejabberd.log" #Исходный лог ejabberd
itog="/var/log/ejabberd/tofail.log" #Оптимизированный лог ejabberd
shab='I(.*) : (.*) Failed authentication for w*@w*.w*.w*'
i="0"
cat $log | while read line
do
dan[$i]="$line"
if [[ ${dan[$i]} =~ $shab ]]; then #Если находим соответствие шаблону...
i=`expr $i - 4`
vrem="${dan[$i]}" # ...вычисляем предыдущие
i=`expr $i + 1`
con="${dan[$i]}" # ...две
i=`expr $i + 3`
fai="${dan[$i]}" # ...строки
echo "$vrem $con $fai" >>$itog #Записываем в оптимизированный лог
fi
i=`expr $i + 1`
done
sed -i 's/,/./g' "$itog" #Заменяем все запятые на точки
Что делает скрипт. Просматривает ejabberd.log, при нахождении строки с сообщением о вводе неправильного пароля заносит в переменные предыдущие две строки со временем и ip адресом подключения. После чего все три значения записывает в лог.
После этого необходимо подготовить fail2ban. В /etc/fail2ban/filter.d/ создаем файл ejabberd.conf со следующим содержимым:
# Fail2Ban configuration file
[Definition]
failregex = Accepted connection {{<HOST>}
ignoreregex =
Проверить что фильтр отрабатывает можно командой fail2ban-regex /var/log/ejabberd/tofail.log /etc/fail2ban/filter.d/ejabberd.conf
В jail.cfg записываем
[ejabberd]
enabled = true
port = 5222
filter = ejabberd
action = iptables-allports[name=EJABBERD, protocol=all]
logpath = /var/log/ejabberd/tofail.log
maxretry = 3
Далее. Творение сие задумчиво и работает долго. Чтобы лишний раз не грузить систему, будем запускать скрипт только когда размер лога ejabberd изменится. Поэтому вешаем в crontab скажем файлик filesize.sh с таким содержимым:
#!/bin/bash
logf="/var/log/ejabberd/ejabberd.log"
filesize="/etc/ejabberd/size.txt"
live=`stat -c%s $logf`
cat $filesize |while read line
do
if [ $live -ne $line ]
then
/etc/ejabberd/expres.sh
fi
done
echo `stat -c%s $logf` >$filesize
У меня запускается раз в минуту. Частоту обновления у вас, выбирайте сами.
Вот собственно с такими костылями, джаббер и был выпущен наружу. Неудачные конекшены есть, но пока это сами сотрудники ошибаются при вводе пароля. В ближайшем будущем необходимо будет потестить насколько вся эта система справится с jBrute и jbbl. Любые комментарии по поводу оптимизации кода приму с большой благодарностью и после проверки опубликую.
Автор: Bansher