☰
WORDPRESS / PRACTICE

Як обмежити спроби входу до WordPress через Nginx

Як обмежити спроби входу до WordPress через Nginx

Навіть складний пароль не зупиняє ботів від масових спроб входу до WordPress. Автоматизовані мережі надсилають сотні або тисячі POST-запитів до /wp-login.php, через що зайво навантажуються PHP-FPM, база даних і сервер.

Rate limiting на рівні Nginx обмежує частоту таких запитів ще до передавання їх у PHP. Це не заміна MFA, надійним паролям і контролю облікових записів, але ефективний додатковий бар’єр проти автоматизованого brute-force.

Як працює обмеження запитів у Nginx

Nginx може вести лічильник запитів для кожної IP-адреси та не пропускати їх частіше за встановлений ліміт. Для wp-login.php зазвичай достатньо дозволити приблизно один запит на секунду, залишивши невеликий burst для короткочасних піків.

Директива limit_req_zone створює спільну зону зберігання лічильників. Параметр rate=1r/s означає середню швидкість один запит на секунду для однієї IP-адреси. burst=5 дозволяє коротку чергу або сплеск із п’яти додаткових запитів. Параметр nodelay не ставить ці запити в очікування, а пропускає їх одразу в межах burst; наступні запити отримають помилку.

  • 429 Too Many Requests повідомляє клієнту, що ліміт перевищено.
  • Лічильник потрібно прив’язувати до реальної IP-адреси клієнта.
  • Обмеження краще застосовувати саме до wp-login.php, а не до всіх PHP-файлів сайту.

Базова конфігурація для wp-login.php

Зону limit_req_zone розміщують у контексті http, а саме обмеження — у location для wp-login.php. Розташування файлів залежить від дистрибутива та структури конфігурації Nginx, тому змінюйте активний серверний блок, який обслуговує ваш домен.

Наведений приклад містить окремий FastCGI-обробник для wp-login.php. Шлях до PHP-FPM сокета, document root і набір fastcgi-параметрів потрібно адаптувати до вашого сервера.

  • Переконайтеся, що директива limit_req_zone не вставлена всередину server або location.
  • Перевірте, який PHP-FPM сокет реально використовується вашим сайтом.
  • Якщо у вас уже є окремий PHP location, не копіюйте його механічно: перенесіть потрібні параметри до точного location для wp-login.php.
http {
    limit_req_zone $binary_remote_addr zone=wp_login:10m rate=1r/s;

    server {
        server_name example.com;
        root /var/www/example.com/public;

        location = /wp-login.php {
            limit_req zone=wp_login burst=5 nodelay;
            limit_req_status 429;

            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_pass unix:/run/php/php-fpm.sock;
        }
    }
}

Як інтегрувати правило з наявним PHP-FPM location

У робочій конфігурації часто вже є блок location ~ \.php$, який передає PHP-файли до PHP-FPM. Точний location = /wp-login.php має вищий пріоритет для цього шляху, тому він може перехопити запит раніше за загальний PHP-блок.

Через це в точному location потрібно залишити всі необхідні FastCGI-параметри та fastcgi_pass. Якщо додати лише limit_req, але не передати запит у PHP-FPM, сторінка входу перестане працювати.

Найбезпечніший підхід — взяти FastCGI-частину з уже працюючого PHP location і додати до неї обмеження. Не змінюйте одночасно версію PHP, root, правила кешування та інші параметри без потреби.

  • Перевірте, чи містить fastcgi_params параметр SCRIPT_FILENAME у вашій системі; за потреби задайте його явно.
  • Не вказуйте вигаданий шлях до сокета: він може мати назву на кшталт php8.2-fpm.sock або працювати через TCP.
  • Після змін протестуйте не лише головну сторінку, а й відкриття форми входу та сам вхід до адмінпанелі.

Перевірка, застосування та спостереження за правилом

Перед перезавантаженням Nginx перевірте синтаксис конфігурації. Якщо команда повертає помилку, сервіс не потрібно перезапускати, доки проблему не буде виправлено.

Після успішного тесту застосуйте конфігурацію без розриву активних з’єднань. Потім перевірте access log і error log: перевищені ліміти мають бути помітні за статусом 429 або повідомленнями limit_req.

  • Перевірка конфігурації: nginx -t
  • Застосування змін: systemctl reload nginx
  • Перевірка відповіді: curl -I https://example.com/wp-login.php
  • Для POST-запитів тестуйте обережно, щоб не створювати непотрібні спроби входу.
sudo nginx -t && sudo systemctl reload nginx

Реальна IP-адреса за reverse proxy або CDN

Якщо сайт працює за Cloudflare, балансувальником, reverse proxy або іншим проміжним сервером, Nginx може бачити IP проксі замість IP відвідувача. У такому разі всі користувачі потраплять під один спільний ліміт і звичайні входи можуть почати отримувати 429.

Спочатку налаштуйте модуль realip: вкажіть довірені адреси проксі та правильний заголовок, який вони передають. Не можна бездумно довіряти довільному X-Forwarded-For, інакше клієнт зможе підмінити IP та обійти обмеження.

Після налаштування перевірте access log: у ньому має відображатися реальна адреса клієнта, а не лише адреса CDN або балансувальника. Список довірених мереж повинен відповідати документації вашого проксі та регулярно оновлюватися.

  • Не використовуйте заголовок відвідувача як джерело IP без перевірки довіреного проксі.
  • Переконайтеся, що $binary_remote_addr обчислюється вже після обробки realip.
  • Перевірте ліміти з різних мереж: домашньої, мобільної та через корпоративний проксі.

Типові помилки та налаштування ліміту

Занадто суворий ліміт може заважати легітимним користувачам, особливо якщо кілька людей входять із однієї офісної IP-адреси або весь мобільний оператор використовує спільний NAT. Почніть із помірного значення та спостерігайте за логами.

Обмеження для всіх запитів до wp-login.php також стосується GET-запиту, який відкриває форму входу. Для більшості сайтів це прийнятно, але нестандартні інтеграції або системи автоматизації можуть вимагати окремого тестування.

Не варто сприймати rate limiting як повну систему захисту. Якщо обліковий запис уже скомпрометований, Nginx не виявить проблему самостійно.

  • Помилка 404 після змін часто означає неправильний root або неповний FastCGI location.
  • Помилка 502 зазвичай вказує на неправильний PHP-FPM сокет або недоступний сервіс PHP-FPM.
  • Масові 429 для всіх користувачів часто спричинені неправильним real IP за reverse proxy.
  • Для додаткового захисту використовуйте MFA, унікальні паролі, оновлення WordPress і блокування скомпрометованих облікових записів.

Поширені запитання

Чи достатньо rate limiting для захисту WordPress від brute-force?

Ні. Він зменшує швидкість автоматизованих спроб і навантаження на PHP-FPM, але не замінює MFA, надійні паролі, оновлення ядра та плагінів і моніторинг облікових записів.

Чому після налаштування всі користувачі отримують 429?

Найчастіше Nginx бачить спільну IP-адресу reverse proxy або CDN. Налаштуйте realip для довірених проксі та перевірте, яку адресу записує access log.

Де розміщувати limit_req_zone?

Директива limit_req_zone має бути в контексті http. Директиву limit_req, яка вмикає зону для конкретного шляху, розміщують у server або location.

Що робити, якщо wp-login.php перестав працювати після змін?

Виконайте nginx -t, перевірте error log, PHP-FPM сокет, root і FastCGI-параметри. Точний location для wp-login.php має самостійно містити коректний fastcgi_pass та необхідні параметри.

Висновок

Rate limiting для wp-login.php на рівні Nginx зменшує кількість автоматизованих спроб входу ще до запуску WordPress і PHP. Почніть із ліміту 1 запит на секунду та невеликого burst, перевірте реальну IP-адресу клієнта й уважно протестуйте конфігурацію.

Після впровадження стежте за кодами 429 і журналами сервера. Якщо сайт працює за проксі або CDN, коректний real IP є критично важливим, інакше захист може блокувати звичайних відвідувачів замість ботів.

← Усі матеріали WordPress