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

HTTP X-Forwarded-For 頭部字段的應用

辦公 comm 詳細 type targe 程序 redirect blog 行修改

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

常見如下兩個網絡結構,從辦公室用戶通過公網訪問一臺webserver服務
技術分享圖片

這個事例是公司的一個用戶(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進行修改。

$proxy_add_x_forwarded_for
the “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.

可以理解為$X-Forwarded-For,$remote_addr

用戶訪問
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

網絡方案二架構:
技術分享圖片

技術分享圖片
(這個字段可以追加也可以擦除在寫入,看設備修改的方式)

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

HTTP X-Forwarded-For 頭部字段的應用