在云原生架構(gòu)下,Nginx 或應用服務前面掛了 WAF、負載均衡(SLB) 等安全和流量治理組件,Nginx 日志里 $remote_addr
往往不再是用戶的真實公網(wǎng) IP,而是代理設備的出口 IP。
本文帶你從原理到實踐,搞清楚如何優(yōu)雅、安全地拿回真實客戶端 IP。
?? 背景與問題
為什么 `$remote_addr` 是代理 IP?因為 TCP 連接實際是和 WAF/SLB 建立的。
對 Nginx 來說,連接對端就是 SLB/WAF 的出口地址,而不是用戶。
?? 用戶真實 IP 的去向
WAF/SLB 會把真實用戶 IP 寫入 HTTP 頭X-Forwarded-For: <client-ip>, <proxy-ip>, ...
X-Real-IP: <client-ip>
(某些設備使用)
因此,只能在 HTTP 七層讀取這些頭部才能拿回真實客戶端 IP。
?? 正確獲取真實 IP 的 Nginx 配置
直接打印 `$http_x_forwarded_for` 有安全風險
正確做法:使用 ngx_http_realip_module
,并只信任來自自家代理設備的 IP。
# 1) 信任的代理網(wǎng)段
set_real_ip_from 10.0.0.0/16;
set_real_ip_from 192.168.0.0/24;
# 2) 指定頭部
real_ip_header X-Forwarded-For;
# 3) 啟用遞歸解析,獲取最左側(cè)的客戶端 IP
real_ip_recursive on;
# 4) 日志配置
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'status=$status bytes=$body_bytes_sent '
'xff="$http_x_forwarded_for" ua="$http_user_agent"';
access_log /var/log/nginx/access.log main;
?? 非 HTTP/HTTPS 場景怎么辦?
有些業(yè)務跑在 WebSocket、HTTPS 直透、純 TCP 服務 上,這時不能依賴 HTTP 頭。
- PROXY protocol(推薦)
上游設備在 TCP 握手時寫入真實 IP
Nginx 開啟支持:
server {
listen 443 proxy_protocol;
real_ip_header proxy_protocol;
set_real_ip_from 10.0.0.0/16;
}
適用于 HTTPS、TCP 等多場景
- 透明代理/TPROXY
?? 避坑指南
忘記配置可信網(wǎng)段:導致 Nginx 誤信任偽造頭
未開啟遞歸解析:多級代理場景下,拿到的是中間代理 IP
只記錄真實 IP,不記錄頭:排查問題時丟失上下文
后端透傳遺漏:業(yè)務服務無法獲取到真實 IP
set_real_ip_from
指定可信代理網(wǎng)段
real_ip_header X-Forwarded-For
并開啟 real_ip_recursive on
日志同時打印 $remote_addr
與 $http_x_forwarded_for
向后端透傳真實 IP:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
? 總結(jié)
為什么看不到真實 IP? ?? TCP 對端是 WAF/SLB。
如何拿回? ?? HTTP 場景依賴 X-Forwarded-For
,必須配合 realip
模塊。
非 HTTP 場景? ?? 使用 PROXY protocol。
最佳實踐? ?? 配置可信網(wǎng)段、遞歸解析、雙日志記錄、后端透傳。
這樣配置后,無論日志分析、風控策略還是安全審計,都能基于準確的用戶源 IP 進行判斷。
閱讀原文:原文鏈接
該文章在 2025/9/11 10:01:11 編輯過