Сервер в кармане, или просто о сложном!

главная - Статьи - Linux, FreeBSD



Настройка fail2ban в CentOS

Дата обновления: 06.04.2021

Теги: fail2ban Облако Linux

fail2ban мониторит лог файлы (например, /var/log/secure и др. по вашему желанию) и при появлении в логах заранее настроенных событий (например, неверный пароль по ssh) блокирует удаленный компьютер, внося в цепочку iptables fail2ban-SSH IP этого удаленного компьютера. Время блокирования (вплоть до навсегда), количество неудачных попыток ввода пароля и другие параметры настраиваются вами на основании уже готовых шаблонов. Почти никаких шаманств.

Пример того, как потом будет ))

Вот маленький пример, в котором если кто-то в течении 1 часа (3600) неверно ввел 5 раз пароль при подключении по ssh (если, конечно, вы не настроили авторизацию по ключу ssh), то его IP будет блокирован на 5 часов (18000 сек):

[ssh-iptables]

enabled = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
           sendmail-whois[name=SSH, dest=you@example.com, sender=fail2ban@example.com, sendername="Fail2Ban"]
logpath  = /var/log/secure

# in 1 hour
findtime = 3600

maxretry = 5

# time, sec
bantime = 18000

Обратите внимание на enabled = true. По умолчанию, fail2ban не банит все сервисы подряд, вызывая у вас головную боль. Только когда вы захотите контролировать что-то, вы это включаете.

Если предположить, что в нашем примере кто-то с IP 192.168.55.172 решил подобрать пароль на нашем сервере, то после 5 попыток подбора пароля fail2ban добавит его IP (192.168.55.172) в цепочку fail2ban-SSH:

> iptables -L
...
Chain fail2ban-SSH (1 references)
target prot opt source destination
REJECT all -- 192.168.55.172 anywhere reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere

Все, счастье хулигана закончилось.

Как это все сделать? Как всегда, ничего особо сложного.

Установка fail2ban

yum install fail2ban

Если не удалось, добавьте репозиторий EPEL:

rpm -ivh http://download.fedoraproject.org/pub/epel/6/$(arch)/epel-release-6-8.noarch.rpm

и повторите yum install fail2ban.

Настройка fail2ban и борьба с подбором пароля по ssh

Правила для fail2ban хранятся в файле /etc/fail2ban/jail.conf, но если вы его откроете, то в самом его верху можно прочитать:

# YOU SHOULD NOT MODIFY THIS FILE.
#
# It will probably be overwitten or improved in a distribution update.
#
# Provide customizations in a jail.local file or a jail.d/customisation.local.

Т.е. этот файл может быть перезаписан при обновлении и все наши труды исчезнут. Предлагается использовать файл jail.local или jail.d/customisation.local. Файл /etc/fail2ban/jail.conf уже содержит в себе шаблоны для основных ситуаций, поэтому мы просто скопируем его в файл /etc/fail2ban/jail.local и будем по мере необходимости включать функционал.

# cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Для примера настроим проверку подбора пароля ssh (из примера в начале статьи). Для этого в файле /etc/fail2ban/jail.local найдем секцию [ssh-iptables] и установим параметры сработки правила и срок блокировки злоумышленника ))

# nano /etc/fail2ban/jail.local

[ssh-iptables]
enabled  = true
filter   = sshd
action   = iptables[name=SSH, port=ssh, protocol=tcp]
           sendmail-whois[name=SSH, dest=you@example.com, sender=fail2ban@example.com, sendername="Fail2Ban"]
logpath  = /var/log/secure
returntype = DROP

# in 1 hour
findtime = 3600

maxretry = 5

# time, sec
bantime = 300

На что можно обратить внимание:
enabled = true. Правило включено.
filter = sshd. Будет применен фильтр /etc/fail2ban/filter.d/sshd.conf.
returntype = DROP. Iptables может REJECT или DROP. Reject - это вежливый drop, с уведомлением удаленной стороне, а DROP - тупо отбрасывание пакетов. По-умолчанию включен режим "REJECT --reject-with icmp-port-unreachable".

В данном случае отлаживать вряд-ли что-то надо, т.к. это предустановленное правило, к тому же максимально стандартное. Поэтому нам просто надо убедиться, что в файл /var/log/secure отражаются успешные и неудачные попытки логина по ssh (просто просмотрите этот файл - ваш заход тоже там отражен). Если все ок, сохраняем изменения и перезапускаем fail2ban:

# service fail2ban restart

Перед тем, как проверять работу блокировки, не заблокируйте сами себя, тестируя работу. Лучше попытаться несколько раз неуспешно залогиниться с другого компьютера, чтобы в логе отразились эти попытки (я немного сократил лог, чтобы уместился по ширине):

...
Failed password for bigmama277 from 192.168.55.172 port 56803 ssh2
password check failed for user (bigmama277)
Failed password for bigmama277 from 192.168.55.172 port 56803 ssh2
...

Можно попробовать проверить, заблокирован ли 192.168.55.172:

# iptables -L

В цепочке fail2ban-SSH должна быть запись о нашем неудачном хакере:

Chain fail2ban-SSH (1 references)
target prot opt source destination
REJECT all -- 192.168.55.172 anywhere reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere

И повторная попытка соединения с 192.168.55.172 будет невозможна до истечения срока ограничения (в нашем случае 5 мин).

Если мы решим снять блокировку для этого ip, это можно сделать командой:

# fail2ban-client set ssh-iptables unbanip 192.168.55.172

Если вы хотите посмотреть, как именно сравниваются записи в лог файле, откройте файл /etc/fail2ban/filter.d/sshd.conf. В нем указаны регулярные выражения, на соответствие которым проверяется лог файл /var/log/secure.

Пример 2: fail2ban и Owncloud

Попробуем немного усложнить задачу и будем отслеживать попытки подбора пароля к сервису Owncloud (куда уж в наше время без своего облака???).

Первым делом, добавляем в /etc/fail2ban/jail.local новую секцию [owncloud]:

# nano /etc/fail2ban/jail.local

[owncloud]
enabled = true

# define filter in /etc/fail2ban/filter.d/***.conf
filter = owncloud

action = iptables[name=Owncloud, port=https, protocol=tcp]

logpath = /var/log/owncloud.log

bantime = 18000
findtime = 3600
maxretry = 3

Директива filter = owncloud отсылает fail2ban к файлу-фильтру /etc/fail2ban/filter.d/owncloud.conf, который мы создадим чуть ниже.

Спойлер: логи owncloud

По-умолчанию, owncloud сохраняет логи в своей директории в файл /var/www/html/owncloud/data/owncloud.log. По мне, логи лучше держать в директории /var/logs/, поэтому я перенастроил Owncloud на хранение логов в /var/log/owncloud.log:

# touch /var/log/owncloud.log
# chown apache:apache /var/log/owncloud.log

Если у вас веб-сервер работает от имени другого пользователя, замените apache:apache на ваш вариант.

# nano /var/www/html/owncloud/config/config.php

'logfile' => '/var/log/owncloud.log',
'logtimezone' => 'Europe/Moscow'

Запомните опцию logtimezone - она еще встретится на нашем пути... Я перезапустил httpd (возможно, это не требуется, чтобы изменения в конфиге owncloud применились):

# service httpd restart

Убедитесь, что в файл /var/log/owncloud.log стали записываться данные. Считаем, что все ок.

Создадим файл анализа лог-файла /etc/fail2ban/filter.d/owncloud.conf, с помощью которого fail2ban поймет, что кто-то ломиться через парадную дверь. Возможно, этот файл уже существует. nano создаст новый файл, если он не существовал раньше.

# nano /etc/fail2ban/filter.d/owncloud.conf

[Definition]

failregex = {"app":"core","message":"Login failed: '.*' (Remote IP: '', X-Forwarded-For: '.*')","level":2,"time":".*"}
              ^{"reqId":"[0-9a-zA-Z]*","remoteAddr":"<HOST>","app":"core","message":"Login failed: '.*' (Remote IP: '.*s*$

ignoreregex =

В версии 8 чуть изменился формат лога - мы можем просто добавить новый формат (я сделал так) или отредактировать старый. Формат записи с ^ или с { на скорость не влияет - можно и так, и так.

Мы почти у цели.

Формат лог-файла owncloud должен соответствовать формату парсинга fail2ban. Это касается в том числе формата даты событий в логе owncloud!

Fail2ban очень чувствительно отнесся к несоответствию временных зон в системном времени (команда date, например) и в настройках owncloud, который пишет в лог /var/log/owncloud.log о попытках ввода неверного пароля. Это несоответствие привело к тому, что абсолютно верно настроенные правила фильтрации не срабатывали, а в лог fail2ban шли записи вида:

fail2ban.filter.datedetector[17573]: DEBUG Matched time template ISO 8601
fail2ban.filter.datedetector[17573]: DEBUG Got time using template ISO 8601
fail2ban.filter [17573]: DEBUG Processing line with time:1415178183.0 and ip:192.168.22.133
fail2ban.filter [17573]: DEBUG Ignore line since time 1415178183.0 < 1415188983.73 - 3600

Т.е. вроде бы попытку ловит (ip верно выделяет), но не добавляет этот ip в iptables! Это были кошмарные, но познавательные для меня 3 часа поисков... Делюсь бесплатно ;) Поэтому время на хосте должно быть настроено правильно, с правильно указанной временной зоной. И такая же зона должна быть указана в настройках owncloud. Справедливости ради стоит отметить, что для owncloud точное и правильное время вообще очень важно. Но это немного другая тема.

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

# service fail2ban restart

Ошибок быть не должно!

Проверяем созданные цепочки iptables:

# iptables -L

...
Chain fail2ban-Owncloud (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere

Chain fail2ban-SSH (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere

fail2ban должен подготовить цепочку fail2ban-Owncloud. Если нет, надо смотреть, что с ним не так.

Отладка fail2ban

Парсер fail2ban основан на питоне и по идее, обычные регулярки здесь прокатят. Но! Не всегда, к сожалению. Проверить, сработает ли fail2ban на определенную строку, можно так:

# fail2ban-regex /var/log/owncloud.log /etc/fail2ban/filter.d/owncloud.conf
# fail2ban-regex /var/log/owncloud.log "ваша_регулярка_из_owncloud.conf"
# fail2ban-regex "произвольная строка (а не только лог-файл)" "произвольная регулярка"

На выходе должны получить что-то вроде: Lines: 16 lines, 0 ignored, 16 matched, 0 missed. Добивайтесь, чтобы были matches (совпадения).

Такс, идем дальше. Терпение писать почти закончилось, но и осталось немного. Пробуем залогинится в owncloud с заведомо неверным паролем и проверяем, что в логе это отразилось:

...
{"app":"core","message":"Login failed: 'vasya' (Remote IP: '192.168.22.133', X-Forwarded-For: '')...
...

И вот сейчас, после моих мучений по написанию, а ваших - по чтению, мы подошли к моменту, когда все должно работать. Наверное )) Если сейчас бана по ip нет, совершаем несколько попыток подобрать пароль owncloud.

# iptables -L

...
Chain fail2ban-Owncloud (1 references)
target prot opt source destination
REJECT all -- 192.168.22.133 anywhere reject-with icmp-port-unreachable RETURN all -- anywhere anywhere

Chain fail2ban-SSH (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere

Вроде все ок!

 

 

Возможные грабли с SELinux

Вполне возможна ситуация, когда включенный SELinux не дает доступ fail2ban к логу owncloud, особенно когда путь до лога был изменен, или файл лога мы создавали сами (а не в процессе авто установки). Можно попробовать временно отключить SELinux и проверить работу. Если проблема решена, ВКЛЮЧИТЬ SELinux обратно и решать проблему примерно как описано ниже. Если проблема не решена, ВКЛЮЧИТЬ SELinux и думать, что еще может мешать ))

Для примера:

# ls -Z /var/www/html/owncloud/index.php
-rw-r-----. root apache system_u:object_r:httpd_sys_content_t:s0 /var/www/html/owncloud/index.php

Файл /var/log/owncloud.log, который мы создали:

# ls -Z /var/log/owncloud.log
-rw-r-----. apache apache unconfined_u:object_r:var_log_t:s0 /var/log/owncloud.log

Выполняем:

# chmod 640 /var/log/owncloud.log
# chown apache:apache /var/log/owncloud.log
# semanage fcontext -a -t httpd_log_t "/var/log/owncloud.log"
# restorecon -Rv /var/log/owncloud.log
   restorecon reset /var/log/owncloud.log context unconfined_u:object_r:var_log_t:s0->unconfined_u:object_r:httpd_log_t:s0
# service fail2ban restart

Вообще, SELinux вроде бы и полезная вещь, но порой можно поспорить, так ли он полезен. Например, на хабре пробовали проверить, насколько SELinux полезен. Просмотрите статью по ссылке по диагонали, хотя бы.

 

 

ВСЕ РАБОТАЕТ?

# chkconfig fail2ban on

Все.



22.09.2016 11:41 Munk
Немного актуализируйте failregex:
{"reqId":".*","remoteAddr":"<HOST>","app":"core","message":"Login failed: .*","level":2,"time":".*"}
22.09.2016 11:41 Munk
А вообще - спасибо, все достаточно подробно.

Авторизуйтесь для добавления комментариев!


    забыли пароль?    новый пользователь?