X-Forwarded-For的一些理解(1)

zyhmz發表於2018-09-08

文章目錄


##關於X-Forwarded-For的簡要概述
X-Forwarded-For 是一個 HTTP 擴充套件頭部,主要是為了讓 Web 伺服器獲取訪問使用者的真實 IP 地址,但是這個IP卻未必是真實的,我們後面會回來描述這個問題。一些開發者為了獲取客戶IP,我們經常會使用request.remote_ip來獲得使用者IP。但是很多使用者都是通過代理來訪問伺服器的,如果使用remote_ip這個全域性變數來獲取IP,開發者往往獲得的是代理伺服器的IP,並不是使用者真正的IP。

客戶端=>正向代理=>透明代理=>伺服器反向代理=>Web伺服器

假如客戶端直接連線 Web 伺服器(假設 Web 伺服器有公網地址),則 request.remote_ip獲取到的是客戶端的真實 IP 。

假設 Web 伺服器前部署了反向代理(比如 Nginx),則 request.remote_ip獲取到的是反向代理裝置的 IP(Nginx)。

假設客戶端通過正向代理直接連線 Web 伺服器(假設 Web 伺服器有公網地址),則request.remote_ip獲取到的正向代理裝置的 IP 。

其實這裡的知識點很多,記住一點就行了,request.remote_ip獲取到的 IP 是 Web 伺服器 TCP 連線的 IP(這個不能偽造,一般 Web 伺服器也不會修改這個頭)。

##關於X-Forwarded-For的一個思考
我們都知道,Http是基於Tcpip的協議,我們為什麼不可以從傳輸層的socket獲得我們所需要源使用者ip呢?其實Http已經從socket取得所需要IP,但是這個IP並一定是我們所需要的真實IP,來看看下面的兩個例子。

Created with Raphaël 2.2.0clientrails(web server)

在第一個例子中,我們可以看出來,客戶端是直接連結的伺服器,則獲取到的IP即為真實的client ip地址資訊。

Created with Raphaël 2.2.0clientnginxrails(web server)

若通過代理, 則直連的ip會被代理伺服器的ip所替代。通過兩個例子中的對比, 我們可以清楚的觀察到, 在反向代理模式下, 客戶端的socket已經被nginx的socket所代替。若還是按預設的方式來獲取客戶端ip, 將失去意義。在這裡,基本可以回答我們疑惑了,但是我們可以再往下探究一下,http的請求經過了nginx,我們是怎麼從X-Forwarded-For中獲得我們真實的IP。

##nginx配置
nginx是7層代理, 不是4層代理。7層代理的意思我們只能從修改第七層的包資訊,因此不可能在tcp/ip這層做手腳. 只能在http/https這個應用層協議中做文章。nginx的策略是: 往http/https請求中, 新增額外的header資訊, 以此來完成真實客戶端ip的資訊傳遞。下面是nginx中的一些內部變數的定義:

$remote_addr #來自對端socket的ip地址
$remote_port #來自對端socket的port資訊
$proxy_add_x_forwarded_for #http/https請求流經的所有代理的ip

在nginx配置中, 需要在location標籤下新增如下項:

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

X-Real-IP我們很容易可以理解了,就是取得和我們伺服器建立tcp連結的ip地址。這裡就需要X-Forwarded-For來記錄ip的資訊了。
標準格式如下:X-Forwarded-For: client1, proxy1, proxy2。從標準格式可以看出,X-Forwarded-For頭資訊可以有多個,中間用逗號分隔,第一項為真實的客戶端ip,剩下的就是曾經經過的代理或負載均衡的ip地址,經過幾個就會出現幾個。

光從定義來看, X-Forward-For只是記錄了, 來自客戶端所流經的代理伺服器的鏈路路程, 好像沒啥作用. 獲取真實IP, 通過獲取設定的X-Real-IP即可。當nginx只有一層代理,這種方案是可行的。

但是在現實的web架構中, 存在多層代理伺服器時, 使用X-Real-IP會丟失真實的客戶端IP, 而X-Forward-For依舊為你保留了真實的客戶端IP, 這也為什麼後端web server從X-Forward-For中獲取client ip, 而不是從X-Real-IP中獲取的本質原因。

Created with Raphaël 2.2.0clientnginx(一級代理)nginx(二級代理)rails(web server)

##總結
這是一篇比較淺顯的部落格,目的只是為了可以更好理解X-Forwarded-For的使用場景,以及結合nginx使用可以產生的效果。後面如果還有更深入的思考,會繼續寫下去。

相關文章