Nginx

代理時如何讓 nginx 不覆蓋 x-forwarded-for?

  • February 1, 2022

我在負載均衡器後面有一個 nginx 伺服器,nginx 伺服器將請求傳遞給各種服務,但在本例中是一個執行 apache 的 docker 容器。負載均衡器正確設置了 X-Forwarded-For,但是當它到達 docker 容器時,X-Forwarded-For 已設置為 LB IP。

我在 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 正在發送正確的標頭。

我錯過了一步嗎?

我認為問題出在您的真實IP配置中。

set_real_ip_from {{LB IP}};

real_ip_header X-Real-IP;

real_ip_recursive on;

當 real_ip_header 應該(在你的情況下)設置為 X-Forwarded-For。我假設您的 LB 中的 X-Forwarded-For 標頭如下所示:

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;

引用自:https://serverfault.com/questions/1090749