1. 程式人生 > >HTTP X-Forwarded-For 頭部欄位的應用

HTTP X-Forwarded-For 頭部欄位的應用

【背景】
在運維工作中,經常會遇到X-Forwarded-For 這個欄位,比如nginx、haproxy、快取代理、甚至好點的網路7層網路裝置都可以修改這個欄位,這個欄位對記錄客戶端的真實IP地址非常有用,在分析nginx日誌,haproxy日誌中,經常利用這個欄位統計訪問的來源,並進一步分析問題

常見如下兩個網路結構,從辦公室使用者通過公網訪問一臺webserver服務
HTTP X-Forwarded-For 頭部欄位的應用

這個事例是公司的一個使用者(10.28.81.84)的使用者通過網路出口公網地址是116.247.112.179 訪問 公網地址是110.189.90.120的內部服務。其中經歷了一臺haproxy在代理到一臺nginx web服務。

haproxy增加X-Forwarded-For的設定
option forwardfor :如果伺服器上的應用程式想記錄發起請求的客戶端的IP地址,需要在HAProxy上配置此選項,這樣HAProxy會把客戶端的IP資訊傳送給伺服器,在HTTP請求中新增"X-Forwarded-For"欄位。

X-Forwarded-For:簡稱XFF頭,它代表客戶端,也就是HTTP的請求端真實的IP,只有在通過了HTTP 代理或者負載均衡伺服器時才會新增該項。它不是RFC中定義的標準請求頭資訊,在squid快取代理伺服器開發文件中可以找到該項的詳細介紹。
標準格式如下:
X-Forwarded-For: client1, proxy1, proxy2
從標準格式可以看出,X-Forwarded-For頭資訊可以有多個,中間用逗號分隔,第一項為真實的客戶端ip,剩下的就是曾經經過的代理或負載均衡的ip地址,經過幾個就會出現幾個。

nginx增加X-Forwarded-For的設定

set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

解釋:

如果 set_real_ip_from 設定錯誤可能會導致如下現象(本機IP是 10.10.20.32 容器機IP)
#set_real_ip_from 10.0.0.0/8;
#set_real_ip_from 172.0.0.0/8;
set_real_ip_from 192.168.0.0/16;

real_ip_header X-Forwarded-For;

這兩個指令 來自 HttpRealipModule,表示把來在10.0.0.0/8 段的所有請求的來源地址,都改成 X-Forwarded-For 頭中的最後一個IP,這時候新來源地址會賦給 remote_addr 變數;這裡如果請求頭沒有 X-Forwarded-For 頭 或者頭是不合法IP,Nginx 不會對來源IP進行修改。

使用者訪問
www.xxxxx.com

haproxy日誌格式
%ci\ %si\ %[capture.req.hdr(1)]\
格式解釋:
#HAProxy的日誌記錄內容配置
capture request header Host len 40 # 請求中的主機名
capture request header X-Forwarded-For len 100

日誌格式:
%ci\ %si\ %[capture.req.hdr(1)]\
%ci:client_ip (accepted address) 客戶端IP
%si: server_IP (target address)

日誌:
116.247.112.179 10.10.20.34 -

可以看到haproxy獲取的日誌是
客戶端IP是 116.247.112.179
後端server的IP地址是 10.10.20.34
X-Forwarded-For 為 -

nginx日誌的格式
$request_time $upstream_response_time $remote_addr "$http_x_forwarded_for" - "$server_addr"
日誌內容
0.135 0.135 116.247.112.179 "116.247.112.179" - "172.18.0.4" 0384682027257641

可見:$proxy_add_x_forwarded_for 的值為 116.247.112.179 且 $remote_addr 被賦值成了 116.247.112.179

網路方案二架構:
HTTP X-Forwarded-For 頭部欄位的應用

haproxy日誌:
日誌:
116.247.112.179 10.10.20.34 10.28.81.84
可以看到haproxy獲取的日誌是
客戶端IP是 116.247.112.179
後端server的IP地址是 10.10.20.34
X-Forwarded-For 為 10.28.81.84

疑問? 為啥公司的內網地址都變成 X-Forwarded-For ,因為公司的出口之前的那個代理裝置加上了X-Forwarded-For 將地址客戶的來源地址寫入了 X-Forwarded-For http欄位中去了

nginx日誌
nginx日誌的格式
$request_time $upstream_response_time $remote_addr "$http_x_forwarded_for" - "$server_addr"
日誌內容
0.008 0.008 116.247.112.179 "10.28.81.84, 116.247.112.179" - "172.18.0.4"

可以看出 $http_x_forwarded_for 的值為 10.28.81.84, 116.247.112.179