Nginx docker обратный прокси рекурсивная петля при установке proxy_set_header Host

Вопрос или проблема

Я пытаюсь настроить обратный прокси nginx в контейнере docker на машине с Windows для разработки. Это должно отражать, как связаны сервисы на производстве.

В настоящее время я сталкиваюсь с проблемой, когда при попытке маршрутизации на другую машину в сети по IP-адресу, я не могу сделать это, так как это приводит к зацикленной запросу, пока nginx не выдаст “400 header or cookie too large”, так как заголовок X-Forwarded-For становится слишком большим, похоже.

Когда я выполняю команду curl локально на своей хостовой машине:

curl -v -H "Host: subdomain1.example.com" http://192.168.1.10

Я получаю ожидаемый ответ, который является ответом с сайта IIS. Но при выполнении команды в контейнере docker я получаю ответ 400 от nginx.

Я думал, что проблема в том, что DNS разрешает subdomain1.example.com на себя. Поскольку на роутере есть локальный DNS, который отображает subdomain1.example.com на IP-адрес хостовой машины Windows. Но даже когда я настраиваю пользовательский резолвер (который является контейнером dnsmasq, работающим на хостовой машине Windows – проверено с помощью nslookup), я получаю ту же ошибку. Я пытался установить DNS контейнера docker с помощью команды --dns=192.168.1.11, а также установить --add-host=subdomain1.example.com:192.168.1.10. Но что бы я ни делал, это, похоже, всегда приводит к рекурсивной петле. Проблема возникает только при установке proxy_set_header Host "subdomain1.example.com". Как только я его убираю, маршрутизация работает, но на сайт по умолчанию в IIS, что мне не нужно. Мне нужно, чтобы заголовок хоста совпадал с именем сервера nginx, чтобы правильное привязка могла быть обнаружена в IIS и направлена на правильный сайт.

Подхватывает ли nginx, что заголовок хоста совпадает с именем сервера, и пытается обработать запрос самостоятельно? Если да, то как мне это прекратить, но при этом сохранить заголовок хоста, чтобы он мог использоваться в IIS? Я не могу изменить поддомен заголовка хоста, так как сайт приложения выдаст ошибку POST CORS. Например, если я использую subdomain1proxy.example.com и привяжу его к тому же сайту – это не подходит из-за проблемы с CORS. Он должен совпадать с хостом запроса.

Как я могу этого добиться?

Вот мой текущий конфигурационный файл:

upstream iis_server {
    server 192.168.1.10:80;
}

upstream next_server {
    server host.docker.internal:3000;
}

upstream api_server {
    server host.docker.internal:7071;
}

upstream image_server {
    server host.docker.internal:7072;
}

server {
    listen 80;
    server_name subdomain1.example.com;

    location ~ ^/(?<dest>(one|two|three).*) {
        resolver 192.168.1.11 ipv6=off;
        proxy_pass http://iis_server;

        proxy_set_header Host "subdomain1.example.com";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

    }


    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://next_server/;
        proxy_redirect off;
    }

}

server {
    listen 80;
    server_name subdomain2.example.com;

    location / {

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        proxy_pass http://api_server/;
        proxy_redirect off;
    }

}

server {
    listen 80;
    server_name subdomain3.example.com;

    location / {

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;

        proxy_pass http://image_server/;
        proxy_redirect off;
    }

}

Ответ или решение

Настройка обратного прокси-сервера Nginx в контейнере Docker может быть непростой задачей, особенно когда вы сталкиваетесь с проблемами, такими как циклические перенаправления или ошибки "400 header or cookie too large". В данной ситуации возникает проблема, когда попытка проксировать запросы из Docker-контейнера с установленным заголовком proxy_set_header Host приводит к рекурсивному циклу и, в конечном итоге, к ошибке "400".

Теория

Основная задача обратного прокси заключается в том, чтобы направлять входящие HTTP-запросы к соответствующим серверам на основе выбранных условий конфигурации. Заголовок Host играет важную роль в маршрутизации запросов, особенно если на конечном сервере, таком как IIS, настроено несколько сайтов, и они идентифицируются именно по этому заголовку.

Циклы в HTTP-запросах обычно возникают из-за некорректной настройки правил перенаправления или проксирования, где прокси-сервер может пытаться обработать запросы сам, перенаправляя их обратно на себя.

Пример

Согласно представленному конфигурационному файлу Nginx, наблюдается следующее:

  1. В секции, которая отвечает за проксирование к IIS (upstream iis_server), вы устанавливаете proxy_set_header Host "subdomain1.example.com". Это действие говорит Nginx отправлять в виде заголовка Host измененное значение, отличное от исходного.

  2. В конфигурации есть правило для server_name subdomain1.example.com, что означает, что Nginx ожидает входящих запросов на этот точный хост. Установка заголовка Host идентичным server_name может привести к тому, что Nginx начнет рассматривать эти запросы как предназначенные для себя и попытаться их обработать, что потенциально инициирует циклический переход.

  3. Разрешение DNS зацикливается, если нет программного разделения для маршрутизации данных запросов, что может вызывать ошибку.

Применение

Для устранения проблемы с рекурсией и коррекцией проксирования попробуйте следующие действия:

  1. Измените резолюцию: Перепроверьте и при необходимости скорректируйте записи DNS, чтобы убедиться, что любые ссылки на subdomain1.example.com разрешаются верно и не ведут обратно к конфигурации основного сервера Nginx.

  2. Тонкая настройка проксирования: Попробуйте изменить или исключить proxy_set_header Host, вместо этого настройте IIS так, чтобы он мог принимать и интерпретировать запросы без необходимости в изменении заголовка Host. Если это невозможно, убедитесь, что прокси передает запросы в уникальный виртуальный хост на IIS.

  3. Временный тест без заголовка: Можно на уровне теста временно убрать строчку proxy_set_header Host и проверить, как запросы маршрутизируются. Если маршрутизация работает надежно, проблема точно кроется именно в заголовках и необходимости их пересылки.

  4. Логирование и отладка: Включите большее количество логирования для Nginx и Docker, чтобы лучше понять, где осуществляется процесс перенаправления и точную точку возникновения зацикливания.

  5. Обновление конфигурации для уникальности маршрутизации: Разделите конфигурации / цели маршрутизации, чтобы избежать коллизий. Это может включать установку альтернативных портов или дальнейшие модификации конфигурации IIS для уникального идентификатора бэкенда.

  6. Консультация с документацией Nginx и IIS: Просмотрите официальную документацию для обоих систем относительно настройки прокси и обработки заголовков, чтобы не упустить каких-либо специфических рекомендаций.

Заключение

Для успеха в решении подобной проблемы требуется комплексный подход к настройке сетевого окружения, понимание ролей заголовков HTTP и конфигурации серверов приложений. Важно понимать, что во многих случаях проблемы, связанные с заголовками и проксированием, требуют углубленной отладки и тестирования различных подходов, прежде чем будет найдено наиболее устойчивое решение.

Оцените материал
Добавить комментарий

Капча загружается...