Если после установки reverse proxy сайт зацикливает переход на HTTPS или генерирует ссылки с http://, проверьте, какую схему видит приложение. TLS может завершаться на балансировщике, а до backend запрос идти по HTTP: это само по себе не означает, что посетитель открыл незащищённый адрес.
Нужно сопоставить внешний запрос, заголовок схемы от доверенного прокси и результат его обработки в приложении. Добавлять ещё один принудительный редирект до этой проверки опасно: он может поддерживать ту же петлю.
1. Найдите место, где теряется HTTPS
Нарисуйте фактический маршрут: браузер → CDN или балансировщик → nginx → приложение. Для каждого соединения отметьте HTTP или HTTPS и узел, на котором завершается TLS. Если промежуточного nginx нет, не добавляйте его в схему по привычке.
На безопасной публичной странице выполните GET без автоматического перехода. Замените адрес примерного домена своим:
curl -sS -o /dev/null -w '%{http_code} %{redirect_url}\n' https://example.com/
Повторите проверку для HTTP и указанного адреса перехода. Одинаковый HTTPS-адрес в Location — признак для расследования, но ещё не доказательство ошибки Forwarded: ответ мог прийти из кэша или другого правила. Общий разбор маршрута есть в статье о цепочке редиректов.
Сопоставьте время запроса с журналами каждого узла. Установите, кто сформировал редирект: внешний прокси, внутренний веб-сервер или приложение. Если запрос до приложения не дошёл, его настройки доверенных заголовков пока не объясняют ответ.
2. Сравните входной заголовок и вычисленную схему
Попросите администратора проверить в закрытой диагностике приложения три значения: адрес непосредственного прокси, полученный заголовок схемы и результат штатного определения secure/HTTPS. Не публикуйте отладочную страницу и не собирайте Cookie, Authorization или полный дамп запроса.
В зависимости от инфраструктуры передаётся Forwarded: proto=https либо X-Forwarded-Proto: https. В RFC 7239 параметр proto описывает исходную схему; наличие заголовка само по себе не подтверждает его достоверность.
| Наблюдение | Что проверить следующим | | --- | --- | | Внешний HTTPS, заголовка схемы нет | Настройку передачи на узле завершения TLS | | Заголовок дошёл как http | Узел, который заменил исходную схему своей | | Заголовок https, приложение видит HTTP | Доверенные адреса прокси и разрешённые заголовки | | Приложение видит HTTPS, но ссылка HTTP | Базовый URL CMS, шаблон, кэш и отдельные правила генерации URL |
Проверяйте именно объект запроса или API фреймворка, которым пользуется код. Наличие значения в серверной переменной не гарантирует, что приложение его учитывает.
3. Исправьте передачу на нужном узле
Когда nginx сам принимает HTTPS посетителя
На таком узле исходную схему можно передать в HTTP upstream директивой:
proxy_set_header X-Forwarded-Proto $scheme;
Это фрагмент настройки, а не готовый server-блок. Согласно документации nginx, директива задаёт заголовок запроса к upstream. Проверьте фактически используемый location: правила наследования могут отличать его от соседнего блока.
Когда TLS завершается перед nginx
В цепочке балансировщик → HTTP → nginx значение $scheme на nginx будет http. Та же строка перезапишет правильную внешнюю схему. Здесь требуется согласованная передача значения от проверенного балансировщика, а не копирование примера выше.
Не пересылайте пользовательский $http_x_forwarded_proto вслепую. На внешней границе входящие значения должны заменяться данными доверенного узла; внутренний сервер должен принимать их только от предусмотренного прокси. Для нескольких прокси явно определите, какой узел формирует исходную схему и какие её сохраняют.
4. Ограничьте доверие в приложении
Укажите реальные адреса или необходимые диапазоны ваших прокси и только используемые заголовки. Например, Symfony отдельно настраивает trusted_proxies и trusted_headers: передача заголовка и разрешение ему доверять — разные настройки. Конкретный синтаксис сверяйте с установленной версией.
Не включайте доверие всем адресам ради исчезновения петли. Ограничьте прямой доступ к backend: иначе внешний клиент может обойти прокси и прислать собственное значение. Не включайте доверие X-Forwarded-Host только потому, что понадобился X-Forwarded-Proto.
Если присутствуют и Forwarded, и X-Forwarded-Proto, устраните противоречия и проверьте, какой формат использует ваш стек. Не выбирайте произвольно первое или последнее значение из цепочки: обработка должна соответствовать документированной модели доверенных узлов.
5. Проверьте результат после изменения
Сохраните прежнюю конфигурацию, проверьте синтаксис и сначала воспроизведите изменение на стенде. Затем повторите запросы через обычный публичный вход:
- HTTP приводит к предусмотренному HTTPS-адресу без цикла;
- HTTPS не перенаправляется на себя;
- приложение определяет HTTPS, а создаваемые им абсолютные ссылки используют правильную схему;
- клиентский заголовок с ложной схемой не меняет результат определения HTTPS;
- backend остаётся недоступен извне в обход разрешённой цепочки.
Проверку подмены проводите на своём стенде без авторизации и операций с данными. После исправления отделите новый ответ от ранее закэшированного редиректа. Если схема уже правильная, а ресурсы всё ещё загружаются по HTTP, переходите к проверке шаблонов и mixed content.
Web-Puls помогает регулярно контролировать доступность публичного URL после исправления, но внешняя проверка не показывает внутренние trusted headers. Если неизвестно, где меняется схема, можно отправить заявку на поддержку: укажите публичный адрес, маршрут прокси без секретов, время сбоя и наблюдаемые переходы — это даст основу для разбора.