И снова fail2ban — на этот раз охраняем ProFTP и Dovecot

Собственно, это уже совсем … скучно. И тем не менее…

Просмотр логов показывает, что и в ftp-сервер мой постоянно кто-то пытается попасть «мимо кассы»:

Янв 19 07:54:36 dmitrykhn.homedns.org proftpd[27832] dmitrykhn.homedns.org (82.213.28.12[82.213.28.12]): USER service: no such user found from 82.213.28.12 [82.213.28.12] to 192.168.1.115:21
Янв 19 07:54:37 dmitrykhn.homedns.org proftpd[27832] dmitrykhn.homedns.org (82.213.28.12[82.213.28.12]): USER service: no such user found from 82.213.28.12 [82.213.28.12] to 192.168.1.115:21

…и в почтовый сервер тоже:

Feb  1 00:10:12 dmitrykhn dovecot: pop3-login: Disconnected (auth failed, 1 attempts): user=, method=PLAIN, rip=59.124.32.168, lip=192.168.1.115
Feb  1 00:10:19 dmitrykhn dovecot: pop3-login: Disconnected (auth failed, 1 attempts): user=, method=PLAIN, rip=210.202.39.205, lip=192.168.1.115

Что же тогда, сидеть и ждать? Решил я воспользоваться все тем же fail2ban — он и так уже трудится, вот пусть теперь и тут еще постарается…

С ProFTP, как мне казалось, все будет просто — соответствующий фильтр в наборе fail2ban имелся. Взял я программу fail2ban-regex и скормил ей файл протокола /var/log/proftpd/proftpd.log в паре с данным фильтром (как пользоваться fail2ban-regex я уже писал тут). Совпадения нашлись, и почти все было бы хорошо, если бы не одно «но». Программа fail2ban-regex сказала, что моя дата не подходит ни под один из известных ей шаблонов. Как я понял, единственное, что могло смутить fail2ban-regex в моей дате, так это тот язык, на котором она была выведена. То есть, «пришла беда, откуда не ждали». То ли авторы дистрибутива Mandriva, используемого мной, то ли авторы ProFTP, решили сделать мне «хорошо» — раз уж выбрал я русский язык, то пусть и протокол будет на русском. В принципе, оно конечно хорошо — понятнее. Даже не смотря на то, что русского того там в протоколе  — аж целых три буквы в имени месяца!..

В принципе, программа ProFTP (как я понял) использует тот язык, который в момент ее запуска указан в системе в качестве системного. Что ж, подумал я, если в момент запуска ProFTP указать, что системный язык английский, то есть шанс, что и сообщения в лог пойдут тоже на нем. Сказано — сделано. Пошел я в папку /etc/init.d и нашел в ней скрипт запуска сервера ProFTP (файл proftpd). Открыл его в редакторе и нашел в нем следующую строку:

         daemon "proftpd >/dev/null 2>&1"

и НАД ней добавил (чтоб долго не угадывать) следующие три:

        export LC_MESSAGES="en_US.UTF-8"
        export LC_ALL="en_US.UTF-8"
        export LANG="en_US.UTF-8"

Должен заметить, что строка daemon «proftpd >/dev/null 2>&1» присутствует в скрипте два раза. Как следствие и свои строки с назначением переменным LC_MESSAGES, LC_ALL и LANG значения en_US.UTF-8 я тоже добавил два раза (в обоих местах). Перезапустил ProFTP, заглянул в лог — красота, сообщения в нем снова на «родном английском»! Что ж, пол дела сделано.

Вторая половина — включить в fail2ban соответствующий фильтр (proftpd). Для этого я открыл в редакторе файл /etc/fail2ban/jail.conf и сделал в нем следующее — нашел в нем секцию про указанный фильтр и изменил ее, после чего она стала выглядеть следующим образом:

[proftpd-iptables]

enabled  = true
filter   = proftpd
action   = iptables[name=ProFTPD, port=ftp, protocol=tcp]
#           sendmail-whois[name=ProFTPD, dest=you@mail.com]
logpath  = /var/log/proftpd/proftpd.log
maxretry = 4

Собственно, изменений было аж три (выделены красным цветом). Смена в поле enabled значения с false на true включила использование фильтра. Диез (#) превратил строку с командой отправки почтового сообщения в комментарий (ну не надо мне эти письма!). Ну и в поле maxretry я поставил 4 — именно после стольких неудачных попыток нарушитель будет забанен.

А с  dovecot вопрос решился с помощью Google. Нашел я в нем ссылку на вот такую чудную страницу:

http://wiki.dovecot.org/HowTo/Fail2Ban

Просто «тупо» повторил описанное на ней, и все.  Для тех, кому английский так и не стал родным, очень кратко:

Создаем файл /etc/fail2ban/filter.d/dovecot-pop3imap.conf вот такого содержания:

[Definition]
failregex = (?: pop3-login|imap-login): (?:Authentication failure|Aborted login \(auth failed|Disconnected \(auth failed).*rip=(?P\S*),.*
ignoreregex =

После чего в файл /etc/fail2ban/jail.conf добавляем новую секцию вот такого вида:

[dovecot-pop3imap]
enabled = true
filter = dovecot-pop3imap
action = iptables-multiport[name=dovecot-pop3imap, port="pop3,imap", protocol=tcp]
logpath = /var/log/maillog
maxretry = 20
findtime = 1200
bantime = 1200

Пару замечаний про «мой случай» (выделено синим):

  • Лог для анализа в моем случае задействован иной — /var/log/mail/info.log (именно в нем я нашел сообщения об ошибочных авторизациях).
  • Строки про findtime и bantime я в секцию dovecot-pop3imap не писал совсем — меня вполне устраивают и значения «глобальных» настроек».
  • Параметр maxretry я у себя поставил поменьше — нечего тут…

После всех этих описанных выше действий, перезапустил я fail2ban и сижу вот теперь, жду…

fail2ban охраняет apache (часть «следующая»)…

В прошлой заметке, посвященной fail2ban, я описал пару фильтров, используемых мной для предотвращения «вражеских» происков, направленных против моего apache. Работало все это отлично, и вопросов не возникало. И дальше бы работало, если бы меня не потянуло на разборки с Chillispot. Дело в том, что в описанных мной конфигурациях fail2ban блокирование нежелательного доступа осуществляется при помощи shorewall. А его-то я как раз и поломал, ковыряясь с Chillispot. Точнее, не поломал, а отключил, так как для работы Chillispot требуется загрузка своего собственного скрипта с правилами для iptables, который «множит на ноль» всю работу shorewall

Чтож, iptables, так iptables. Нам-то какая разница!? Нужно всего-лишь заставить fail2ban тоже использовать iptables при блокировании доступа. Для этого залез я в файл /etc/fail2ban/jail.conf и настройки «тюрем» своих поисправлял следующим образом:

[apache-shorewall]

enabled  = true
filter   = apache-noscript
action   = iptables[name=httpd, port=http, protocol=tcp]
logpath  = /var/log/httpd/error_log
maxretry = 2

И второй «тюрьме» тоже:

[apache-overflow]
enabled	= true
filter	= apache-overflows
action   = iptables[name=httpd, port=http, protocol=tcp]
logpath	= /var/log/httpd/error_log
maxretry = 1

Изменения по сравнению с предыдущим вариантом, описанным мной ранее, для наглядности я выделил красным цветом. Также, если сравнить с предыдущими вариантами, я не стал писать строку со вторым «действием» (action) — отправку письма администратору (mail-whois или sendmail). Ему (мне) и так писем достаточно… Названия самих «тюрем» (те, что в указанных примерах написаны в квадратных скобках) я менять не стал. Они все равно ни на что не влияют, только лишь в лог пишутся.

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

fail2ban-client reload

И все! Кстати, есть еще одно отличие у данного варианта блокирования по сравнению с shorewall, описанным ранее: iptables блокирует только порт apache

Ну «Secure», так «secure» (часть 3 — fail2ban охраняет apache)

В прошлых моих записях с заголовком «Ну «Secure», так «secure» я защищался от попыток постороннего входа в мой «сервер» по ssh. Но, это ведь не единственный порт моего «сервера», который открыт наружу. Раз уж у меня установлен веб-сайт, то доступ к нему извне, естественно, тоже есть. И вот теперь заглянем-ка в файл протокола ошибок apache (/var/log/httpd/error_log):

[Sat Jan 31 12:05:49 2009] [error] [client 89.18.176.83] File does not exist: /var/www/html/bin
[Sat Jan 31 12:05:50 2009] [error] [client 89.18.176.83] File does not exist: /var/www/html/mail
[Sat Jan 31 12:05:52 2009] [error] [client 89.18.176.83] File does not exist: /var/www/html/webmail
[Sat Jan 31 12:05:53 2009] [error] [client 89.18.176.83] File does not exist: /var/www/html/roundcube
[Sat Jan 31 12:05:58 2009] [error] [client 89.18.176.83] File does not exist: /var/www/html/rc

Насколько я понимаю, данные строки лога показывают, что «некто» пытается найти в моем сервере «нечто». Не знаю, можете называть это паранойей, но мне это очень не нравится! А вдруг найдет? Или вот еще, к примеру, строка из лога:

[Mon Jan 26 22:19:46 2009] [error] [client 213.21.37.175] script '/var/www/html/azenv.php' not found or unable to stat

Может это самый лучший и самый полезный в мире скрипт, а может быть и нет. Как по мне, так лучше не надо!

Итак, решено — будем защищаться. fail2ban у меня уже установлен — ssh защищает. Но это далеко не единственная возможность программы. Просто по умолчанию сразу после установки в ней включен единственный фильтр — sshd.conf. Вернемся к сути программы fail2ban. Она постоянно анализирует файлы протоколов работы служб компьютера, пытаясь найти в них сообщения об ошибках, соответствующие установленным шаблонам. Если условие совпадает, программа выполняет указанное действие. Условия-шаблоны прописываются в файлах фильтров, расположенных в папке /etc/fail2ban/filter.d. Возможные действия представлены файлами, находящимися в папке /etc/fail2ban/action.d. Управление «включением» и «выключением» фильтров, а также выбор последующих «действий» осуществляется в файле настроек /etc/fail2ban/jail.conf. Борьбу за безопасность apache я начал с поиска подходящего фильтра в папке /etc/fail2ban/filter.d. На первый взгляд мне подошел файл фильтра apache-noscript.conf. Его я поначалу и задействовал (об этом ниже). Однако, впоследствии, сопоставляя файл протокола ошибок apache и файл протокола работы fail2ban, я заметил, что далеко не все сообщения об ошибках приводят к бану вызвавших их посетителей. Утверждать, что программа не работает, было бы неправдой — на часть ошибок она все-таки реагировала. Следовательно, «что-то не то» с шаблонами. Отличным подспорьем в «разборках» с шаблонами является программа fail2ban-regex, устанавливаемая на компьютер вместе с fail2ban. Программа позволяет проанализировать указанный лог (или просто текстовую строку) на предмет нахождения соответствий шаблону из файла фильтра (или просто текстовой строке). Именно этим я и занялся. Взял лог, взял фильтр и «скормил» их програмке — ввел в консоли команду:

fail2ban-regex /var/log/httpd/error_log apache-noscript.conf

Первый ответ, о том, что найдено аж 10 совпадений меня очень развеселил.  «Невооруженным глазом» было видно, что в логе их гораздо больше… И начал я подбирать шаблон, попутно проверяя его эффективность все той же приведенной выше командой. Число совпадений росло, сначала три сотни, потом больше тысячи, финальный результат был равен 1706. Я решил, что пока хватит, а дальше посмотрим. Теперь о произведенных мной изменениях. Изначально в файле фильтра apache-noscript.conf строка шаблона сообщения об ошибке выглядела так:

failregex = [[]client <HOST>[]] (File does not exist|script not found or unable to stat): .*(\.php|\.asp|\.exe|\.pl)

Результат, который в конце концов устроил лично меня, выглядит так:

failregex = [[]client <HOST>[]] (File does not exist|Invalid URI in request|.* not found or unable to stat)

В чем суть моих изменений? Во первых, оригинальная строка шаблона предполагает, что в логе сообщение об ошибке должно содержать что-либо из «.php», «.asp», «.exe» или «.pl». Если же в строке такого нет, шаблон не срабатывает. Но даже в той «нарезке» лога apache, что я привел выше мы видим, что нет там никаких «.php», «.asp», «.exe» или «.pl». Следовательно фильтр не сработает. По этому, окончание шаблона — (\.php|\.asp|\.exe|\.pl) — я попросту выкинул.

Ну и во вторых, та часть шаблона, которая вылавливает неправильные скрипты. В оригинале она хочет, чтобы в логе был такой текст «script not found or unable to stat» (одним непрерывным куском!!!). Но, посмотрев в свои логи я увидел, что зачастую там текст отформатирован иначе, например так: «script ‘/var/www/html/pt.php’ not found or unable to stat». Следовательно этот фильтр тоже не срабатывал бы. Пришлось его заменить на «.* not found or unable to stat«. В данном случае «.*» обозначает «любой текст». После этого фильтр начал срабатывать на сообщения об ошибках о запуске несуществующих скриптов.

 

Ну и вкратце о том, как я подключал фильтр. В файле настроек /etc/fail2ban/jail.conf я нашел раздел:

[apache-shorewall]

enabled  = false
filter   = apache-noscript
action   = shorewall
           sendmail[name=Postfix, dest=you@mail.com]
logpath  = /var/log/apache2/error_log

И изменил его следующим образом:

[apache-shorewall]

enabled  = true
filter   = apache-noscript
action   = shorewall
           mail-whois[name=Apache, dest=dmitry@my-svr]
logpath  = /var/log/httpd/error_log
maxretry = 2

Таким образом я:

  • включил (enabled = true)…
  • выбранный фильтр (filter = apache-noscript)…
  • на анализ файла протокола (logpath = /var/log/httpd/error_log)…
  • и при возникновении 2 ошибок (maxretry = 2)…
  • доступ блокируется при помощи файервола (action = shorewall).

Вот и все…

P.S.
Не вышло «все», однако… 21 марта с одного IP такой «вал валил», что я решил предпринять что-то. И нашел еще один фильтр — apache-overflows.conf, который вроде как очень подходил моим потребностям. Судите сами, вот кусок лога apache:

[Sat Mar 21 17:19:35 2009] [error] [client 221.223.93.132] Invalid method in request \xf0\xaf\xa0_\x98\x1b\x9fi\xe2\x84\xca\xc8\xca\xfa\xabA\xb4f\xe0+\xf3\x96>S\x90\x90\xc1D\x80\xc2\x11\xe17\xcc\x91\x97
[Sat Mar 21 17:20:04 2009] [error] [client 221.223.93.132] Invalid URI in request \xfb%\xd2\ba\xf5\x84\x9c'\x0c\xbc\xf4|\xffu\x10?\xf2\x96\xee\xda\x9d\xe9\x9f\xb0\x15\xc9\xe9nd
[Sat Mar 21 17:20:43 2009] [error] [client 221.223.93.132] request failed: error reading the headers

А вот (но, правда, уже немножко подкорректированный мной) фильтр:

# Notes.:  Regexp to catch Apache overflow attempts.
# Values:  TEXT
#
failregex = [[]client []] (Invalid method in request|Invalid URI in request|request failed: URI too long|request failed: error reading the headers|erroneous characters after protocol string).*

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =

Пришлось и его включать. С поправкой на тот факт, что мне показалось, что это была именно атака, рубить доступ я решил с первой же попытки. Для этого в файл /etc/fail2ban/jail.conf я добавил следующие строки:

[apache-overflow]
enabled	= true
filter	= apache-overflows
action	= shorewall
logpath	= /var/log/httpd/error_log
maxretry = 1

После этого перезапустил fail2ban командой:

fail2ban-client reload

И вот теперь сижу и жду новых поводов для добавления новых фильтров…

Еще про fail2ban

Ну «Secure», так «secure» (часть 2)

В прошлой заметке я уже описал, как боролся с «подбирателями паролей» на моем ssh-демоне. В принципе, я считаю, что принятых мер достаточно для защиты моего сервера (да и кому он надо-то?!). Но, с другой стороны, тысячи строк с сообщением об ошибке в логе авторизации просто «напрягают зрение понапрасну». И вот, просматривая сайт с новостями программного обеспечения, я наткнулся на название программы, которое меня заинтересовало — «Fail2Ban«. Открыл у себя «Центр управления Mandriva Linux», в нем выбрал «Управление программами» и ввел имя программы в поле «Поиск». «Есть у нас такая программа» — сказал поиск. Поставил «птичку», установил. Чем заинтересовала-то меня данная программа? Вот что про нее написано;

Fail2Ban scans log files like /var/log/secure and bans IP that makes too many password failures. It updates firewall rules to reject the IP address. These rules can be defined by the user. Fail2Ban can read multiple log files including sshd or Apache web server logs.

А если вкратце и по русски, программа сканирует логи и динамически меняет правила файервола, запрещая доступ тем IP, с которых происходит слишком много НЕУДАЧНЫХ попыток авторизации (читай, «происходит подбор пароля»)!!! Вот и все!

Остается лишь в качестве подтверждения эффективности программы процитировать два лога. Первый — протокол авторизации в системе (файл /var/log/auth.log):

Jul 25 20:12:31 smb-svr sshd[26144]: Invalid user guest from 61.168.222.170
Jul 25 20:12:31 smb-svr sshd[26144]: error: Could not get shadow information for NOUSER
Jul 25 20:12:31 smb-svr sshd[26144]: Failed password for invalid user guest from 61.168.222.170 port 1652 ssh2
Jul 25 20:12:36 smb-svr sshd[26147]: Invalid user guest from 61.168.222.170
Jul 25 20:12:36 smb-svr sshd[26147]: error: Could not get shadow information for NOUSER
Jul 25 20:12:36 smb-svr sshd[26147]: Failed password for invalid user guest from 61.168.222.170 port 2597 ssh2
Jul 25 20:12:42 smb-svr sshd[26149]: Invalid user guest from 61.168.222.170
Jul 25 20:12:42 smb-svr sshd[26149]: error: Could not get shadow information for NOUSER
Jul 25 20:12:42 smb-svr sshd[26149]: Failed password for invalid user guest from 61.168.222.170 port 3700 ssh2

А второй — протокол работы самой программы (файл /var/log/fail2ban.log):

2008-07-25 20:12:43,045 fail2ban.actions: WARNING [ssh-iptables] Ban 61.168.222.170
2008-07-25 20:22:43,414 fail2ban.actions: WARNING [ssh-iptables] Unban 61.168.222.170

Для «полного понимания» добавлю лишь, что по умолчанию программа:

  • запрещает доступ с IP-адреса после трех неверных попыток ввода пароля;
  • блокирует доступ на 600 секунд.

Первое прекрасно видно при сравнении времени третьей попытки из первой «цитаты» со временем включения файервола во второй «цитате». Второе легко заметить, сравнив во второй «цитате» время включения и выключения блокирования адреса. При желании Вы можете изменить те значения настроек, которые Вас не устраивают , самостоятельно отредактировав файлы в папке /etc/fail2ban.

…С тех пор у меня нет в логах авторизации многотысячных записей «Failed password for invalid user...» Чего и вам желаю!,,,

ЗЫ. Балуясь на днях (зкспериментируя) с авторизацией в ssh, заполучил бан самого себя. «Сервер» дома, я на работе, а дела-то не ждут! Пришлось себя срочно «разрешать»… Спас Webmin. У него в разделе «Прочее» есть пункт «Командная оболочка (shell)» (командная строка). Вот в ней-то я и запустил команду:

fail2ban-client status

Сервер fail2ban ответил, что запущен следующий фильтр (Jail): ssh-iptables. Чтобы остановить его, ввел команду:

fail2ban-client stop ssh-iptables

И напоследок, чтобы на будущее меня ни в коем случае не банило, прописал свой рабочий адрес в файл /etc/fail2ban/jail.conf в строке:

ignoreip = 127.0.0.1 XXX.XXX.XXX.XXX

(адреса, когда их несколько, разделяются пробелами)…