WordPress: Надто багато перенаправлень — як виправити цикли www/https/Cloudflare

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

Ви змінили «одну дрібну налаштування» — можливо переключили SSL у Cloudflare, примусили HTTPS або поміняли www — і тепер сайт відскакує як кулька: браузер показує Надто багато перенаправлень, вхід не тримається, а моніторинг доступності прислав лекцію у віршах.

Цикли перенаправлень рідко таємничі. Це просто розподілені системи, які роблять те, що ви їм наказали, у чотирьох різних місцях, у невірному порядку. Розберемо це за виробничими діагностичними кроками, а не випадковими кліками.

Що насправді означає «Надто багато перенаправлень»

Браузер звертається за URL, отримує 301/302/307/308 перенаправлення, йде за ним і продовжує отримувати перенаправлення, поки не досягне ліміту (зазвичай близько 20–30 переходів). Помилка — це механізм браузера, який захищає від нескінченого циклу. Цикл може виникнути на кількох рівнях:

  • Додаток: WordPress вважає, що має бути HTTPS або www, тому виписує редиректи.
  • Вебсервер: правила перепису Nginx/Apache примушують HTTPS або канонічний хост, часто з регулярним виразом, що ловить усе.
  • Edge/CDN: Cloudflare «Always Use HTTPS», Transform Rules, Page Rules або Workers перенаправляють ще до того, як досягнуто origin.
  • Балансувальник навантаження / зворотний проксі: TLS-термінація + відсутні проксі-заголовки змушують origin думати, що запит — HTTP, навіть якщо клієнт використовує HTTPS.

Цикли зазвичай відповідають одному з таких патернів:

  • HTTP ↔ HTTPS «піонг-понг»: Edge каже «вимагай HTTPS», origin каже «ні, повертайся на HTTP».
  • www ↔ кореневий домен «піонг-понг»: Один шар примушує www, інший — без www.
  • Перехрестя схеми і хоста: HTTPS non-www → HTTPS www → HTTP www → HTTP non-www → …
  • Цикли з куками/сесіями: особливо навколо /wp-admin або оформлення замовлення WooCommerce, коли захищені куки і виявлення схеми не співпадають.

Надійна модель для розуміння: цикл перенаправлень — це конфлікт політики канонізації, розподілений між системами, які не діляться станом.

Топологія циклу перенаправлень: де народжується цикл

Дебаг перенаправлень швидший, якщо ви нанесете шлях запиту на карту:

  1. Клієнт → край Cloudflare (правила, режим SSL, поведінка HSTS, кеш)
  2. Cloudflare → Origin (схема, якою Cloudflare підключається, заголовки, які він додає)
  3. Front door origin (vhost правила Nginx/Apache та переписування)
  4. PHP/WordPress (SiteURL/Home, wp_redirect(), плагіни, логіка is_ssl())
  5. Назовні (заголовки Location переписуються? закешовано? змішано?)

Коли ви бачите «Надто багато перенаправлень», ви не шукаєте «ту налаштування». Ви шукаєте дві суперечливі думки про канонічний URL. Приберіть одну думку.

Швидкий план діагностики

Якщо ви на виклику, часу на філософію немає. Робіть це в такому порядку.

1) Спостерігайте ланцюжок перенаправлень іззовні

Використайте інструмент, який показує кожен хоп, схему, хост і код статусу. Мета: визначити точку перемикання, де відбувається фліп (http→https або www→apex).

2) Визначте, чи бере участь Cloudflare

Якщо відповіді містять заголовки Cloudflare (або ваш DNS проксовано «оранжево»), припускайте, що Cloudflare може переписувати або кешувати редиректи. З’ясуйте налаштований режим SSL і будь-які функції «примусу HTTPS».

3) Обійдіть Cloudflare, щоб протестувати поведінку origin

Зверніться безпосередньо до origin (або через hosts override) з тим самим заголовком Host. Якщо сам origin зациклюється — виправляйте origin/WordPress. Якщо origin чистий, цикл на Cloudflare (або між Cloudflare і origin через невідповідність режиму SSL).

4) Визначте одну політику канонічного URL

Виберіть точно один канонічний хост (www або apex) і точно одну схему (HTTPS). Потім застосуйте це в одному місці — краще на краю або на вебсервері, а не у WordPress плюс три плагіни.

5) Перевірте проксі-заголовки і виявлення схеми WordPress

Якщо TLS завершується до origin, WordPress має дізнатись початкову схему через заголовки на кшталт X-Forwarded-Proto. Без цього WordPress думає, що запит — HTTP і «дбайливо» перенаправляє на те, що вважає правильним.

6) Очистіть кеші, що запам’ятали неправильний редирект

Cloudflare може кешувати редиректи. Так само браузери та плагіни кешування WordPress. Ваше виправлення може бути вірним і водночас здаватися зламаним, поки кеші не очистять або не обійдуть.

Цікаві факти і контекст (бо історія повторюється)

  • Факт 1: HTTP-заголовок Host (віртуальний хостинг) став масовим у кінці 1990-х; до того багато серверів припускали один сайт на IP. Редиректи залежно від хосту стали набагато поширенішими після цього.
  • Факт 2: 301 (Moved Permanently) часто кешують браузери й посередники. Поганий 301 може переслідувати вас довше, ніж поганий 302.
  • Факт 3: Режим Cloudflare «Flexible» існує для сайтів без TLS на origin, але це класичний спосіб створити HTTP↔HTTPS цикл, коли origin змушує HTTPS.
  • Факт 4: WordPress історично зберігав канонічні URL у двох опціях — siteurl і home — і їхнє невідповідання досі один із найшвидших способів вигадати цикл.
  • Факт 5: HSTS не робить редиректи через відповіді сервера; він апгрейдить запити всередині браузера. Це добре для безпеки й водночас породжує плутанину «чому він все ще йде на https?».
  • Факт 6: Статуси редиректів змінились з очікуваннями HTTP/1.1: 307 і 308 введено для збереження семантики методу (POST лишається POST). Деякі проксі все ще некоректно обробляють їх у крайніх випадках.
  • Факт 7: Ранні практики «примусити SSL в адмінці» у WordPress передували загальним TLS-термінуючим проксі; багато фрагментів коду припускають, що origin бачить HTTPS, і ламаються за сучасних балансувальників навантаження.
  • Факт 8: CDN починали як прискорювачі статичного контенту; тепер вони надають повну логіку запит/відповідь (Workers, edge rules). Це потужність — і ще три місця, де випадково можна додати редирект.

Одна оперативна цитата, яку варто тримати на стікері:

перефразована ідея — John Allspaw: «Безвинні постінцидентні розбори працюють, бо фокусуються на тому, як система зробила можливим збій, а не на тому, хто натиснув кнопку.»

Практичні завдання: команди, очікуваний результат і рішення

Ці завдання — основа реальної діагностики. Кожне включає (a) команду, (б) що означає вихід, (в) наступне рішення. Виконуйте їх з шелу, яким ви контролюєте.

Завдання 1: Отримати ланцюжок редиректів (тільки заголовки)

cr0x@server:~$ curl -sS -I -L -o /dev/null -w '%{url_effective}\n%{http_code}\n' https://example.com
https://www.example.com/
200

Значення: З -L curl пройшов редиректи. Effective URL — куди ви припинили. Код HTTP в кінці — фінальна відповідь.

Рішення: Якщо ви ніколи не дістаєтесь 200 і curl видає «maximum redirects followed», зафіксуйте повний список хопів далі (Завдання 2). Якщо ви опиняєтесь на іншому хості/схемі, ніж очікували, знайдіть, де відбувається канонізація.

Завдання 2: Вивести кожен хоп (заголовки Location)

cr0x@server:~$ curl -sS -D - -o /dev/null http://example.com | sed -n '1,20p'
HTTP/1.1 301 Moved Permanently
Date: Fri, 26 Dec 2025 12:00:00 GMT
Location: https://example.com/
Server: cloudflare
CF-RAY: 8abc1234abcd1234-LHR

Значення: Ви бачите, чи редирект згенеровано Cloudflare (Server header, CF-RAY) чи origin.

Рішення: Якщо Cloudflare видає редирект — перевіряйте правила/режим SSL Cloudflare першочергово. Якщо ні — йдіть у конфіг origin.

Завдання 3: Попросити curl показати весь слід редиректів

cr0x@server:~$ curl -sS -o /dev/null -w '%{http_code} %{redirect_url}\n' -I https://example.com
301 https://www.example.com/

Значення: Сервер повернув редирект, і curl показує вам наступний URL.

Рішення: Якщо redirect_url несподівано змінює схему/хост, визначте, який шар відповідає, обійшовши Cloudflare (Завдання 6/7).

Завдання 4: Перевірити, чи браузер робить HSTS-апгрейди (з боку сервера, інферувати)

cr0x@server:~$ curl -sS -I https://example.com | grep -i strict-transport-security
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

Значення: HSTS увімкнено. Браузери можуть примусово використовувати HTTPS, навіть якщо ви вводите HTTP.

Рішення: Якщо ви тестуєте поведінку HTTP, не довіряйте звичайній сесії браузера. Використайте curl, свіжий профіль браузера або тимчасово видаліть HSTS після стабілізації сайту (обережно).

Завдання 5: Розв’язати DNS, щоб підтвердити, що ви справді використовуєте Cloudflare

cr0x@server:~$ dig +short example.com
104.21.12.34
172.67.98.76

Значення: Це схоже на Cloudflare anycast IP (не завжди, але часто). Якщо ви бачите IP origin — ви можливо не проксовані.

Рішення: Якщо проксовано — параметри Cloudflare мають значення. Якщо DNS вказує на origin — зосередьтеся на origin/WordPress.

Завдання 6: Обійти Cloudflare, звернувшись до origin IP з заголовком Host

cr0x@server:~$ curl -sS -I --resolve example.com:80:203.0.113.10 http://example.com
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
Server: nginx

Значення: --resolve змушує curl говорити з origin IP, зберігаючи Host: example.com. Це найчистіший тест «Cloudflare — проблема?».

Рішення: Якщо сам origin редиректить у цикл (повторіть для HTTPS також), виправляйте origin/WordPress. Якщо origin повертає 200 чисто, а шлях через Cloudflare зациклюється — налаштовуйте Cloudflare.

Завдання 7: Тестувати HTTPS origin напряму (сертифікат може не збігатися)

cr0x@server:~$ curl -sS -I -k --resolve example.com:443:203.0.113.10 https://example.com
HTTP/1.1 200 OK
Server: nginx

Значення: -k ігнорує валідацію сертифіката. Ви тестуєте поведінку, а не коректність PKI.

Рішення: Якщо HTTPS до origin повертає 200, але Cloudflare у «Flexible» підключається по HTTP, ви знайшли невідповідність. Переключіть режим SSL Cloudflare (деталі нижче).

Завдання 8: Інспектувати припущення Cloudflare→origin щодо схеми через заголовки на origin

cr0x@server:~$ sudo tail -n 3 /var/log/nginx/access.log
198.51.100.23 - - [26/Dec/2025:12:01:02 +0000] "GET / HTTP/1.1" 301 169 "-" "Mozilla/5.0" "https"
198.51.100.23 - - [26/Dec/2025:12:01:03 +0000] "GET / HTTP/1.1" 301 169 "-" "Mozilla/5.0" "http"

Значення: Багато форматів Nginx включають $scheme або forwarded proto поля. Якщо ви бачите чергування «http» і «https» для тієї ж клієнтської подорожі, ви в зоні піонг-понгу.

Рішення: Виправте примус схеми в одному шарі, і переконайтесь, що forwarded-proto вшановується WordPress.

Завдання 9: Перевірити WordPress SiteURL і Home (WP-CLI)

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ wp option get siteurl
http://www.example.com
cr0x@server:~$ wp option get home
https://example.com

Значення: Вони не повинні конфліктувати. Тут вони не погоджуються за схемою та хостом одночасно.

Рішення: Вирішіть канонічний URL (наприклад https://example.com) і встановіть обидва на нього (Завдання 10). Також перевірте будь-які захардкоджені редиректи в конфіг сервера.

Завдання 10: Безпечно виправити WordPress SiteURL/Home (WP-CLI)

cr0x@server:~$ wp option update siteurl 'https://example.com'
Success: Updated 'siteurl' option.
cr0x@server:~$ wp option update home 'https://example.com'
Success: Updated 'home' option.

Значення: WordPress тепер погодився сам із собою. Це прибирає одне з джерел редиректів.

Рішення: Повторно протестуйте ланцюжок редиректів (Завдання 1/2). Якщо цикл лишається — шукайте інші шари (Cloudflare або вебсервер).

Завдання 11: Знайти хардкодовані WP_HOME/WP_SITEURL в wp-config.php

cr0x@server:~$ grep -nE "WP_HOME|WP_SITEURL" /var/www/html/wp-config.php
82:define('WP_HOME', 'https://www.example.com');
83:define('WP_SITEURL', 'https://www.example.com');

Значення: Ці константи перевизначають опції в базі. Оновлення через WP-CLI не матиме ефекту, якщо вони задані.

Рішення: Відредагуйте їх до канонічного URL або видаліть, якщо хочете контролювати через БД. Потім повторно протестуйте.

Завдання 12: Перевірити симптоми режиму SSL Cloudflare, спостерігаючи схему в Location

cr0x@server:~$ curl -sS -I https://example.com | egrep -i 'HTTP/|location:|server:'
HTTP/2 301
location: http://example.com/
server: cloudflare

Значення: Ви запросили HTTPS, Cloudflare відповів редиректом на HTTP. Це майже завжди правило або неправильна каноналізація на edge/origin.

Рішення: Перевірте «Always Use HTTPS», Redirect Rules та режим SSL у Cloudflare. Також перевірте, чи origin не переписує заголовки Location дивним чином.

Завдання 13: Nginx: перелічити блоки server і шукати return/rewrite

cr0x@server:~$ sudo nginx -T 2>/dev/null | egrep -n "server_name|return 301|rewrite" | head
123:    server_name example.com www.example.com;
140:    return 301 https://$host$request_uri;

Значення: У вас є універсальний редирект на HTTPS, що використовує $host. Якщо інший шар змінює хост, ви можете зациклитися.

Рішення: Канонізуйте хост явно (виберіть один), замість віддзеркалення $host, і переконайтесь, що налаштування Cloudflare узгоджені.

Завдання 14: Apache: знайти RewriteRule, що примушує схему/хост

cr0x@server:~$ sudo apachectl -t -D DUMP_VHOSTS | head
VirtualHost configuration:
*:80                   example.com (/etc/apache2/sites-enabled/000-default.conf:1)
*:443                  example.com (/etc/apache2/sites-enabled/default-ssl.conf:2)
cr0x@server:~$ grep -RIn "RewriteRule|RewriteCond|Redirect " /etc/apache2/sites-enabled | head
/etc/apache2/sites-enabled/000-default.conf:12:RewriteCond %{HTTPS} !=on
/etc/apache2/sites-enabled/000-default.conf:13:RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Значення: Це примушує HTTPS на основі Apache-нього %{HTTPS}. За проксі Apache може не бачити, що TLS увімкнено.

Рішення: Навчіть Apache довіряти forwarded proto або робіть термінацію TLS в Apache. Інакше він буде постійно редиректити, навіть якщо клієнт уже на HTTPS.

Завдання 15: Підтвердити, що WordPress вважає схему запиту (PHP-скрипт через wp-cli eval)

cr0x@server:~$ wp eval 'var_export([ "is_ssl" => is_ssl(), "https_server" => $_SERVER["HTTPS"] ?? null, "xfp" => $_SERVER["HTTP_X_FORWARDED_PROTO"] ?? null ]);'
array (
  'is_ssl' => false,
  'https_server' => NULL,
  'xfp' => 'https',
)

Значення: WordPress бачить X-Forwarded-Proto: https, але is_ssl() все ще false, залежно від того, як сервер/PHP обробляє змінні.

Рішення: Реалізуйте довірливу обробку проксі, щоб WordPress інтерпретував forwarded proto правильно (деталі в розділі про WordPress/проксі). Якщо не можете цього безпечно зробити, примусовуйте каноналізацію на краю і тримайте origin консистентним.

Завдання 16: Підтвердити, що кеш Cloudflare не віддає старий редирект

cr0x@server:~$ curl -sS -I https://example.com | egrep -i 'cf-cache-status|age|location|http/'
HTTP/2 301
location: https://www.example.com/
cf-cache-status: HIT
age: 834

Значення: Cloudflare віддає кешований редирект. Можливо, ваш origin уже виправлено.

Рішення: Очистіть відповідний кеш у Cloudflare і переконайтесь, що новий канонічний редирект правильний перед повторним включенням кешування.

Жарт 1: Цикли редиректів — єдиний тип «нескінченної масштабованості», якого більшість WordPress-сайтів досягає без зусиль.

Специфічні причини в WordPress: SiteURL, Home, куки та адмін

1) Невідповідність SiteURL vs Home

WordPress використовує два URL, що звучать як синоніми, бо були винайдені в різні епохи для трохи різних цілей:

  • siteurl: де лежать файли ядра WordPress (wp-admin, wp-includes).
  • home: публічний корінь сайту.

У більшості інсталяцій вони мають бути однаковими. Якщо вони розходяться за схемою або хостом, WordPress може «виправляти» себе редиректами. Коли є проксі/CDN, це виправлення може зіткнутися з іншими виправленнями.

Робіть: встановіть обидва на канонічний URL, якщо ви справді не запускаєте ядро WordPress у підкаталозі.

Уникайте: виправляти це лише в БД, коли wp-config.php перекриває значення, або навпаки. Виберіть одне джерело правди.

2) FORCE_SSL_ADMIN і «допоміжні» плагіни безпеки

define('FORCE_SSL_ADMIN', true); примушує SSL у адмінці. Це нормально, коли origin бачить HTTPS. Це генератор циклів, коли TLS завершується в Cloudflare або балансувальнику і origin бачить plain HTTP.

Багато плагінів безпеки дублюють цю поведінку, іноді власною логікою редиректів або встановленням куків з прапором Secure, тоді як додаток вважає, що це HTTP. Так виникають цикли входу, коли облікові дані приймаються, але сесія ніколи не закріплюється.

3) WordPress за зворотним проксі: зробіть визначення схеми нудним

Якщо запити доходять до origin по HTTP, але користувач на HTTPS, WordPress має знати, що «реальна» схема — HTTPS. Зазвичай це через:

  • X-Forwarded-Proto: https
  • CF-Visitor: {"scheme":"https"} (Cloudflare)

У ідеальному світі ваш вебсервер встановлює $_SERVER['HTTPS']='on', коли він довіряє проксі-заголовкам. У реальному світі вам треба явно це підключити і обмежити довіру відомими IP проксі. Інакше ви дасте зловмисникам можливість «прикинутися https» і створите вразливість.

4) Куки та domain/secure прапори

Цикли перенаправлень навколо входу часто виникають тому, що куки обмежені іншим доменом, ніж поточний хост. Наприклад: cookie встановлено для www.example.com, а користувача редиректить на example.com. WordPress не бачить cookie, думає, що ви не увійшли, редиректить знову — і так по колу.

Подібно, якщо браузер надсилає Secure-куки лише по HTTPS, але щось переключає вас на HTTP у ланцюгу, ви втрачаєте сесію й потрапляєте в цикл, що виглядає як «не можу залишитись увійденим».

Специфічні причини в Cloudflare: режими SSL, правила та кешування

1) Режими SSL/TLS Cloudflare: фабрика циклів

У Cloudflare є кілька режимів SSL між відвідувачем↔Cloudflare і Cloudflare↔origin. Відомий режим провалу:

  • Cloudflare «Flexible»: відвідувач підключається по HTTPS до Cloudflare, але Cloudflare підключається до origin по HTTP.
  • Ваш origin (або WordPress) налаштований на примусове HTTPS.
  • Origin відповідає 301 Location: https://example.com.
  • Cloudflare отримує цю URL… але все одно продовжує використовувати HTTP до origin (через Flexible), отримує HTTPS-редирект знову — цикл відбувається з корпоративним ентузіазмом.

Виправлення: Не використовуйте Flexible для WordPress, якщо ви примушуєте HTTPS на origin. Використовуйте «Full» або «Full (strict)» з дійсним сертифікатом на origin. Якщо поки не можете цього зробити — припиніть примушувати HTTPS на origin і нехай Cloudflare обробляє це (але це має компроміс у безпеці).

2) «Always Use HTTPS» плюс redirects на origin

Подвійне примусове застосування не завжди шкідливе, але підвищує складність. Якщо Cloudflare примушує HTTPS, а ваш origin також примушує HTTPS на основі невірного виявлення схеми, ви все одно можете зациклитися.

Мій префер: примушувати схему на краю, а origin налаштувати так, щоб він обслуговував обидва протоколи без редиректів (або редиректив лише тоді, коли origin впевнено бачить правильну схему). Це знижує навантаження на origin і тримає каноналізацію в одному шарі.

3) Правила www/non-www: оберіть один канонічний хост

Cloudflare може робити редиректи хостів через правила. Origin теж може. WordPress теж (залежно від збережених URL). Якщо дозволити всім трьом це робити, ви практично запрошуєте розбіжність о 2:00 ранку.

Оберіть одне:

  • Опція A (каноналізація на краю): Cloudflare обробляє www↔apex і HTTP→HTTPS. Origin повертає контент без «допоміжних» редиректів.
  • Опція B (каноналізація на origin): Nginx/Apache робить канонічні редиректи. Cloudflare просто проксує і кешує.

Я схиляюсь до Опції A, коли Cloudflare стоїть перед сайтом, бо це зменшує запити до origin і уникає участі PHP. Але робіть це чисто і уникайте кешування поганих редиректів.

4) Кешовані редиректи і театр «все ще зламано»

Cloudflare може кешувати 301/302. Браузери можуть агресивно кешувати 301. Якщо ви один раз протестували — ви можете отруїти свої результати.

Оперативно ви хочете підтвердити поведінку з заголовками, що руйнують кеш, або з чистого середовища. І коли виправляєте — очищайте edge-кеш після перевірки нової поведінки; занадто раннє очищення лише підсилює радіус впливу невірного фіксу.

5) Workers і Transform Rules: тихі автори редиректів

У корпоративних налаштуваннях цикл перенаправлень іноді не чекбокс. Це Worker, розгорнутий шість місяців тому, щоб нормалізувати URL або ставити куки. Workers можуть переписувати заголовки Location, змінювати схеми і робити умовні редиректи на основі заголовків і гео. Це потужно.

І саме тому ваш аргумент «я перевірив Page Rules» не справить враження на ваше майбутнє “я”.

Конфігурації Nginx/Apache, що підводять

Nginx: пастка дзеркала $host

Це поширено і часто неправильне у багатошарових розгортаннях:

  • return 301 https://$host$request_uri;

Якщо вхідний Host іноді www, іноді apex (бо попередній шар переключає), ви віддзеркалюєте цей Host і зберігаєте конфлікт. Краще: робити редирект явно на ваш канонічний хост, а не на те, що прийшло.

Nginx: виявлення схеми за проксі

Коли Nginx знаходиться за проксі, $scheme — це схема між проксі і origin, а не між користувачем і edge. Якщо Cloudflare підключається по HTTP, $schemehttp, хоча користувач на HTTPS. Якщо ви пишете редиректи на основі $scheme, ви можете редиректити HTTPS-користувачів на HTTPS (добре), але робити це вічно (погано), залежно від того, як проксі реплеїть заголовки.

Apache: RewriteCond %{HTTPS} !=on не враховує проксі

%{HTTPS} в Apache відображає, чи Apache сам провів TLS-зустріч. Якщо TLS завершується вище по ланцюгу, він буде off. Apache тоді перенаправить на HTTPS — хоча користувач уже на HTTPS. З проксі, що підключається по HTTP, це може зациклитися.

Правильне рішення — проксі-обізнана конфігурація (і, що критично, обмеження довіри до IP проксі).

Жарт 2: Найшвидший спосіб знайти всі правила редиректу у стеку — зламати продакшн і почекати, поки п’ять команд присягнуть, що вони нічого не додавали.

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

Ось шаблони, що найчастіше трапляються, з конкретними діями для виправлення.

1) Симптом: HTTPS-запит редиректить на HTTP (або постійно фліппить)

Корінь: правило Cloudflare, що примушує HTTP, неправильна конфігурація канонічних редиректів на origin, або взаємодія Flexible SSL з примусовим HTTPS на origin.

Виправлення: Використовуйте Cloudflare «Full»/«Full (strict)» коли origin примушує HTTPS. Видаліть будь-яке правило на edge, що редиректить на HTTP. Переконайтесь, що origin не генерує HTTP Location.

2) Симптом: apex редиректить на www, а www редиректить на apex

Корінь: конкуруючі правила канонічного хоста на різних шарах (Cloudflare + Nginx + WordPress). Або невідповідність SiteURL/Home в WordPress.

Виправлення: Виберіть один канонічний хост. Реалізуйте рівно одне правило редиректу (переважно на edge або вебсервері). Встановіть WordPress home і siteurl на канонічний хост.

3) Симптом: /wp-admin постійно редиректиться на /wp-admin/ (або на логін) без кінця

Корінь: WordPress неправильно визначає HTTPS, що спричиняє невідповідність захищених куків/сесій. Іноді ускладнюється плагінами кешування.

Виправлення: Переконайтеся, що forwarded proto довіряється і відображається так, щоб is_ssl() було правильним. Вимкніть кешування для адмін-путів. Перевірте domain куки і канонічний хост.

4) Симптом: Працює, коли Cloudflare призупинено (тільки DNS), fails коли проксовано

Корінь: правила/режим SSL Cloudflare/кешований редирект або origin очікує прямий TLS.

Виправлення: Узгодьте режим SSL («Full strict» ідеально), перегляньте правила на edge, очистіть кешовані редиректи.

5) Симптом: Лише деякі користувачі бачать цикл; інші в порядку

Корінь: кешований 301 у браузері, HSTS, гео-специфічна логіка edge або різні POPи з несумісним кешем.

Виправлення: Тестуйте з curl і чистим профілем браузера. Очистіть edge-кеш. Переконайтеся щодо HSTS і уникайте перемикань схем під час ремедіації.

6) Симптом: Цикл з’явився після вмикання «Always Use HTTPS» або плагіна SSL у WordPress

Корінь: дублююче примусове застосування плюс неправильне визначення схеми проксі.

Виправлення: Видаліть одного з примусників. Якщо Cloudflare примушує HTTPS, вимкніть плагін SSL у WordPress і приберіть зайві серверні редиректи, якщо вони не потрібні.

Три корпоративні міні-історії з полів бою перенаправлень

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

В компанії був WordPress маркетинговий сайт за Cloudflare і керованим балансувальником навантаження. Розробник увімкнув плагін безпеки, який «примушував HTTPS скрізь». Зміна пройшла, бо звучала очевидно правильно, а стейджинг не мав такого шляху проксі.

За декілька хвилин головна сторінка стала недоступною в браузерах. Моніторинг показав сплеск 301 відповідей. Інженер на виклику зробив класичну перевірку: звернення до origin — гаразд. Через Cloudflare — цикл редиректів.

Хибне припущення було тонким: вони вірили, що origin побачить HTTPS, коли користувач використовує HTTPS. Ні. TLS завершувався на балансувальнику, а з балансувальника до origin йшов HTTP. WordPress глядав у $_SERVER['HTTPS'], нічого не бачив і виписував редиректи на HTTPS. Cloudflare (у Flexible) теж говорив HTTP до origin і ганявся за редиректом вічно.

Виправлення було нудним і миттєвим: переключити режим SSL Cloudflare на Full, додати дійсний origin-сертифікат і вимкнути функцію редиректу в плагіні. Довгострокове виправлення — рукописуємий план власності на канонізацію (edge) і політика довіри проксі на origin.

Міні-історія 2: Оптимізація, що повернулась бумерангом

Команда хотіла «зменшити навантаження на origin», кешуючи більше на Cloudflare. Хтось дозволив кешування HTML і кешування 301 відповідей. Це працювало — поки не перестало.

Через тиждень маркетинг змінив канонічний хост з www на apex. Вони оновили URL в WordPress і додали редирект на hості на edge. В одному браузері все добре. Потім почали надходити скарги: половина світу все ще редиректиться на старий хост і далі відскакує, досягаючи ліміту редиректів.

Повернення бумерангу було не через само кешування; воно полягало в кешуванні не того в неправильний час. Cloudflare закешував старі редиректи в різних POPах. Деякі клієнти теж назавжди зберегли 301. Система стала неконсистентною: різні користувачі отримували різну «правду» про канонічний URL, що підживлювало власну логіку редиректів WordPress і доменні куки.

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

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

Інша організація підтримувала кілька WordPress-проєктів з типовим шаблоном edge/origin. Нічого особливого: документ з політикою канонічного URL, обов’язкова «перевірка ланцюга редиректів» під час рев’ю змін і маленький скрипт, що валідував обидва www і apex по HTTP та HTTPS перед деплоєм.

Одної п’ятниці міграція DNS перемістила домен в інший акаунт Cloudflare. Новий акаунт мав правило за замовчуванням: «Always Use HTTPS». Origin вже примушував HTTPS, але робив це в Apache з %{HTTPS} !=on. За Cloudflare Apache ніколи не бачив HTTPS. Це мав би стати класичним циклом.

Але інциденту не сталося, бо їхні перевірки до релізу миттєво це виявили. Скрипт показав, що ланцюг редиректів не доходить до 200. Вони заблокували зміну, налаштували Apache бути проксі-обізнаним (і обмежили довіру), а вже потім ввімкнули правило на edge.

Урок нудний, але правдивий: найкраще виправлення редиректів — не допускати появи циклу в релізі. Це не гламурно. Це надійно.

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

Крок 0: Визначте політику канонічного URL (не пропускайте)

  • Канонічна схема: HTTPS.
  • Канонічний хост: оберіть або example.com або www.example.com.
  • Один шар для примусового застосування: edge або origin (не обидва, якщо ви не розумієте їхню взаємодію).

Крок 1: Зафіксуйте матрицю редиректів (4-way тест)

Протестуйте всі комбінації і запишіть, куди кожна потрапляє:

  • http + apex
  • http + www
  • https + apex
  • https + www

Всі чотири повинні закінчуватися точно на одному канонічному URL у 0–2 переходи.

Крок 2: Спочатку виправте режим SSL Cloudflare, коли Cloudflare перед сайтом

  • Якщо origin підтримує TLS: використовуйте Full (strict) коли можливо; інакше Full.
  • Уникайте Flexible, коли origin примушує HTTPS.

Крок 3: Приберіть дубльовану логіку редиректів

  • Вимкніть плагіни WordPress, що «примушують SSL», якщо edge/origin вже це обробляє.
  • Приберіть конфліктні правила перепису Nginx/Apache, що примушують хост, якщо Cloudflare робить це.
  • Тримайте WordPress SiteURL/Home в узгодженні з канонічним URL.

Крок 4: Зробіть origin проксі-обізнаним (безпечно)

  • Переконайтесь, що origin встановлює правильну схему на основі довірених проксі-заголовків.
  • Обмежте довіру відомими діапазонами IP проксі (Cloudflare IPs і ваш балансувальник).
  • Перевірте, що is_ssl() повертає true для HTTPS-трафіку користувачів.

Крок 5: Очистіть кеші і повторно протестуйте

  • Очистіть кеш Cloudflare для сайту (або принаймні кешовані редиректи).
  • Обійдіть кеш браузера (новий профіль / інкогніто не завжди достатньо для HSTS).
  • Повторно запустіть curl-тести і переконайтесь, що фінальний URL стабільний.

Крок 6: Додайте запобіжник у CI/рев’ю змін

  • Додайте автоматизований тест ланцюга редиректів для 4-way матриці.
  • Блокувати зміни, якщо будь-який шлях перевищує 2 редиректи або ніколи не досягає 200/403/401 очікуваних кінцевих точок.

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

1) Чому WordPress редиректить, навіть якщо я не налаштовував редиректи?

WordPress примушує канонічні URL на основі збережених home/siteurl і інтерпретації запиту. Він може редиректити на «правильний» хост/схему, особливо для адмін-путів.

2) Який найшвидший спосіб визначити, чи Cloudflare є джерелом редиректу?

Перевірте заголовки відповіді на наявність маркерів Cloudflare (наприклад CF-RAY), а потім обійдіть Cloudflare за допомогою curl --resolve, щоб вдарити origin напряму з тим же Host заголовком.

3) Чи безпечний режим Cloudflare «Flexible» для WordPress?

Він може бути, але крихкий. Якщо origin або WordPress коли-небудь примусить HTTPS, Flexible — ризик циклу. У продакшні «Full (strict)» — це доросла відповідь.

4) Я виправив, але деякі користувачі ще отримують неправильний редирект. Чому?

Погані 301 кешуються браузерами і Cloudflare. Також HSTS апгрейди відбуваються на клієнті. Очистіть edge-кеш і тестуйте з чистого середовища; розгляньте тимчасовий 302 під час переходів.

5) Де мені примушувати www/non-www: у WordPress, Nginx чи Cloudflare?

Оберіть одне. Якщо Cloudflare завжди перед сайтом, примус на edge часто найпростіший. Якщо іноді обходите Cloudflare (регіонально, API-клієнти), робіть це на origin. Те, чого не варто робити — намагатися примусити в усіх трьох місцях.

6) Чому /wp-admin зациклюється більше, ніж головна сторінка?

Адмін-потоки залежать від куків і прапорів secure. Якщо WordPress думає, що запит — HTTP, він може встановлювати куки або редиректити непослідовно, що викликає «відскок при вході».

7) Як обробляти редиректи, не порушивши POST-запити (форми оформлення)?

Уникайте редиректів для POST коли можливо. Якщо мусите редиректити, переконайтесь, що ви використовуєте коди статусу, що зберігають семантику методу де потрібно (307/308), і перевірте, що ваш стек edge/proxy їх підтримує. Часто краще виправити канонічну схему/хост до відправки форми.

8) Чи може плагін спричинити цикл редиректів, навіть якщо SiteURL/Home правильні?

Так. Плагіни безпеки, SSL і кешування часто додають редиректи або змінюють поведінку куків. Тимчасово відключіть їх для ізоляції. Якщо відключення вирішує проблему, приберіть функцію редиректу з плагіна і реалізуйте каноналізацію в іншому місці.

9) Чому це ламається лише в мобільних мережах або у конкретних країнах?

Різні POPи Cloudflare можуть віддавати різні кешовані редиректи, і гео-правила/Workers можуть поводитися по-різному. Розглядайте це як проблему розподіленого кешу: перевірте заголовки, ідентифікатори POP і очищення.

10) Яка «одна зміна», що фіксує більшість циклів?

Узгодьте режим SSL Cloudflare з реальністю origin (Full/Full strict) і зробіть так, щоб WordPress погодився на канонічний URL (SiteURL/Home). Потім приберіть дубльовану логіку редиректів.

Висновок: наступні кроки, які реально можна відправити в продакшн

Цикли перенаправлень виникають, коли кілька шарів сперечаються, який URL «справжній». Ваше завдання — припинити суперечку.

  1. Оберіть один канонічний URL (HTTPS + один хост).
  2. Доведіть, де саме цикл за допомогою огляду хопів curl і тестів обходу origin.
  3. Виправте відповідальний шар: режим/правила Cloudflare, правила перепису origin, або SiteURL/Home у WordPress та проксі-заголовки.
  4. Приберіть дубльовану логіку редиректів, щоб вона не з’явилась знову під час наступної «дрібної» зміни.
  5. Очистіть кешовані редиректи і перевірте 4-way матрицю (http/https × www/apex), щоб всі шляхи швидко вели до одного URL.

Якщо ви нічого не зробите більше: припиніть використовувати конфліктних авторів редиректів. Продакшн любить простоту. І він також любить, щоб вас не будили посеред ночі.

← Попередня
Проблеми MTU/MSS у офісних VPN: чому великі файли зависають (SMB/RDP) і як це виправити
Наступна →
Реагування на рансомваре в ZFS: сценарій зі снапшотами, що рятує

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