X-Forwarded-For的一些理解(1)
文章目錄
##關於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,來看看下面的兩個例子。
在第一個例子中,我們可以看出來,客戶端是直接連結的伺服器,則獲取到的IP即為真實的client ip地址資訊。
若通過代理, 則直連的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中獲取的本質原因。
##總結
這是一篇比較淺顯的部落格,目的只是為了可以更好理解X-Forwarded-For的使用場景,以及結合nginx使用可以產生的效果。後面如果還有更深入的思考,會繼續寫下去。
相關文章
- JSON的一些理解JSON
- HTTP X-Forwarded-For是什麼?HTTPForward
- 對ThreadLocal的一些理解thread
- 對Transformer的一些理解ORM
- 一些八股:1.fetch 的理解。2.let、const、var
- 對React一些原理的理解React
- React事務的一些理解React
- c++ typedef的一些理解C++
- Express原始碼的一些理解Express原始碼
- 關於position的一些理解
- 分散式鎖的一些理解分散式
- map底層的一些理解
- flutter中的rebuild一些理解FlutterRebuild
- 關於position定位的一些理解
- 差分約束的一些理解
- 通俗理解一些概念
- JS Array.prototype.reduce的一些理解JS
- 對於Redux原始碼的一些理解Redux原始碼
- 關於Swift中Properties的一些理解Swift
- 關於Dart中Future的一些理解Dart
- 關於Base64的一些理解
- new static ,new self ,self::, $this的一些理解
- webpack (1)——核心概念的理解Web
- 1. 對Vue的理解Vue
- redux中介軟體的原始碼的一些理解Redux原始碼
- SOLIDWORKS新增的一些功能1Solid
- 關於服務高可用的一些理解
- 對Java多執行緒的一些理解Java執行緒
- 關於跨域和JSONP的一些理解跨域JSON
- HTTP2 的一些理解與練習HTTP
- 關於虛擬函式的一些理解函式
- 關於 Python 裝飾器的一些理解Python
- gitlab上CI/CD的一些小實踐和理解Gitlab
- 關於spring事務原始碼的一些小理解Spring原始碼
- kafka-一些我在學習中的理解Kafka
- 關於 Node.js scoped module 的一些理解Node.js
- 初學Java時沒有理解的一些概念Java
- 關於01揹包個人的一些理解