Как я могу заставить 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/

и теперь все работает.

Другие вопросы по тегам