Pull to refresh

Ограничение количества попыток ввода пароля в веб-форме авторизации при помощи Nginx или HAProxy на примере WordPress

Reading time3 min
Views17K
Рассмотрим на примере WordPress способ усиления безопасности при помощи ограничения количества HTTP-запросов к форме ввода пароля. Это позволит оградить опубликованный блог от брутфорса (поиска и взлома пароля путем перебора всех теоретически возможных вариантов из определенного набора символов или подбора по словарю распространенных паролей). Данный способ, в принципе, можно использовать и для защиты других веб-приложений.

Задача может быть реализована в Nginx с помощью модуля ngx_http_limit_req_module [1], выступающем в роли фронт-энда к Apache или веб-сервера FastCGI, или же с помощью HAProxy [2, 3], выступающем в роли балансировщика нагрузки перед веб-серверами.

В обоих случаях алгоритм работы следующий. При аутентификации браузер обращается по адресу, содержащему в себе подстроку "/wp-login.php". Необходимо отследить ее и ограничить количество запросов с одного IP не затрагивая обращения по всем остальным адресам. Параметры блокировки необходимо подобрать таким образом, чтобы не создавать неудобств обычным пользователями. Особенно внимательно следует настраивать блокировки в том случае, когда формой авторизации пользуется большое количество пользователей с одного IP-адреса.

Способ №1: Nginx

Конфигурационный файл исправлен по советам из комментариев. Спасибо VBart и J_o_k_e_R!

http {
     <...>
     
     limit_req_zone $binary_remote_addr zone=login:10m  rate=15r/m;

     server {
          listen      80;
          server_name  frontend.example.org;

     location ~* /wp-login.php {
          limit_req  zone=login burst=4;
          proxy_pass        http://backend:8080;
          <...>
     }

     location / {
          proxy_pass        http://backend:8080;
          <...>
     }
}

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

limit_req_zone $binary_remote_addr zone=login:10m rate=15r/m; Задаёт параметры зоны разделяемой памяти, которая хранит состояние для разных IP-адресов. В нашем случае состояния хранятся в зоне “login” размером 10 мегабайт, и средняя скорость обработки запросов для этой зоны не может превышать 15 запросов в минуту. Скорость обработки можно задать в запросах в секунду (r/s) или в запросах в минуту (r/m).

limit_req zone=login burst=4; устанавливает зону login и максимальный размер всплеска запросов (burst). Если скорость поступления запросов превышает описанную в зоне, то их обработка задерживается так, чтобы запросы обрабатывались с заданной скоростью. Избыточные запросы задерживаются до тех пор, пока их число не превысит максимальный размер всплеска. При превышении запрос завершается с ошибкой 503.

Способ №2: HAProxy

В секцию backend, обслуживающую наш блог, добавляем следующие строки [2]:
tcp-request inspect-delay 10s
tcp-request content accept if HTTP
# brute force protection
acl wp_login path_beg -i /wp-login.php
stick-table type binary len 20 size 500 store http_req_rate(20s) peers local
tcp-request content track-sc2 base32+src if METH_POST wp_login
stick store-request base32+src if METH_POST wp_login
acl bruteforce_detection sc2_http_req_rate gt 5
acl flag_bruteforce sc1_inc_gpc0 gt 0
http-request deny if bruteforce_detection flag_bruteforce

При обнаружении POST-запроса к к странице /wp-login.php сохраняется хэш из трех элементов: заголовка HTTP Host, URL-пути и IP источника. Идентифицируемый на основе хеша пользователь сможет сделать пять запросов за 20 секунд; шестой запрос будет заблокирован.

Литература
  1. Модуль ngx_http_limit_req_module — nginx.org
  2. wordpress CMS brute force protection with HAProxy — blog.haproxy.com
  3. Better Rate Limiting For All with HAProxy — blog.serverfault.com
Tags:
Hubs:
Total votes 29: ↑25 and ↓4+21
Comments30

Articles