WordPress 429 Too Many Requests: боти, обмеження запитів, Cloudflare — як виправити

Було корисно?

Ваш сайт на WordPress «працює», але користувачі не можуть увійти, оформлення замовлення не проходить, API починає вередувати, а Cloudflare
люб’язно відповідає 429 Too Many Requests. Нічого так не видає «здорову платформу», як блокування платних клієнтів, тому що бот-ферма знайшла
/wp-login.php.

429 ніколи не є загадкою. Це політичне рішення, прийняте чимось у вашому шляху запиту — WordPress, плагіном, Nginx/Apache, PHP‑FPM, зворотним проксі,
WAF або Cloudflare. Завдання — знайти, хто саме це застосовує, і чи працює воно на користь або просто витрачає гроші.

Що насправді означає 429 у WordPress (і звідки воно походить)

HTTP 429 «Too Many Requests» означає, що клієнт перевищив ліміт запитів. Цей клієнт може бути ботом, легітимним користувачем, колбеком платіжного шлюзу, вашим
апаратом перевірки доступності або мобільним додатком у петлі повторних спроб.

У світі WordPress 429 часто спрацьовує через одне з наступного:

  • Cloudflare: правила rate limiting WAF, Bot Fight Mode, кастомні правила або керовані виклики.
  • Nginx: правила limit_req / limit_conn, іноді застосовані надто широко.
  • Apache: mod_evasive або сторонні модулі WAF.
  • Додаток/плагін: плагіни для обмеження входів, плагіни безпеки, обмеження API або «захисна» проміжна логіка перед WP.
  • Верхній проксі/балансувальник: обмеження частоти або з’єднань з заплутаними заголовками.

Ключове правило операцій: 429 — це не «помилка WordPress». Це рішення щодо формування трафіку. Ваше завдання — визначити, хто прийняв рішення,
чи воно розумне, і як його налаштувати, щоб страждали боти, а люди — ні.

Швидкий план діагностики (перші/другі/треті перевірки)

Коли продакшн горить, немає часу на інтерпретативне дебагування. Ось найшвидший шлях до істини.

1) Перша перевірка: чи Cloudflare (або інший edge) генерує 429?

  • Подивіться на заголовки відповіді: server: cloudflare, cf-ray, заголовки виклику чи сторінка помилки з брендом Cloudflare.
  • Порівняйте origin і edge, виконавши curl прямо до origin (обійдіть CDN, якщо можете) і подивіться, чи залишається 429.

Якщо 429 на межі (edge), спочатку виправляйте правила rate limiting/WAF. Не «масштабуйте origin», щоб вгамувати правило WAF. Це як купувати другий холодильник,
бо перший зачинений.

2) Друга перевірка: чи origin‑логи показують відповіді 429?

  • Якщо access‑логи origin показують 429 для уражених шляхів, обмеження застосовано на origin.
  • Якщо в логах origin переважно 200/302, а користувачі бачать 429, то edge/проксі блокує досягнення origin.

3) Третя перевірка: ідентифікуйте ендпоінт і «ідентичність клієнта» для лімітів

  • Це /wp-login.php, /xmlrpc.php, /wp-json/, /wp-admin/admin-ajax.php чи /?
  • Чи лімитер ключує по IP, cookie, Authorization header або CF-Connecting-IP?
  • Чи багато реальних користувачів за одним NAT (офіс, школа, мобільний оператор) сприймаються як «один зловмисник»?

4) Четверта перевірка: шукайте повтори й петлі зворотного зв’язку

  • Неправильно сконфігурований плагін, зламаний кеш або JS‑клієнт можуть бити по ендпоінту з повторними спробами.
  • Вебхуки платіжних сервісів також можуть агресивно повторювати спроби, якщо ви відповідаєте 429. Це може перетворити «малу проблему» на «самопідтримувану бурю».

Парафразована ідея (приписують): Збої — нормальні; стійкість приходить від проектування систем, які продовжують працювати, коли щось йде не так — Вернер Вогельс (парафраз).

Цікаві факти та історія: 429, боти й обмеження частоти

  • 429 — відносно новий: він стандартизований у RFC 6585 (2012). Раніше відмови через ліміти класифікували як 503 або 403.
  • Retry-After має значення: 429 може містити заголовок Retry-After, але багато реалізацій його ігнорують, що заохочує «дурні» штормові повтори.
  • XML-RPC — магніт для зловживань: xmlrpc.php дозволяв pingback і віддалене публікування; також довгі роки використовувався для ампліфікації й брутфорсу.
  • «Боти» — не лише скрейпери: credential stuffing, тестування карт, зриви інвентаря і SEO‑спам також виглядають як «занадто багато запитів».
  • CDN зробили ліміти частоти масовими: коли edge‑сервери могли дешево рахувати запити, обмеження стало типовою політикою, а не кастомним origin‑хаком.
  • HTTP/2 змінив характер зловживань: менше з’єднань, більше запитів на з’єднання; обмеження за з’єднанням почали вводити в оману.
  • Більшість болю через спільні IP — стара проблема: припущення «одна IP = один користувач» зламалося з появою NAT і корпоративних проксі.
  • admin-ajax WordPress став поглиначем трафіку: теми і плагіни використовували його для всього, часто без кешування, що робило його м’якою ціллю для штормів.
  • Виявлення ботів — ймовірнісне: WAF жертвують точністю заради безпеки. Налаштування — не опція; це операційна необхідність.

Жарт №1: Обмеження частоти — як швейцар: чудово, доки не вирішить, що ваші платні клієнти «виглядають підозріло», бо в них однаковий NAT.

Відстеження, хто накладає обмеження: Cloudflare vs origin vs додаток

Ви побачите 429 у трьох загальних сценаріях. Кожен вказує на інше рішення.

Схема A: Cloudflare повертає 429, origin ніколи не бачить запит

Це часто трапляється, коли правила Rate Limiting Cloudflare або кастомні правила WAF занадто широкі, або ви ввімкнули «bot mode», думаючи, що воно влучить лише по ботах.
Edge‑429 зазвичай супроводжується Cloudflare‑заголовками та HTML‑сторінкою помилки.

Виправлення: налаштуйте правила Cloudflare точніше за шляхами й методами, і перестаньте застосовувати ліміти до всього підряд. Люди здебільшого роблять GET. Боти та атаки на облікові записи люблять POST.

Схема B: origin повертає 429, бо Nginx/Apache встановлює ліміти

Зазвичай виникає після того, як хтось вклеїв сниппет з блогу, який обмежує / або /wp-admin/, не врахувавши кешування, AJAX чи REST‑клієнтів.

Виправлення: обмежуйте правильні локації, ключуйтеся по реальному IP клієнта і задайте розумні «burst». Обмеження має поглинати піки, а не вирівнювати ваш базовий трафік.

Схема C: WordPress/плагін повертає 429 або 403‑подібну поведінку помилково маркують як 429

Деякі плагіни повертають 429, інші — 403, а деякі повертають 200 з повідомленням про помилку. Не довіряйте лише браузеру; довіряйте логам і заголовкам.

Виправлення: знайдіть плагін/проміжний шар, потім вирішіть — налаштовувати, замінити чи видалити. Плагіни безпеки — як кухонні ножі: корисні, поки хтось не вирішить жонглювати.

Боти та шаблони запитів, що викликають 429

Не всі «занадто багато запитів» є зловмисними. Просто вночі вони виглядають схоже.

Поширені зловмисні шаблони

  • Credential stuffing на /wp-login.php: швидкі POST‑запити, багато імен користувачів, ті самі діапазони IP, часто headless user‑agents.
  • XML‑RPC multicall brute force: менше запитів, але кожен містить кілька спроб входу.
  • Перебір REST API: атаки на /wp-json/wp/v2/users, /wp-json/, пошукові ендпоінти.
  • Штурм admin-ajax: повторні виклики admin-ajax.php від ботів або зламаних фронтенд‑скриптів.
  • Масштабне скрейпінг: агресивні GET‑запити, що ігнорують заголовки кешування, іноді з рандомізованими query‑строками, щоб обійти кеш.
  • Тестування карт на точках оформлення WooCommerce: багато дрібних транзакцій або спроб платежів.

Поширені не‑зловмисні шаблони

  • Реальні користувачі за одним NAT: офіс проводить навчання і всі одночасно входять; ваш ліміт по IP панікує.
  • Пінг‑перевірки й монітори доступності: занадто часті, з кількох регіонів, вдаряють по некешованих ендпоінтах.
  • Мобільні додатки: петлі повторних спроб при поганому зв’язку; можуть виглядати як армія ботів з поганим сигналом.
  • Неправильне кешування: обхід кешу для залогінених користувачів викликає раптовий сплеск на origin, і спрацьовують ліміти.

Практичні завдання: команди, виводи й рішення (12+)

Це операційні завдання, які можна виконати на типовому Linux‑хості WordPress. Кожне містить: команду, реалістичний вивід, що це означає, і що робити далі.
Підлаштуйте шляхи, якщо ваша дистрибуція/локації логів відрізняються.

Завдання 1: Підтвердити, хто згенерував 429 (заголовки говорять правду)

cr0x@server:~$ curl -sSI https://example.com/wp-login.php | sed -n '1,25p'
HTTP/2 429
date: Sat, 27 Dec 2025 10:12:01 GMT
content-type: text/html; charset=UTF-8
server: cloudflare
cf-ray: 85a1b2c3d4e5f678-FRA
retry-after: 10

Що це означає: Cloudflare емулює 429. Origin може бути в порядку — або також обмежувати, але ця відповідь від edge.
Рішення: Почніть з налаштувань rate limit/WAF/bot у Cloudflare, перед тим як торкатися Nginx чи WordPress.

Завдання 2: Обійти Cloudflare, щоб протестувати origin напряму (якщо можна)

cr0x@server:~$ curl -sSI --resolve example.com:443:203.0.113.10 https://example.com/wp-login.php | sed -n '1,25p'
HTTP/1.1 200 OK
Server: nginx
Content-Type: text/html; charset=UTF-8

Що це означає: Origin не повертає 429. Правила Cloudflare — головний підозрюваний.
Рішення: Виправляйте edge‑правила; не «апґрейдьте сервер» через роздратований edge.

Завдання 3: Перевірити, чи origin повертає 429 у access‑логах

cr0x@server:~$ sudo awk '$9==429 {count++} END{print count+0}' /var/log/nginx/access.log
312

Що це означає: Nginx на origin повернув 429 принаймні 312 разів у цьому файлі логів.
Рішення: Проінспектуйте конфіг Nginx ( limit_req, limit_conn ) і визначте уражені локації.

Завдання 4: Знайти найгарячіші ендпоінти, що отримують 429

cr0x@server:~$ sudo awk '$9==429 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
180 /wp-login.php
74 /xmlrpc.php
29 /wp-json/wp/v2/users
18 /wp-admin/admin-ajax.php
11 /

Що це означає: Входи й XML‑RPC — основні проблеми.
Рішення: Обмежуйте POST на /wp-login.php, серйозно подумайте про відключення XML‑RPC, якщо він не потрібен, і ставте правила Cloudflare за шляхами.

Завдання 5: Ідентифікувати топ‑IP, що спричиняють 429 (з погляду origin)

cr0x@server:~$ sudo awk '$9==429 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
91 198.51.100.77
68 198.51.100.12
44 203.0.113.55

Що це означає: Невелика кількість IP домінує в обмеженому трафіку.
Рішення: Якщо вони очевидно зловмисні — блокувати на Cloudflare/WAF або firewall. Якщо це корпоративні NAT чи сервісні IP — не блокувати, а тонко налаштувати ключування лімітерів.

Завдання 6: Перевірити, чи ви ключуєтеся не тим IP (підводний камінь reverse proxy)

cr0x@server:~$ sudo tail -n 3 /var/log/nginx/access.log
172.68.10.25 - - [27/Dec/2025:10:12:01 +0000] "POST /wp-login.php HTTP/1.1" 429 169 "-" "Mozilla/5.0"
172.68.10.25 - - [27/Dec/2025:10:12:02 +0000] "POST /wp-login.php HTTP/1.1" 429 169 "-" "Mozilla/5.0"
172.68.10.25 - - [27/Dec/2025:10:12:03 +0000] "POST /wp-login.php HTTP/1.1" 429 169 "-" "Mozilla/5.0"

Що це означає: «IP клієнта» — це IP Cloudflare. Якщо Nginx лімітує по $binary_remote_addr без відновлення реального IP,
ви фактично обмежуєте всіх користувачів разом. Так виникає загальносайтова вечірка 429.
Рішення: Виправте обробку реального IP (real_ip_header CF-Connecting-IP; і довірені діапазони) перш ніж налаштовувати ліміти.

Завдання 7: Перевірити конфігурацію Nginx на директиви ліміту

cr0x@server:~$ sudo nginx -T 2>/dev/null | egrep -n "limit_req|limit_conn|limit_req_zone|real_ip_header|set_real_ip_from" | head -30
45: real_ip_header CF-Connecting-IP;
46: set_real_ip_from 173.245.48.0/20;
47: set_real_ip_from 103.21.244.0/22;
120: limit_req_zone $binary_remote_addr zone=wp_login:10m rate=1r/s;
245: limit_req zone=wp_login burst=3 nodelay;

Що це означає: Лімітування існує. Схоже, реальний IP налаштовано (добре), але підтвердіть, що всі релевантні проксі‑діапазони включені та це в правильному контексті.
Рішення: Якщо 429 все ще б’є по нормальних користувачах — підвищте rate/burst або змініть ключ на щось розумніше для аутентифікованого трафіку.

Завдання 8: Перевірити, чи PHP-FPM не насичений (429 іноді ховає виснаження upstream)

cr0x@server:~$ sudo ss -s
Total: 684
TCP:   412 (estab 96, closed 262, orphaned 0, timewait 262)

Transport Total     IP        IPv6
RAW       0         0         0
UDP       6         4         2
TCP       150       92        58
INET      156       96        60
FRAG      0         0         0

Що це означає: Неоднозначно, але якщо встановлених з’єднань і timewait дуже багато, ви можете бути під навантаженням. Поєднуйте з моніторингом PHP‑FPM, якщо він увімкнений.
Рішення: Якщо upstream задухає — збільшуйте потужності й кешуйте; не покладайтеся лише на 429 як єдину оборону.

Завдання 9: Якщо PHP-FPM status увімкнений, перевірити використання пулу

cr0x@server:~$ curl -s http://127.0.0.1/php-fpm-status | sed -n '1,20p'
pool:                 www
process manager:      dynamic
start time:           27/Dec/2025:08:00:00 +0000
accepted conn:        124590
listen queue:         0
max listen queue:     47
listen queue len:     128
idle processes:       2
active processes:     38
total processes:      40
max active processes: 40
max children reached: 19

Що це означає: Ви досягли max children; пул інколи насичений. Це може викликати повільні відповіді, повтори й потім тригери ліміту upstream.
Рішення: Налаштуйте PHP‑FPM (pm.max_children) і зменшіть динамічні запити через кеш і специфічні пом’якшувальні заходи. Масштабування PHP без зменшення бот‑трафіку — це біг на місці.

Завдання 10: Підтвердити, чи WordPress бомблять через XML‑RPC

cr0x@server:~$ sudo awk '$7=="/xmlrpc.php" {count++} END{print count+0}' /var/log/nginx/access.log
9812

Що це означає: Трафік на XML‑RPC величезний. Часто це сміття.
Рішення: Якщо вам XML‑RPC не потрібен (Jetpack, деякі мобільні додатки, застарілі інтеграції) — блокувати його на edge або origin. Якщо потрібен — лімітувати і додати керовані виклики Cloudflare.

Завдання 11: Помітити спроби обходу кешу у вигляді унікальних query‑рядків на гарячих сторінках

cr0x@server:~$ sudo awk '$7 ~ /\?/ {print $7}' /var/log/nginx/access.log | head -5
/?utm_source=bot1
/?a=174563
/?rand=991827
/?__cf_chl_tk=abc123
/?q=cheap-seo

Що це означає: Боти використовують query‑строки, щоб обійти кеш або викликати нові ключі кешу.
Рішення: Нормалізуйте або ігноруйте марні query‑рядки на edge (Cloudflare Cache Rules) і лімітуйте підозрілі шаблони запитів.

Завдання 12: Ідентифікувати user‑agent’и за 429‑відповідями

cr0x@server:~$ sudo awk '$9==429 {print $12}' /var/log/nginx/access.log | tr -d '"' | sort | uniq -c | sort -nr | head -10
141 python-requests/2.31.0
88 Mozilla/5.0
61 curl/8.5.0
22 Go-http-client/1.1

Що це означає: Частина трафіку явно автоматизована (python-requests, curl), але деякі маскуються під браузери.
Рішення: Агресивно блокувати очевидну автоматизацію; браузероподібні UA обробляти обережніше і орієнтуватися на поведінку (частота, шляхи, невдалі входи) замість рядків агента.

Завдання 13: Підтвердити, що відновлення реального IP Cloudflare працює в Nginx

cr0x@server:~$ sudo nginx -T 2>/dev/null | sed -n '35,60p'
http {
    real_ip_header CF-Connecting-IP;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    real_ip_recursive on;
    ...
}

Що це означає: Nginx використовуватиме CF‑Connecting‑IP як IP клієнта, коли запити йдуть від довірених діапазонів проксі.
Рішення: Переконайтеся, що довірені діапазони повні й актуальні. Пропущені діапазони означають, що деякі POP‑и відображатимуться як «один IP», і ваш лімітер перетвориться на гільйотину.

Завдання 14: Перевірити iptables/nftables на грубі блоки чи ліміти

cr0x@server:~$ sudo nft list ruleset | sed -n '1,80p'
table inet filter {
  chain input {
    type filter hook input priority 0; policy accept;
    ip saddr 198.51.100.77 drop
  }
}

Що це означає: Є щонайменше один ручний блок. Він не генерує 429 (скидає пакети), але може пояснити «рандомні відмови», які неправильно інтерпретують.
Рішення: Краще блокувати на edge, коли можливо; блоки на origin теж прийнятні, але потрібен контроль змін, щоб випадково не відрубати власні сервіси.

Завдання 15: Швидко перевірити, чи 429 корелює з невдалими входами (credential stuffing)

cr0x@server:~$ sudo grep -E "wp-login\.php|authentication failed|Invalid username" /var/log/nginx/access.log | tail -n 5
198.51.100.77 - - [27/Dec/2025:10:11:52 +0000] "POST /wp-login.php HTTP/1.1" 429 169 "-" "python-requests/2.31.0"
198.51.100.77 - - [27/Dec/2025:10:11:50 +0000] "POST /wp-login.php HTTP/1.1" 429 169 "-" "python-requests/2.31.0"

Що це означає: Тротлінг пов’язаний із трафіком логінів. Це добре — якщо він не ловить реальних адміністраторів.
Рішення: Додайте потужніші механізми виявлення ботів, MFA і бажано винесіть логін за додаткові захисти (керовані виклики Cloudflare, allowlist для IP адміністраторів або окремий домен для адмінки).

Специфічні виправлення для Cloudflare, що не карають реальних користувачів

Cloudflare може виправити 80% подій 429, спричинених ботами, бо він зупиняє трафік ще до PHP.
Але він також може створити 80% квитків у саппорт, коли хтось з ентузіазмом увімкнув налаштування, як дитина, що клацає вимикачі.

Проєктування правил Cloudflare: будьте точними, а не відважними

Почніть з ендпоінтів, що заслуговують підозри:

  • /wp-login.php (POST — небезпечніший)
  • /xmlrpc.php (часто безпечніше блокувати повністю)
  • /wp-json/ (лімітуйте за методом і за токеном, якщо він є)
  • /wp-admin/admin-ajax.php (залежить від сайту; налаштовуйте обережно)

Змусьте лімітер Cloudflare відповідати вашим намірам

  • Лімітуйте POST суворіше, ніж GET. Люди переглядають; боти відправляють форми.
  • Використовуйте виклики (challenges) замість блокувань, коли помилкові спрацьовування шкодять доходам (оформлення замовлення, логін для учасників).
  • Розділяйте анонімний і аутентифікований трафік. Якщо можна ключувати за наявністю cookie — робіть це. Аутентифіковані сесії не мають ділитися одним відром із анонімними ботами.
  • Захищайте вебхуки. Платіжні шлюзи та колбеки SaaS краще allowlist‑ити по IP/провайдеру, або обмежувати окремо з вищими порогами.

Врахуйте реальність NAT і спільних IP

Обмеження по IP за замовчуванням — просте рішення. Воно також частіше помилкове, ніж ми визнаємо.
Зменшити побічні ушкодження можна так:

  • Встановлюйте вищі пороги для кінцевих точок, які легітимні користувачі можуть зачіпати у сплесках (assets, головна), і нижчі для чутливих ендпоінтів (логін, XML‑RPC).
  • Додавайте bot score / керовані виклики для підозрілої поведінки замість жорсткого 429 з першої помилки.
  • Винятки для відомих корпоративних egress IP застосовуйте лише коли впевнені і з хорошою причиною. «Бо продажники не можуть зайти з готельного Wi‑Fi» — погана причина.

Кешування Cloudflare як клапан від тиску ліміту

Якщо ви лімітуєте тому, що origin не витримує навантаження, ви використовуєте швейцара як конструкційного інженера.
Кешуйте статичне й кешоване динамічне на edge агресивно. Менше запитів дійдуть до PHP — менше причин ставити 429.

Жарт №2: Найкращий спосіб позбутися бот‑трафіку — зробити його проблемою когось іншого, бажано Cloudflare.

Виправлення на origin/сервері: Nginx, Apache, PHP-FPM і зворотні проксі

Nginx: лімітуйте лише те, що мали на увазі

limit_req у Nginx працює добре, якщо:

  • У вас правильні IP клієнтів (відновлення реального IP — обов’язково за проксі/CDN).
  • Ви обмежуєте шляхи, які справді чутливі.
  • Дозволяєте burst для людської поведінки (браузер швидко завантажує ресурси).

Типовий безпечніший підхід: визначайте зони по ендпоінтах. Не використовуйте одну «сайт‑широку» зону, якщо не любите квитки у підтримку.

Apache: уникайте «магічних модулів», яких не розумієте

mod_evasive та подібні інструменти можуть допомогти, але часто поводяться як сторожовий пес, навчений читати настрій.
Якщо ви їх використовуєте, переконайтеся, що можете спостерігати, кого й чому вони блокують.

Ланцюг зворотних проксі: переконайтеся, що ідентичність клієнта переживає шлях

Звичний ланцюг: Cloudflare → load balancer → Nginx → PHP‑FPM → WordPress.
Лімітування на будь‑якому рівні ланцюга має погоджуватися, що означає «клієнт». Якщо один шар бачить усі запити як від проксі, ваш лімітер трактуватиме інтернет як одну людину.

PHP‑FPM: не лікуйте симптоми заглушенням

Якщо PHP‑FPM на max children і черзі, ви вже в зоні ризику. Лімітування може запобігти повному колапсу, але все одно потрібно:

  • Виправити кешування (page cache, object cache, edge cache де можливо).
  • Усунути «гарячі», некешовані ендпоінти, які не повинні бути динамічними.
  • Зменшити кількість дорогих плагінів або запитів, що викидають CPU‑час на запит.

Виправлення в WordPress/додатку: логін, XML-RPC, REST API, плагіни

Припиніть ставити wp-login як публічний API

/wp-login.php — це вхід у адмінку. Це також найчастіше атакований ендпоінт на платформі. Практичні кроки:

  • Увімкніть MFA для всіх адміністраторів. Це не зменшить кількість запитів, але зменшить наслідки, якщо запит вдасться.
  • Обмежуйте спроби входу (обережно). Віддавайте перевагу інструментам, що інтегруються з Cloudflare або інтелектом IP, а не лише лічильниками по IP.
  • Розгляньте окремий hostname для адмінки з суворішими правилами Cloudflare або allowlist для доступу персоналу.

XML‑RPC: якщо не потрібен — блокувати

У 2025 році більшість сайтів не потребує XML‑RPC. Якщо ви не використовуєте функції Jetpack, віддалене публікування або застарілі інтеграції — блокувати /xmlrpc.php.
Якщо потрібен — лімітуйте й додайте керовані виклики Cloudflare. Не залишайте його відкритим і сподівайтесь, що плагін безпеки «порахує».

REST API: лімітуйте розумно й автентифікуйте правильно

REST API корисний і часто піддається зловживанню. Лімітуйте ендпоінти, що є ресурсно‑витратними або чутливими.
Якщо ви надаєте API партнерам/мобільним додаткам, зробіть окремий механізм автентифікації й лімітуйте за токеном, а не за IP.

admin-ajax.php: безшумна фабрика запитів

Багато тем і плагінів звертаються до /wp-admin/admin-ajax.php для функцій, які можна було б кешувати або віддати статично.
Один зламаний скрипт може бити по ньому повторно, і ваш лімітер із задоволенням заблокує всіх інших, хто намагається виконати динамічну дію.

Дія: ідентифікуйте, які дії викликаються часто, кешуйте відповіді, де безпечно, і перенесіть публічну функціональність у REST‑ендпоінти з кешуванням і кращою логікою тротлінгу.

Три міні-історії з корпоративного життя

Міні‑історія 1: Інцидент через хибне припущення

Середня компанія тримала портал на WordPress за Cloudflare. Вони додали Nginx‑лімітування, щоб «захистити логін», і інженер почувався впевнено. Ліміт був скромний — один запит на секунду з невеликим burst — застосований до /wp-login.php.

У понеділок вранці: наплив 429, але тільки для співробітників. Клієнти були майже не зачеплені. Саппорт загорівся, канал інцидентів заповнився, і хтось припустив: «Cloudflare знову впав», що нині еквівалент звинувачення ретроградного Меркурія.

Хибне припущення було просте: думали, що Nginx бачить реальні IP клієнтів. Ні. Логи Nginx показували один і той же IP для всіх запитів: egress Cloudflare.
Отже, лімітер трактував кожного співробітника (і деяких клієнтів) як одного клієнта, бо всі були з під тим самим проксі‑ідентифікатором.

Виправлення було теж простим і трохи прикрим: правильно налаштувати відновлення реального IP і підтвердити це в логах. Коли Nginx почав бачити реальні клієнтські IP, лімітер став інструментом, а не жартом.

Пост‑інцидентна дія: жодних змін у лімітуванні без кроку валідації, що перевіряє, чи ключ лімітеру відповідає ідентичності клієнта. Нудно. Надзвичайно ефективно.

Міні‑історія 2: Оптимізація, що відбилася боком

Інша команда хотіла швидшої адмінки. Вони ввімкнули агресивні правила кешування і підсилили безпеку Cloudflare. Додали правило: «Challenge будь‑якого, хто запитує /wp-admin/ більше N разів за хвилину». Здавалося логічним — адміни не повинні спамити сторінки адмінки.

Потім вони запустили новий плагін‑дашборд. Плагін використовував REST API і admin‑ajax для опитування кожні кілька секунд. У staging, з двома адмінами, ніхто не помітив. У production, під час квартального звітування, десятки співробітників одночасно відкрили дашборд.

Cloudflare побачив сплеск запитів до адмін‑ендпоінтів і почав виклики й лімітування. Потік викликів змусив плагін повторювати запити. Повтори підняли частоту. Частота викликала більше викликів. Їхня «оптимізація» створила петлю зворотного зв’язку, де кожна спроба користуватися UI підвищувала ймовірність блокування.

Остаточне виправлення полягало в тому, щоб припинити поліцію загальної швидкості адмін‑сторінок і натомість таргетувати небезпечну підмножину: невдалі входи та підозрілі POST. Також зменшили інтервал опитування плагіна і кешували важкі API‑відповіді. Адміни працювали, боти страждали, і система перестала їсти сама себе.

Міні‑історія 3: Нудна, але правильна практика, що врятувала

Рітейл‑бренд вів WooCommerce в масштабі з Cloudflare спереду. У них була практика, яка звучала нудно: щоквартально проводити «аудит формування трафіку».
Це був чекліст: підтвердити конфіг реального IP на origin, переглянути правила WAF/лімітів, перевірити allowlist вебхуків і виконати синтетичні тести на оформлення й логін.

Під час одного аудиту вони помітили повільне зростання 429 на /wp-json/. Нічого ще не ламалося. Але виявили шаблон:
інтеграції партнерів переходили з server‑to‑server викликів на мобільний SDK, що ділило IP через carrier NAT.

Оскільки були логи й базові показники, вони не чекали аварії. Підкоригували ліміти щоб ключуватися по API‑токенах, а не по IP, і створили окремі правила Cloudflare для аутентифікованих API‑клієнтів. Додали також Retry-After на origin для одного внутрішнього ендпоінта, щоб уникнути штурму повторних спроб.

Потім бот‑кампанія вдарила по логіну і пошуку товарів. Edge це прийняв на себе, origin залишився стабільним, і клієнти продовжували оформляти замовлення.
Ніхто не отримав трофей. Зате мав тихий вихідний.

Поширені помилки: симптом → корінна причина → рішення

Це режими відмов, які я бачу постійно. Вони поширені, бо правдоподібні. Але їх можна уникнути, якщо припинити гадати.

1) Симптом: «Усі отримують 429, навіть звичайне переглядання»

Корінна причина: сайт‑широке лімітування (або лімітування /) з надто низькими порогами; або лімітер ключує по IP проксі (всі користувачі виглядають однаково).

Вирішення: відновіть реальні IP клієнтів; обмежте ліміти до чутливих ендпоінтів; підвищте burst; виключіть статичні ресурси; підтвердіть роботу кешу.

2) Симптом: «Лише wp-admin не працює, фронтенд — ок»

Корінна причина: правило Cloudflare викликає challenge/ліміт для адмін‑ендпоінтів; або storms через admin‑ajax.

Вирішення: розділіть правила для логіна адміністратора і для перегляду адмінки; зменшіть polling; використовуйте керовані виклики лише там, де потрібно; allowlist IP персоналу лише якщо стабільна і керована політика.

3) Симптом: «Оформлення замовлення час від часу падає з 429»

Корінна причина: WAF/ліміти трактують POST‑запити оформлення як зловмисні; повтори вебхуків викликають сплески; тестування карт ботами.

Вирішення: винятки або тонке налаштування для шляхів checkout з вищими порогами; захист із виявленням ботів; розділення webhook‑ендпоінтів і allowlist відомих провайдерів; додати fraud‑контроли.

4) Симптом: «Клієнти REST API падають, сайт виглядає ок»

Корінна причина: обмеження по IP карає спільний NAT; API‑ключі не використовуються для формування політики; правила кешування Cloudflare не відповідають семантиці API.

Вирішення: лімітуйте за токеном; додайте окремий hostname для API; реалізуйте адекватний backoff клієнта з підтримкою Retry-After.

5) Симптом: «429 сплески відразу після ввімкнення плагіну безпеки»

Корінна причина: плагін агресивно блокує, або інтерпретує CDN IP як клієнтські, або тротлить admin‑ajax/REST запити, які використовує тема.

Вирішення: налаштуйте довірені проксі; виключайте внутрішні кінцеві точки; перегляньте доцільність плагіну. Якщо ви не можете пояснити його рішення — не використовуйте в продакшні.

6) Симптом: «429 лише для деяких регіонів / ISP»

Корінна причина: ці клієнти ділять egress IP; відмінності POP на edge; геоблок/ліміти по країні в Cloudflare.

Вирішення: проведіть аудит по COLO/регіонах Cloudflare; уникайте агресивних обмежень по країні; де можливо, використовуйте поведінкові правила замість географії.

Контрольні списки / покроковий план

Покроковий план: стабілізувати спочатку, потім виправити правильно

  1. Підтвердити, хто енфорсер: edge vs origin vs додаток (Завдання 1–3).
  2. Ідентифікувати ендпоінт: топ‑шляхи з 429 (Завдання 4).
  3. Підтвердити ідентичність клієнта: відновлення реального IP і логування (Завдання 6–7, Завдання 13).
  4. Класифікувати трафік: топ‑IP, UA, методи і чи це логін/REST/ajax (Завдання 5, Завдання 12, Завдання 15).
  5. Застосувати цільові пом’якшувальні заходи:
    • Блокувати або викликати /xmlrpc.php, якщо не використовується.
    • Лімітувати POST /wp-login.php з людяним burst.
    • Налаштувати ліміти для REST і admin‑ajax за методом і автентифікацією.
  6. Зменшити навантаження на origin: кешуйте, перевірте, що PHP‑FPM не постійно насичений (Завдання 9).
  7. Перевірити вплив на користувачів: тестуйте логін, оформлення, API‑виклики з реальних мереж (не лише з офісу).
  8. Збирайте докази: фіксуйте метрики до/після і зразки логів, щоб наступний інцидент не перетворився на фольклор.

Операційний чекліст: що змінювати (і чого уникати)

  • Робіть: лімітуйте чутливі ендпоінти (логін, XML‑RPC, окремі REST‑маршрути).
  • Робіть: розділяйте анонімний і аутентифікований трафік, де можливо.
  • Робіть: використовуйте керовані виклики для неоднозначного трафіку замість миттєвого блокування.
  • Робіть: забезпечуйте Retry-After, коли ви контролюєте 429 і клієнти можуть його дотримуватись.
  • Уникайте: тотальних per‑IP лімітів на / або всьому /wp-admin/, якщо не хочете навчати керівництво, що таке NAT.
  • Уникайте: впровадження нових WAF/ліміт‑правил без канаркового тестування і кнопки відкату.
  • Уникайте: «безпека через купу плагінів». Один добре зрозумілий шар краще за п’ять непрозорих.

Питання й відповіді (FAQ)

1) Чи 429 завжди означає проблему з ботами?

Ні. Часто це боти, але може бути легітимний трафік за NAT, петлі повторних спроб, агресивні монітори доступності або вебхуки, що повторюють через тротлінг.
Діагностуйте по логах перед тим, як звинувачувати «ботів».

2) Як зрозуміти, чи Cloudflare повертає 429?

Перевірте заголовки відповіді на наявність server: cloudflare, cf-ray і порівняйте з прямим запитом до origin (Завдання 1 і 2).
Якщо origin ніколи не бачить запиту — Cloudflare і є енфорсером.

3) Чому мої співробітники отримують 429, а клієнти — ні?

Часто тому, що співробітники ділять egress IP (офісний NAT/VPN). Лімітер по IP трактує їх як одного клієнта і тротлить.
Виправляйте відновлення реальних IP і налаштовуйте ліміти, або ключуйте по сесії/токену, коли можливо.

4) Чи просто вимкнути лімітування, щоб зупинити 429?

Тимчасово — можливо, якщо ви блокуєте реальних користувачів і йдеться про дохід. Але не залишайте так.
Правильний підхід — цільове лімітування і пом’якшення ботів, а не «вільний доступ для атакувальників».

5) Чи безпечно блокувати xmlrpc.php?

Для багатьох сайтів — так. Якщо ви покладаєтесь на Jetpack або застарілі мобільні/віддалені функції, блокування XML‑RPC може порушити функціональність.
Якщо сумніваєтесь — спочатку лімітуйте і викликайте, потім вимірюйте, чи щось легітимне використовує його.

6) Чи кешування може виправити 429?

Опосередковано — так. Кешування зменшує навантаження на origin, тож не потрібно суворих лімітів. Але кеш не зупинить brute‑force логіни чи зловживання API само по собі.
Використовуйте кеш плюс захист на рівні ендпоінтів.

7) Чому WooCommerce checkout викликає 429?

Оформлення включає POST‑запити, кроки платежів і іноді сторонні виклики. Правила WAF можуть помилково класифікувати це як зло, а боти тестують карти.
Налаштуйте особливі правила для шляху checkout і захищайте від bot‑fraud окремими механізмами.

8) Який найкращий ключ для лімітеру: IP, cookie чи токен?

Для анонімного перегляду IP прийнятний при розумних burst і виявленні ботів. Для API й аутентифікованих користувачів краще лімітувати за токеном/сесією.
Лімітування лише по IP — крихке в світі повному NAT і мобільних мереж.

9) Чому бачу 429 у браузері, але не в логах origin?

Бо щось upstream (Cloudflare, load balancer, WAF) генерує його до того, як запит дійде до origin. Підтвердіть через перевірку заголовків і тести обходу origin.

10) Чи мають 429 включати Retry-After?

Якщо ви контролюєте відповідь і клієнти можуть її поважати — так. Це зменшує шторм повторних спроб і робить тротлінг передбачуванішим.
Для браузерів це менш корисно; для API‑клієнтів і вебхуків — важливо.

Висновок: практичні наступні кроки

Виправлення помилок WordPress 429 — не «вмикай випадкові налаштування безпеки, поки червона стрічка не зникне». Це трасування рішення через стек і роблення його розумнішим.
Найкращий результат — не нуль 429. Найкращий результат — 429, направлені на боти навмисно, при цьому реальні користувачі цього не помічають.

  1. Пройдіть швидкий план діагностики: підтвердьте, хто емулює 429 і які ендпоінти це викликають.
  2. Переконайтеся, що обробка реальних IP працює наскрізь. Якщо це неправильно — все інше театрально.
  3. Застосуйте цільові захисти: challenge/ліміт для POST /wp-login.php, блок/тротл для /xmlrpc.php, тонке налаштування REST/admin‑ajax за методом і автентифікацією.
  4. Зменште навантаження на origin завдяки кешу й налаштуванню PHP‑FPM, щоб ліміти були опорою, а не милицею.
  5. Запишіть правила і мотивацію. Майбутній ви — інша людина і не заслуговує ваших загадок.
← Попередня
Міграція VM з ESXi в Proxmox без vCenter: експорт OVF/OVA, імпорт і виправлення драйверів
Наступна →
ZFS dRAID: Швидше відновлення — чи просто швидша складність?

Залишити коментар