Защита wordpress с помощью fail2ban

Совершенно не моё изобретение, да и гуглится несложно, но тем не менее не грех будет упомянуть о средствах контрацепции для этого нашего вордпресса, чтобы на просторах интернетика было ему безопасно.

Вообще говоря, защита учеток вордпресса — это совсем отдельная тема, в которую можно погружаться и погружаться. Ботнеты ищут инсталляции ВП и стараются атаковать, как правило, с двух сторон: разумеется это wp-login.php — страница аутентификации с логином и паролем; и xmlrpc.php — кусок механизма для удаленного подключения и управления сайтом. Причем большинство атак приходится на вторую сторону, и в интернете куча инфы (копия) о том, как эту лавочку прикрыть, отрубив весь механизм. На самом деле это вполне дельная мысль, так как велика вероятность что удаленный доступ к сайту вовсе не используется, но если есть желание, например, постить через мобильный клиент вордпресса — он понадобится.

Но вне зависимости от отключения  xmlrpc, придется защищать и основную форму логона. Опять же тут можно (и нужно) возвести многоступенчатую защиту. Негрешно воткнуть капчу при помощи  WordPress ReCaptcha Integration, хорошей мыслью будет вообще запретить или ограничить регистрацию с логином и паролем, включив авторизацию через социальные сети (с этим поможет Social Login). Однако все неплохо, пока на сайт пытаются ломиться люди, но вышеупомянутые ботнеты любят атаковать с пачек IP-адресов, посылая частые запросы на аутентификацию, и тут я подбираюсь к сабжу…

Хотя на самом деле скажу еще одно: для блокировки пользователей, активно брутящих пароли, можно с помощью неплохого плагина для самого вордпресса — Limit Login Attempts Reloaded. Он вполне шикарен — ведет список IP, банит на установленный срок при превышении лимита попыток, умеет писать об этом в почту админа. Но в какой-то момент мне захотелось, чтобы такие айпишники не просто банились на уровне ВП, а выпиливались на файрволле — это более концептуальное решение, которое ко всему прочему разгружает сервер от левых запросов. Ну и конечно для такого типа задач есть готовое решение — демон fail2ban.

Оказывается прикрутить его к вордпрессу — проще простого.

Для начала нужно в папку «wp-content/mu-plugins» (если ее нет — нужно ее создать) положить файлик:

return_403_on_failed_login.php
 
<?php
/**
 *  * Plugin Name: Return 403 on Failed Login
 *   */
function my_login_failed_403() {
    status_header( 403 );
}
add_action( 'wp_login_failed', 'my_login_failed_403' );

Этот файлик, положенный в эту папку, будет постоянно работающим плагином, который нельзя отключить (папка mu-plugins — именно для таких). Суть его работы в том, чтобы при неудачной попытке залогиниться, в лог вебсервера сообщение о доступе к файлам wp-login.php и xmlrpc.php падало с 403й ошибкой. Это нужно чтобы отличать такие фейлы от простого запроса страниц. Выглядеть это будет примерно так:

 
 
  1. 143.255.155.196 - - [30/Apr/2019:09:11:01 +0300] "POST /wp-login.php HTTP/1.1" 403 2947 "https://qiwichupa.net/wp-login.php" "Mozilla/5.0 (Windows NT 10.0; rv:48.0) Gecko/20100101 Firefox/48.0"

Теперь нужно пошаманить с fail2ban.

Добавляем фильтр таких сообщений:

/etc/fail2ban/filter.d/wp-login.conf
 
  1. [Definition]
  2. failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 403

Простая регулярка, которая выхватит IP из строки с 403ей ошибкой и нужными именами файлов.

Теперь настроим тюрьму:

/etc/fail2ban/jail.d/wordpress.conf
 
  1. [wp-mysite]
  2. enabled = true
  3. port = http,https
  4. filter = wp-login
  5. logpath = /var/log/nginx/mysite_access.log
  6. findtime = 600
  7. maxretry = 2
  8. bantime = 86400

Тут нужно обратить внимание на параметр logpath — он должен вести к аксес-логу вебсервера (apache или nginx, если он стоит перед апачем). Параметры findtime и bantime принимают значение в секундах, первый отвечает за интервал в который с одного айпишника должны упасть фейлы для срабатывания блокировки, второй — время бана. Так данный пример конфига отправит айпишник в бан на сутки, если с него за 10 минут прилетит больше двух неудачных попыток аутентификации.

Собственно и всё. Рестартим fail2ban, смотрим в /var/log/fail2ban.log — в нем должно быть написано что тюрьма запустилась, а спустя какое-то время, если на сайт полезли боты, и сообщения о банах должны появиться:

 
 
  1. 2019-04-30 00:42:10,120 fail2ban.jail : INFO Jail 'wp-mysite' started
  2. 2019-04-30 00:42:37,452 fail2ban.actions: WARNING [wp-mysite] Ban 119.160.136.138
  3. 2019-04-30 00:42:37,483 fail2ban.actions: WARNING [wp-mysite] Ban 143.255.155.57