Как перенаправить часть пути на поддомен с помощью NGINX?

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

У меня есть сервер A, который принимает HTTPS-запросы, такие как:

https://example.com/CHANGEME/example/index.html

У меня есть сервер B, который принимает:

https://CHANGEME.example.com/example/index.html

Клиент должен обращаться только к серверу A.

Вопрос: как я должен настроить прокси NGINX на сервере A, чтобы использовать строку между первыми двумя “/” и использовать ее в качестве поддомена?

Важно вырезать эту часть из пути и использовать ее как поддомен.

Конечно, когда сервер A получает ответ от сервера B, поддомен должен быть переписан обратно в путь для клиента.

Все, что я пробовал, не работало, и это, кажется, нетипичная проблема.

Я упустил какую-то функцию перезаписи шаблона?

заранее спасибо!

редактировать:
Я хотел бы немного изменить мой вопрос, так как он не работает, как ожидалось.

Теперь я хотел бы реализовать обратное проксирование на основе значения cookie.

Для тестирования я установил cookie с именем url и значением CHANGEME.

В конфигурации NGINX я пробовал:

location / {
    resolver 8.8.8.8;
    proxy_pass https://$cookie_url.example.com;
}

Который в целом работает и загружает нужный сайт.
Проблема в том, что клиент также пытается подключиться к mqtt брокеру wss://example.com/mqtt, и это приводит к ошибке.
Я думаю, из-за отсутствия опции чтения cookie?
Есть шанс, что это будет работать?

Это должно работать следующим образом:

server {
    location ~ ^/(?<subdomain>[^/]+)(?<path>.*)$ {
        proxy_pass http://$subdomain.example.com$path;
    }
}

Блок location соответствует путям и захватывает строку между первыми двумя косыми чертами в переменную $subdomain. Затем остальная часть пути захватывается в переменную $path. Полученные значения затем используются в качестве назначение proxy_pass.

Я могу ответить на вопрос сам.
Получилось.
Недостающая часть конфигурации в location была:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

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

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

  1. Поступающие запросы на сервер A имеют вид: https://example.com/CHANGEME/example/index.html.
  2. Вам нужно перенаправить их на сервер B в форме: https://CHANGEME.example.com/example/index.html.
  3. При обратном ответе от сервера B, нужно восстановить исходный формат URL, чтобы клиент получал те же URL, что и запрашивал, находясь на сервере A.

Теоретическая часть

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

  • Блок location: Использование регулярных выражений в конфигурации location позволяет извлекать части URL и сохранять их в переменных.
  • Переменные NGINX: Позволяют динамически формировать конечный URL-запрос для проксирования.
  • Proxy_pass: Директива, позволяющая перенаправить запросы к другому серверу, может использовать динамически определенные переменные.

Пример

Используя предложенные вами методы и дополнительную логику, мы можем создать следующую конфигурацию:

server {
    listen 80;
    server_name example.com;

    location ~ ^/(?<subdomain>[^/]+)(?<path>/.*)$ {
        # Извлечь поддомен и путь из URL
        proxy_pass http://$subdomain.example.com$path;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # Дополнительно можно настроить заголовки, чтобы сохранить сессию и куки
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Объяснение:

  • Переменная <subdomain> извлекается из URL и используется для построения проксированного URL.
  • Переменная <path> сохраняет остальную часть пути для проксирования.
  • Директива proxy_set_header используется для переноса определенных заголовков, которые необходимы для правильной обработки запроса на сервере B.

Практическое применение

Ваш сценарий затрудняется ещё и необходимостью работы с MQTT по websocket-соединению. Ваша конфигурация указала на использование cookie для этих целей:

location / {
    resolver 8.8.8.8;
    proxy_pass https://$cookie_url.example.com;
}

Однако для работает ли прямое использование cookies в имени сервера, нужно учитывать, что NGINX не имеет прямого функционала для одновременного использования cookie как серверного адреса и поддержки websocket без необходимых заголовков. Как вы правильно заметили, при работе с websocket необходимы заголовки Upgrade и Connection.

Добавление :

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

позволило вам разрешить проблему с вебсокетами, но ошибки могут происходить из-за того, что не все пути (например, /mqtt) должны использовать cookie-адресацию.

Чтобы исправить этот момент, следует:

  • Обработать проксирование /mqtt отдельно, без использования переменной $cookie_url, если она не нужна для MQTT.
  • Убедиться, что все используемые пути подготовлены для работы с cookie, и, если cookie причастен к указанию нужного сервера, быть уверенным в его наличии.

Вывод

Настройка NGINX требует внимания к деталям, особенно при работе с динамичными поддоменами и специфическими протоколами, такими как websocket. Регулярные выражения и переменные NGINX способны значительно упростить подобные задачи, если правильно воспользоваться ими в конфигурациях. Вполне возможно, потребуется дополнительная обработка куки и/или использование дополнительных блоков конфигурации для различных услуг, как в вашем случае с MQTT, чтобы обеспечить корректное выполнение всех функций прокси-сервера.

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

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

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