Nginx недопустимый префикс пути URL .. при отправке клиенту

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

У меня есть следующие настройки сервера, которые работают для одного URL, но, похоже, не работают для другого URL.

location / {


    proxy_buffers 16 4k;
    proxy_buffer_size 2k;       


    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 https;
    proxy_set_header X-Forwarded-Port 443;

    proxy_pass http://10.4.1.81/;


    # Это используется для обработки множества перенаправлений 301, которые выполняет сервер
    proxy_intercept_errors on;
    error_page 301 302 307 = @handle_redirects;     


}   

location @handle_redirects {
    set $saved_redirect_location '$upstream_http_location';
    proxy_pass $saved_redirect_location;
}   

Когда я перехожу по следующему URL:

https://lfdocs.mohave.gov/bos/0/doc/1652027/Page1.aspx

я получаю следующую ошибку от Nginx

2020/12/03 19:10:40 [error] 31251#31251: *1 invalid URL prefix in "/bos/CookieCheck.aspx?redirect=%2fbos%2fDocView.aspx%3fdbid%3d0%26id%3d1652027%26page%3d1" while sending to client, client: 10.10.82.151, server: lfdocs.mohave.gov, request: "GET /bos/0/doc/1652027/Page1.aspx HTTP/2.0", host: "lfdocs.mohave.gov"

Я провел небольшое исследование, но не могу понять. Есть ли советы?

Спасибо

Обновление

Проблема кажется связана с тем, что правильные URL являются корректными. При неудаче это происходит из-за некорректного URL.

  1. Используя echo $saved_redirect_location;

    Успех

    URL:

    https://lfdocs.mohave.gov/Forms/RequestToSpeak

    Возврат:

    https://10.4.1.81/Forms/RequestToSpeak

    Неудача:

    URL:

    https://lfdocs.mohave.gov/bos/0/doc/1652027/Page1.aspx

    Возвращает:

    /bos/CookieCheck.aspx?redirect=%2fbos%2fDocView.aspx%3fdbid%3d0%26id%3d1652027%26page%3d1

  2. Используя echo http://10.4.1.81$saved_redirect_location;

    Неудача

    URL:

    https://lfdocs.mohave.gov/Forms/RequestToSpeak

    Возврат:

    http://10.4.1.81https://10.4.1.81/Forms/RequestToSpeak

    Успех

    URL:

    https://lfdocs.mohave.gov/bos/0/doc/1652027/Page1.aspx

    Возвращает:

    http://10.4.1.81/bos/CookieCheck.aspx?redirect=%2fbos%2fDocView.aspx%3fdbid%3d0%26id%3d1652027%26page%3d1

используя $saved_redirect_location для proxy_pass, есть ли способ проверить, существует ли домен, и если нет, то добавить его?

Обновление

Мое решение было следующим:

   location @handle_redirects {
    set $saved_redirect_location '$upstream_http_location';

    # Если IP существует, просто прокси передача
    if ($saved_redirect_location ~* "10.4.1.81") {
        proxy_pass $saved_redirect_location;
    }

    # Если IP не существует, добавляем его в начало
    if ($saved_redirect_location !~* "10.4.1.81") {
        proxy_pass http://10.4.1.81$saved_redirect_location;
    }       
}

Это решение, которое в итоге сработало для меня. Спасибо, Иван, за совет.

location @handle_redirects {
  set $saved_redirect_location '$upstream_http_location';

  # Если IP существует, просто прокси передача
  if ($saved_redirect_location ~* "10.4.1.81") {
    proxy_pass $saved_redirect_location;
  }

  # Если IP не существует, добавляем его в начало
  if ($saved_redirect_location !~* "10.4.1.81") {
    proxy_pass http://10.4.1.81$saved_redirect_location;
  }       
}

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

Ваша проблема связана с некорректной обработкой URL-адресов, возвращаемых от upstream-сервера в вашем конфигурационном файле Nginx. Описание ошибки "invalid URL prefix" указывает на то, что Nginx сталкивается с некорректной структурой URL при попытке перенаправления. Позвольте предложить теоретическое объяснение, примеры для лучшего понимания и рекомендации по применению вашего решения.

Теория

Когда Nginx используется в качестве реверс-прокси, он пересылает запросы от клиента к upstream-серверу и возвращает ответ обратно клиенту. Иногда upstream-сервер может вернуть редирект HTTP-кодами, такими как 301 или 302, при этом в заголовке ‘Location’ содержится новый URL, на который необходимо перенаправить запрос. Поскольку ваш Nginx сконфигурирован для перехвата таких ошибок с помощью директивы proxy_intercept_errors on;, он попадает в пользовательскую локацию @handle_redirects, где происходит обработка этих случаев.

Проблема в том, что не все URL от upstream-сервера корректно подставляются в proxy_pass. В вашем случае, если URL начинается без домена или IP, Nginx видит это как некорректный префикс и выдаёт ошибку.

Пример

Рассмотрим детали вашего конфигурационного кода:

location / {
    # ... 
    proxy_pass http://10.4.1.81/;
    proxy_intercept_errors on;
    error_page 301 302 307 = @handle_redirects;
}

location @handle_redirects {
    set $saved_redirect_location '$upstream_http_location';
    # Неправильная обработка URL без домена/IP
    proxy_pass $saved_redirect_location;
}

Если '$upstream_http_location' возвращает значение без домена/IP, Nginx не знает, как его интерпретировать, поскольку рассматривает данный фрагмент как часть относительного пути, что и вызывает проблему.

Применение

Ваше итоговое решение исправляет это, проверяя, содержит ли '$saved_redirect_location' указанный IP-адрес, и, в отсутствии оного, добавляя его вручную. Это гарантирует, что proxy_pass всегда получает полный URL. Рассмотрим код вашего решения:

location @handle_redirects {
  set $saved_redirect_location '$upstream_http_location';

  # Проверка наличия IP-адреса и соответствующее действие
  if ($saved_redirect_location ~* "10.4.1.81") {
    proxy_pass $saved_redirect_location;
  } else {
    proxy_pass http://10.4.1.81$saved_redirect_location;
  }       
}

Это решение эффективно, так как оно анализирует структуру URL и корректирует её до безопасного состояния. В случае отсутствия полного доменного имени или IP, оно добавляет недостающую часть URL, делая его пригодным для дальнейшего использования.

Заключение

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

Ваш метод конфигурации и конечное решение являются элегантными и подчеркивают необходимость динамической обработки URL-адресов в различных сетевых конфигурациях. Это гарантирует корректную работу реверс-прокси даже при нестандартных отклонениях в структуре возвращаемых upstream URL.

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

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

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