Настройка периметра для WordPress на Ubuntu Trusty

Posted by

Сегодня я приведу практические рекомендации как обезопасить установленный блог на VPS хостинге. Имея VPS хостинг — Вам выделяются ресурсы (HDD,CPU,RAM) и ваша задача не только поставить систему Ubuntu (LTS релизы) и развернуть CMS-систему WordPress, но и защитить вашу vps‘ку. Что я подразумеваю под защитой:

  • прекратить подбор логина и пароля в административную часть wordpress
  • прекратить подбор пароля до сервера удаленного администрирования (SSH)

Ранее на своем блоге я описал как защитить выставленную систему от несанкционированного подключения с помощью фаервола (ufw) и технологии port knocking, но вот если Вы не хотите использовать port knocking (технология простукивания системы), то можно защититься посредством утилиты fail2ban о которой в практическом применении и пойдет речь. Что может данная утилита — а она просто анализирует логи формируемых сервисов на Вашем сервере посредством составленных фильтров и если количество повторяющихся записей отказа или ошибок повторяется за определенное время то происходит блокировка в виде запрета доступа.

Итак моя система моего блога: Ubuntu Trusty, блог развернут по заметке.

Устанавливаю утилиту fail2ban в систему:

ekzorchik@srv-host:~$ sudo apt-get install fail2ban -y

Конфигурационные файлы утилиты fail2ban располагаются в каталоге /etc/fail2ban, также его содержимое Важно с точки зрения накладываемого функционала на содержимое, а именно:

  • каталог → action.d – содержит правила (/etc/fail2ban/action.d/) реагирования исходя из файла jail.conf и фильтров из каталога /etc/fail2ban/filter.d/
  • каталог –> filter.d – содержит фильтры
  • каталог → jail.conf – файл объединяющий все правила воедино

Но обычно приложение fail2ban используется для защиты выставляемых во всемирную сеть сервисов, к примеру: Asterisk, Mail, FileServer, а вот для CMS систем?

Когда кто-либо пытается зайти в административную часть и не только по переходу ссылкеВойтиуказывая неправильный логин или же пароль, а может и все вместе, то в журналах формируются следующие записи:

  • http://10.7.8.122/wp-login.php

если Login: указывается к примеру ekzorchik, а пароль: подбираемый, то на данной странице выводится подсказка, то да пользователь есть, но вот пароль не соответствует правильному:

ОШИБКА: Введённый вами пароль пользователя ekzorchik неверен. Забыли пароль? (http://10.7.8.122/wp-login.php?action=lostpassword)

ekzorchik@srv-host:~$ tail -f /var/log/apache2/wordpress-access.log

10.7.8.135 — — [16/Feb/2016:09:04:44 +0300] «POST /wp-login.php HTTP/1.1» 200 2166 «http://10.7.8.122/wp-login.php» «Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0»

10.7.8.135 — — [16/Feb/2016:09:04:44 +0300] «GET /wp-includes/css/buttons.min.css?ver=4.4.2 HTTP/1.1» 200 1697 «http://10.7.8.122/wp-login.php» «Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0»

10.7.8.135 — — [16/Feb/2016:09:04:44 +0300] «GET /wp-includes/css/dashicons.min.css?ver=4.4.2 HTTP/1.1» 200 28890 «http://10.7.8.122/wp-login.php» «Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0»

10.7.8.135 — — [16/Feb/2016:09:04:44 +0300] «GET /wp-admin/css/login.min.css?ver=4.4.2 HTTP/1.1» 200 6235 «http://10.7.8.122/wp-login.php» «Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0»

  • если не правильно указываем даже логин и пароль, то еще одна подсказка, то такого логина не существует:

ОШИБКА: Неверное имя пользователя. Забыли пароль? (http://10.7.8.122/wp-login.php?action=lostpassword)

Что примечательно так это события в лог файлах, любое действие авторизации и безуспешно авторизации сопровождается ответным кодом 200 – что якобы успешно по правилам работы в Web-пространстве. Бред какой-то.

Но так дело не пойдет, буду разбирать как прикрутить fail2ban к используемой CMS системе WordPress для этого создаю фильтр:

ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/filter.d/wordpress-authen.conf

[Definition]

failregex = <HOST> - - .* "POST.*(wp-login\.php|xmlrpc\.php).* 200

ignoreregex =

На заметку: режим POSTэто передача параметров путем ввода в соответствующие поля, а режим GETэто получение параметров.

Не забываем сохранить внесенные изменения в новый фильтр. Данная строка означает, что осуществляется поиск строки со статусом кода 200 и запросе/вводе URL адреса или переходу к файлам: wp-login.php & xmlrpc.php.

На заметку: по правилам хорошего тома в конфигурационном файле jail.conf должно быть только то что используется и прокомментировано, все остальное должно быть удалено.

ekzorchik@srv-host:~$ sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.conf.old

А теперь создаю правило реагирования:

ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/action.d/ufw-wordpress.conf

[Definition]

actionstart =

actionstop =

actioncheck =

# этим мы блокируем нарушителя для всего хостинга, если нужно только для 80 порта, то to any port 80

actionban = ufw insert 1 deny from <ip> to any

actionunban = ufw delete deny from <ip> to any

А теперь создаю правило блокировки для сервиса:

ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/jail.conf

[wordpress-authen]

enabled = true

# правила реагирования: /etc/fail2ban/action.d/ufw-wordpress.conf

action = ufw-wordpress

port = http

filter = wordpress-authen

logpath = /var/log/apache2/wordpress-access.log

# если в течение одного часа было 5 неудачных попыток, то блокируем его на одни сутки

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

# в течение часа

findtime = 3600

# пять неудачный попыток

maxretry = 5

# блокировка на 24 часа

bantime = 86400

Не забываем сохранить внесенные изменения.

На заметку: описание параметров из конфигурационного файла jail.conf

  • ignoreipIP–адреса, которые не должны быть заблокированы. Можно задать список IP-адресов разделённых пробелами, маску подсети, или имя DNS–сервера, т. е. Ваш рабочий статический, домашний с которых только Вы можете зайти, а все остальные ни-ни.
  • bantime — время бана в секундах, по истечении которого IP–адрес удаляется из списка заблокированных. findtime = 3600 (## если в течении 1 часа:)
  • maxretry — количество подозрительных совпадений, после которых применяется правило. В контексте [ssh] — это число неудавшихся попыток логина, после которых происходит блокировка.
  • enabled — значение true указывает что данный jail активен, false выключает действие изолятора.
  • port — указывает на каком порту или портах запущен целевой сервис. Стандартный порт SSH–сервера — 22, или его буквенное наименование — ssh, Web-сервера — 80 (http)
  • filter — имя фильтра с регулярными выражениями, по которым идёт поиск «подозрительных совпадений» в журналах сервиса. Фильтру wordpress-authen соответствует файл /etc/fail2ban/filter.d/wordpress-authen.conf
  • logpath — путь к файлу журнала, который программа Fail2ban будет обрабатывать с помощью заданного ранее фильтра. Вся история удачных и неудачных входов в wordpress /var/log/apache2/wordpress-access.log

Чтобы настройки сервиса активировались нужно перезапустить службу fail2ban:

ekzorchik@srv-host:~$ sudo service fail2ban restart

* Restarting authentication failure monitor fail2ban

Проверяем, как отработает блокировка:

ekzorchik@srv-host:~$ sudo tail -f /var/log/apache2/wordpress-access.log

вводим в окне авторизации неправильные логин и пароль в количестве пяти раз, а тем временем в журнале fail2ban появляются нижеследующие строки

2016-02-16 10:16:38,527 fail2ban.jail : INFO Jail ‘wordpress-authen’ started

2016-02-16 10:20:59,344 fail2ban.actions: WARNING [wordpress-authen] Ban 10.7.8.135

вот и мой IP адрес (10.7.8.135) с которого я пишу и попутно тестирую/работаю заблокирован.

по прошествии некого времени мой IP был разблокирован

2016-02-16 10:30:59,591 fail2ban.actions: WARNING [wordpress-authen] Unban 10.7.8.135

и уже обратившись через браузер http://10.7.8.122 — я получаю сообщение от «Попытка соединения не удалась» — и это здорово.

Чтобы посмотреть статистику по отработанному фильтру:

ekzorchik@srv-host:~$ sudo fail2ban-client status wordpress-authen

Status for the jail: wordpress-authen

|- filter

| |- File list: /var/log/apache2/wordpress-access.log

| |- Currently failed: 0

| `- Total failed: 5

`- action

|- Currently banned: 1

| `- IP list: 10.7.8.135

`- Total banned: 1

Как видно, мой IP адрес заблокирован, чтобы разблокировать определенный IP адрес нужно набрать следующую команду:

ekzorchik@srv-host:~$ sudo fail2ban-client set wordpress-authen unbanip 10.7.8.135

10.7.8.135

Отлично теперь можно авторизовать через Web-интерфейс.

А заблокировать снова внеся его в BAN лист в ручную можно такой командой:

ekzorchik@srv-host:~$ sudo fail2ban-client set wordpress-authen banip 10.7.8.135

10.7.8.135

Итак что обозначают введенные команды:

  • wordpress-authen — название настроенного фильтра в конфигурационном файле jail.conf
  • banip — заблокировать указанный адрес
  • unbanip — разблокировать указанный адрес

На заметку:

на будущее смотрите хелп по команде fail2ban-client там все подробно описано (я же справился)

Хочу заменить, что данный способ успешно работает и препятствует доступ к моему блогу нежелательных, вот к примеру, однажды зайдя на свой VPS ресурс и сделав отчет как работает защита wordpress – увидел вот такую картину:

<secret_user>@<secret_host>:~$ sudo fail2ban-client status wordpress-authen

Status for the jail: wordpress-authen

|- filter

| |- File list: /var/log/apache2/wordpress-access.log

| |- Currently failed: 0

| `- Total failed: 72

`- action

|- Currently banned: 5

| `- IP list: 23.125.42.243 184.183.155.178 173.8.27.45 54.186.75.170 69.15.51.33

`- Total banned: 5

Видно, что попытки несанционированного доступа уже пресекаются. И это хорошо.

Так это я рассмотрел действия чтобы не дать зайти в панель администрирования wordpress, но ведь я на него же имею доступ по ssh, защищаю систему по заметке.

ekzorchik@srv-host:~$ sudo ufw allow to any port 381

Rule added

ekzorchik@srv-host:~$ sudo ufw allow to any port 80

Skipping adding existing rule

ekzorchik@srv-host:~$ sudo ufw status numbered

Status: active

To Action From

— —— —-

[ 1] 80 ALLOW IN Anywhere

[ 2] 381 ALLOW IN Anywhere

Теперь перехожу к настройке правила которое будет блокировать несанкционированные попытки зайти на мой блог по порту 381 на котором работает OpenSSH сервис. По умолчанию когда утилита fail2ban установлена, защита ssh активируется по умолчанию:

ekzorchik@srv-host:~$ ps aux | grep sshd

root 742 0.0 0.1 61380 5312 ? Ss 07:58 0:00 /usr/sbin/sshd -D

ekzorchik@srv-host:~$ sudo service ssh status

ssh start/running, process 742

фильтры уже настроены: /etc/fail2ban/filter.d/sshd.conf

Когда кто-то пытается подключиться к службе по стандартному порту, то в логах появляются следующие строки:

Mar 7 09:12:39 srv-host sshd[2718]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=10.7.8.135

Mar 7 09:12:40 srv-host sshd[2718]: Failed password for invalid user ad from 10.7.8.135 port 56800 ssh2

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

А потому нужно настроить блокировку от таких вот часто повторяющихся строк в файлах логов:

ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/jail.conf

#banaction = iptables-multiport

#action_

#action_mw

#action_mwl

#action

[ufw-ssh]

enabled = true

# /etc/fail2ban/action.d/ufw-ssh.conf

action = ufw-ssh

port = 381

filter = sshd

logpath = /var/log/auth.log

# количество подозрительных совпадений

maxretry = 5

# в течении 5 минут - три совпадения

findtime = 300

# блокировка на 24 часа

bantime = 86400

Создаю правила реагирования на нарушителей:

ekzorchik@srv-host:~$ sudo nano /etc/fail2ban/action.d/ufw-ssh.conf

[Definition]

actionstart =

actionstop =

actioncheck =

actionban = ufw insert 1 deny from <IP> to any app OpenSSH

actionunban = ufw delete deny from <IP> to any app OpenSSH

Не забываем по окончании правки конфигурационных файлов сохранить внесенные изменения. А теперь перезапускаем службу failban для активации изменений:

ekzorchik@srv-host:~$ sudo service fail2ban restart

Проверяем текущий статус правила:

ekzorchik@srv-host:~$ sudo fail2ban-client status ssh

Status for the jail: ssh

|- filter

| |- File list: /var/log/auth.log

| |- Currently failed: 0

| `- Total failed: 0

`- action

|- Currently banned: 0

| `- IP list:

`- Total banned: 0

C другой машины пробую подключаться с использованием неизвестных мне логинов и паролей к системе:

aollo@srv-glpi:~$ ssh -l admin 10.7.8.122 -p 381

admin@10.7.8.122’s password:

Permission denied, please try again.

admin@10.7.8.122’s password:

^C

aollo@srv-glpi:~$ ssh -l n 10.7.8.122 -p 381

ssh: connect to host 10.7.8.122 port 381: Connection refused

, а на 22 порт нельзя будет подключиться потому как он закрыт и открывается только когда по нему постучат, хотя на него также желательно настроить fail2ban на всякий случай (ну может быть).

, вот теперь я заблокировал на срок указанный в конфигурационном файле jail.conf нарушителя.

Проверяю:

ekzorchik@srv-host:~$ sudo fail2ban-client status ssh

Status for the jail: ssh

|- filter

| |- File list: /var/log/auth.log

| |- Currently failed: 0

| `- Total failed: 9

`- action

|- Currently banned: 1

| `- IP list: 10.7.8.154

`- Total banned: 1

По сути выставление порта 381 — это просто медовый сервис по отводу личностей от Вашего хостинга. Рекомендую время блокировки IP указать выраженное, как неделя. На этом я хочу подытожить все то, что рассмотрел что нужно сделать чтобы обезопасить вашу VPS от посягательств. В дальнейшем я буду рассматривать защиту различных сервисов посредством связки: ufw + fail2ban для меня так понятней чем писать правила посредством iptabes. Как говориться каждому свое. На этом у меня все и до новых заметок, с уважением автор блога — ekzorchik.