Как я могу заставить nginx не переопределять x-forwarded-for при проксировании?
У меня есть сервер nginx за балансировщиком нагрузки, сервер nginx передает запросы различным службам, но в данном случае докер-контейнеру под управлением Apache. Балансировщик нагрузки правильно устанавливает X-Forwarded-For, но к тому времени, когда он попадает в Docker-контейнер, X-Forwarded-For уже установлен на IP-адрес LB.
У меня есть это в конфигурации nginx:
/etc/nginx/conf.d/real_ip.conf
set_real_ip_from {{LB IP}};
real_ip_header X-Real-IP;
real_ip_recursive on;
и это виртуальный хост:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name *.domain domain;
include /etc/nginx/snippets/domain_ssl.conf;
add_header X-Nginx-Debug "hi";
proxy_pass_request_headers on;
location / {
proxy_pass_request_headers on;
proxy_pass http://container-php;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Remote-Addr $remote_addr;
proxy_set_header X-Real-IP $http_x_real_ip;
proxy_set_header X-Header-Test "Hello World - $http_x_forwarded_for";
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Но что я получаю из контейнера:
array(19) {
["Connection"]=>
string(7) "upgrade"
["Host"]=>
string(19) "domain"
["X-Forwarded-For"]=>
string(12) "{{LB IP}}"
["X-Header-Test"]=>
string(13) "Hello World -"
["X-Forwarded-Proto"]=>
string(5) "https"
["cache-control"]=>
string(9) "max-age=0"
["sec-ch-ua"]=>
string(64) "" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97""
["sec-ch-ua-mobile"]=>
string(2) "?0"
["sec-ch-ua-platform"]=>
string(9) ""Windows""
["upgrade-insecure-requests"]=>
string(1) "1"
["user-agent"]=>
string(114) "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36"
["accept"]=>
string(135) "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
["sec-fetch-site"]=>
string(4) "none"
["sec-fetch-mode"]=>
string(8) "navigate"
["sec-fetch-user"]=>
string(2) "?1"
["sec-fetch-dest"]=>
string(8) "document"
["accept-encoding"]=>
string(17) "gzip, deflate, br"
["accept-language"]=>
string(26) "en-GB,en-US;q=0.9,en;q=0.8"
}
В частности, X-Real-IP, X-Fowarded-For, похоже, не установлены, равно как и Remote_addr. Для файлов, обслуживаемых непосредственно из nginx, x-forwarded-for установлен правильно, поэтому LB отправляет правый заголовок.
Я пропустил шаг?
4 ответа
Я думаю, проблема в вашей реальной конфигурации IP.
set_real_ip_from {{LB IP}};
real_ip_header X-Real-IP;
real_ip_recursive on;
Когда для параметра Real_ip_header (в вашем случае) должно быть установлено значение X-Forwarded-For. Я предполагаю, что ваш заголовок X-Forwarded-For из LB выглядит следующим образом:
X-Forwarded-For: {{Original client ip}}, {{LB ip}}
Поэтому, когда вы устанавливаете для Real_ip_header (заголовок, используемый для замены IP-адреса клиента) значение X-Forwarded-For, он будет соответствовать исходному IP-адресу клиента. Исходный клиент теперь должен находиться в переменной $realip_remote_addr, которую вы можете адресовать proxy_set_header X-Forwarded-For:
proxy_set_header X-Forwarded-For $realip_remote_addr
Пожалуйста, дайте мне знать, если я чем-то помог!
Это оператор, переопределяющий заголовок X-Forwarded-For:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Предполагая, что вы хотите сохранить исходный IP-адрес клиента в этом заголовке, вам следует написать:
proxy_set_header X-Forwarded-For $remote_addr;
Судя по вашему описанию, ваша проблема напрямую связана не с nginx, а с Apache.
В зависимости от вашей конфигурации ваш поток трафика может выглядеть примерно так:
outside -> nginx -> apache -> php (running as fpm)
или
outside -> nginx -> apache + php module
Вам следует заглянуть в конфигурацию Apache, чтобы убедиться, что Apache не отбрасываетx-forwarded-for
иx-real-ip
заголовки при передаче запроса в PHP.
Если ваш поток трафика соответствует первому примеру, у вас есть Apache, проксирующий запрос также на php, что может привести к гораздо большему количеству проблем, если nginx и apache не «синхронизированы».
Если бы вы обрабатывали прокси-сервер PHP только с помощью nginx, вам просто нужно было бы добавить следующее в свой php:location
конфигурация:
location ~ \.php$ {
#...other rules
fastcgi_param REMOTE_ADDR $http_x_real_ip;
#...other rules
}
Таким образом, PHPREMOTE_ADDR
будет правильно установлен.
Что касается вашей конфигурации nginx, если ваш nginx{{LB IP}}
является статическим, вы можете установить его прямо в конфиге.
/etc/nginx/conf.d/real_ip.conf
set_real_ip_from {{LB IP}};
real_ip_recursive on;
Вам не нужноreal_ip_header X-Real-IP;
в вашем файле конфигурации. Это переопределитset_real_ip_from
директива.
Имейте в виду, что для того, чтобы это работало, вам необходимо включить модуль real_ip в nginx.
В конце концов я решил это так, чтобы это работало, но на самом деле не решило основную проблему. Насколько я могу судить, восходящий LB устанавливает «X-Forwarded-For» для удаленного адреса, и магическая попытка nginx установить это правильно для обратного прокси-сервера всегда приводила к неправильной настройке и установке его на адрес LB или пустой адрес. нить.
Вместо этого я переключился с протокола HTTP на протокол PROXY для бита LB->Server, установил следующее в /etc/nginx/proxy_params:
proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
и это в конф.д:
/etc/nginx/conf.d/real_ip.conf
set_real_ip_from {{ LB_IP }};
real_ip_header proxy_protocol;
адаптировано из этого:
https://www.x33u.org/docs/kubernetes-stuff/hetzner-loadbalancer-setup/
и теперь все работает.