X-Forwarded-For
我們常常使用 Nginx 作為 Web 站點的反向代理服務器,如下圖所示,我們可以通過 Nginx 的內置變量 $remote_addr
來獲取客戶端訪問的 IP。
當我們的 Web 站點接入 CDN 或者 WAF 后,$remote_addr
卻是 CDN 或者 WAF 的 IP,因為 CDN 獲取 WAF 這里也充當了一個反向代理服務器。為了解決這個問題,RFC 7239(Forwarded HTTP Extension)標準中定義了 X-Forwareded-For,X-Forwareded-For 放在 HTTP Header 中,格式如下:
X-Forwarded-For: client1, proxy1, proxy2
其中的值通過一個 逗號+空格 把多個IP地址區分開, 最左邊(client1)是最原始客戶端的IP地址, 代理服務器每成功收到一個請求,就把請求來源IP地址添加到右邊。一般來說,CDN 或者 WAF 的廠商均會準守這個協議,所以你接入 CDN 或者 WAF 后的 X-Forwarded-For 的值是 client1, CDN_IP/WAF_IP
,所以,我們可以通過解析 X-Forwarded-For 來獲取真正的客戶端訪問 IP。
ngx_http_realip_module
而 ngx_http_realip
模塊的作用是當你的 nginx 服務器位于一個反向代理后面時,去獲取客戶端真實訪問的 IP。這個模塊默認沒有編譯到 Nginx 中,需要在編譯時通過 --with-http_realip_module
開啟。
這個模塊的相關配置如下:
set_real_ip_from 192.168.1.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
-
set_real_ip_from:
address | CIDR | unix:
, 定義信任地址(trusted address),配合后續的real_ip_recursive
使用。 -
real_ip_header:
field | X-Real-IP | X-Forwarded-For | proxy_protocol
, 默認值是X-Real-IP
, 定義真實的 IP 在請求頭中的字段名。 -
real_ip_recursive:
on | off
, 默認值是off
,如果是off
,則使用real_ip_header
請求頭中匹配信任地址(trusted address)中最后一個作為客戶端請求的真實 IP;如果是on
, 則取匹配的前一個值作為客戶端真實 IP。
ngx_http_realip
模塊將用獲取到的客戶端真實 IP 作為 Nginx 內置變量 $remote_addr
的值。這樣你又能通過 $remote_addr
得到你客戶端訪問的真實 IP 了。
另外,除了使用 ngx_http_realip
模塊,你也可以通過 Lua 腳本去解析 X-Forwarded-For
,從而獲取真實的 IP。