Рейтинг:2

Apache за обратным прокси-сервером nginx, установка правильного заголовка Host

флаг nl

Я запускаю свое приложение с помощью Apache в контейнере Docker. У меня есть nginx, действующий как обратный прокси-сервер, работающий в другом контейнере Docker, в котором Apache является восходящим потоком. я использую proxy_pass директива для этого.

Apache работает в URL https://example-8gnm1aqrns-lz.a.run.app Nginx работает в URL http://example.com

Все это работает в Google Cloud Run, и проблема в том, что Google Cloud Run назначает каждой службе URL-адрес и использует Хозяин заголовок, чтобы различать приложения, поэтому я вынужден отправить заголовок Хост: example-8gnm1aqrns-lz.a.run.app при подключении к восходящему потоку с использованием nginx, чтобы запрос маршрутизировался правильно.

Это вызывает проблему с моим приложением, потому что оно думает, что работает в URL-адресе https://example-8gnm1aqrns-lz.a.run.app и нет http://example.com.

Можно ли использовать некоторую конфигурацию Apache .htaccess для перезаписи Хозяин заголовок на основе X-переадресованный хост отправлено nginx?

Рейтинг:2
флаг co

Вместо того, чтобы Apache выполнял эту работу, пусть NGINX сделает это еще до того, как он передаст данные Apache, установив заголовок Host, который Apache ожидает как часть передачи proxy_pass с дополнительной опцией конфигурации.

NGINX имеет следующую переменную для proxy_set_header, чтобы увеличить то, что передается прокси-серверу в бэкэнде. Итак, у вас будет что-то вроде этого:

...

место расположения / {
    прокси_пасс http://10.20.30.40;
    proxy_set_header Хост example.com;
}
...

в вашей конфигурации NGINX для обратного прокси. Тогда Apache не будет заботиться о X-Forwarded-Host, потому что вместо этого вы установите заголовок Host, который Apache должен отдавайте приоритет обслуживанию.

Этот должен Исправить ситуацию - таким образом я использую несколько систем NGINX, когда домен, доступный браузеру, отличается от отвечающего хоста бэкэнда - и до сих пор он работает с бэкэндами Django, бэкэндами PHP, Apache и даже с HTTP-сервером Python, который я использую для тестирования вещей . И мое понимание Apache заключается в том, что он будет отдавать приоритет заголовку Host над X-Forwarded-Host.

John Hanley avatar
флаг cn
Я могу быть не прав. Если вы отправляете запрос из одной службы Cloud Run в другую, заголовок узла должен совпадать с вызываемой службой, в противном случае вы получите ошибку 404. Это пример, когда пользовательские домены Cloud Run и ваше решение могут решить проблему.
флаг co
@JohnHanley Ааа, да, вы, вероятно, правы, однако, если OP ожидает, что конечная точка будет обслуживать example.com и получать другие URL-адреса, им нужен общий прослушиватель, который соответствует всем потенциальным доменам здесь. Я думаю, что пользовательские домены Cloud Run будут лучше работать для OP (похоже, это должен быть уникальный ответ)
John Hanley avatar
флаг cn
Я думаю, что ваше решение - правильная половина для начала. Затем OP может просмотреть пользовательские домены Cloud Run и т. Д., Чтобы логика его домена работала. Я не понимаю его зависимости от доменных имен для серверной части.
флаг co
@JohnHanley хорошо, если сервер $BACKEND работает с 50 отдельными доменами и обслуживает контент на основе заголовка Host (как работают VirtualHosts и их поля ServerName / ServerAlias ​​в Apache), то заголовок Host необходим для указания, как подключаться и с чем Хост для передачи, чтобы контент обслуживался правильно. Кстати, именно так NGINX определяет, какие зоны обслуживать — соответствие поля server_name (regex, wildcard и т. д.) определяет, какую конфигурацию сервера/сайта обслуживать для данного запроса.
John Hanley avatar
флаг cn
Однако это не то, как работает Cloud Run. Заголовок Host определяет, к какой службе Google Cloud GFE направляет запрос. Если серверная часть обрабатывает 50 доменов, то для службы Cloud Run потребуется 50 пользовательских доменов.Учитывая, что для каждого пользовательского домена потребуется сопоставление домена, я не уверен, что это даже поддерживается (ограничения квоты). Серверной части потребуется другой метод для поддержки этого типа идентификации. Пользовательский заголовок, вероятно, будет работать. Однако это пример впихивания дизайна в сервис, который может не соответствовать архитектуре.
флаг co
@JohnHanley Я думаю, все, что мне нужно знать, это где находится NGINX. Если я правильно понимаю OP, example.com -> NGINX -> Google Cloud Run. Таким образом, заголовок Host для блока местоположения и proxy_pass просто должны установить Host на уникальный URL-адрес GCR для запроса. Предположим, что NGINX на самом деле находится на сайте example.com.
fairport avatar
флаг nl
К сожалению, этот ответ не сработает, потому что я не могу подключиться к контейнеру Apache с помощью IP-адреса, мне нужно использовать домен с заголовком Host, чтобы Google знал, как направить запрос на нужный сервер. Я хотел бы исправить заголовок Host в Apache, чтобы приложение правильно строило свои маршруты. Правильный заголовок Host находится в X-Forwarded-Host, или я мог бы использовать переменную среды, чтобы определить его.
флаг co
@fairport Я не уверен, что в Apache есть возможность переписать заголовок X-Forwarded-Host. Я искал, но не видел такого функционала. Я думаю, что если ваше приложение не будет работать так, как ожидает Google, вам нужно перестроить / реструктурировать ваше приложение с учетом требований Google, а не пытаться взломать его на месте. Что имеет смысл в отношении GCR, потому что они структурируют его очень специфическим образом. (Я могу удалить свой ответ в какой-то момент после того, как вы прочитаете этот комментарий)
fairport avatar
флаг nl
Да, сейчас я изучаю документацию по директиве Apache RequestHeader и смотрю, смогу ли я заменить заголовок Host с помощью переменной среды. Другим способом исправить это может быть настройка сети VPC, таким образом, служба Cloud Run должна иметь статический IP-адрес, который я могу использовать вместо URL-адреса. Последний способ, которым я могу думать, это изменение самого приложения, чтобы оно заменяло заголовок Host с помощью X-Forwarded-Host или переменной среды, но это кажется хакерским.Я отвечу на свой вопрос, если найду хороший способ решить эту проблему.
Рейтинг:1
флаг nl

Я решил эту проблему, определив новую переменную среды с именем APP_HOST в панели управления Google Cloud Run и установив для него значение пример.com.

Затем я добавил следующую конфигурацию в .htaccess файл в корне документа:

<IfModule mod_env.c>
    PassEnv APP_HOST
</IfModule>

<IfModule mod_headers.c>
    RequestHeader set Host %{APP_HOST}e env=APP_HOST
</IfModule>

Это позволило мне переопределить Хозяин заголовок из пример-8gnm1aqrns-lz.a.run.app к пример.com на основе переменной окружения APP_HOST.

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

Редактировать

Вот как вы можете решить это, используя X-переадресованный хост, например, если вы запускаете виртуальные хосты и вам нужно, чтобы сайт был доступен из нескольких доменов

<IfModule mod_setenvif.c>
    SetEnvIf X-Forwarded-Host (.*) REAL_HOST_HEADER=$1
    <IfModule mod_headers.c>
        RequestHeader set Host "%{REAL_HOST_HEADER}e"
    </IfModule>
</IfModule>

Это захватит заголовок из X-переадресованный хост и установите Хозяин заголовок на основе значения.

Ответить или комментировать

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