手機(jī)上自己做網(wǎng)站嗎關(guān)鍵詞提取工具app
X-Forwarded-For和相關(guān)幾個(gè)頭部的理解
-
$remote_addr
是nginx與客戶端進(jìn)行TCP連接過程中,獲得的客戶端真實(shí)地址. Remote Address 無法偽造,因?yàn)榻?TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求
-
X-Real-IP
是一個(gè)自定義頭。X-Real-Ip 通常被 HTTP 代理用來表示與它產(chǎn)生 TCP 連接的設(shè)備 IP,這個(gè)設(shè)備可能是其他代理,也可能是真正的請求端。需要注意的是,X-Real-Ip 目前并不屬于任何標(biāo)準(zhǔn),代理和 Web 應(yīng)用之間可以約定用任何自定義頭來傳遞這個(gè)信息
-
X-Forwarded-For
X-Forwarded-For 是一個(gè)擴(kuò)展頭。HTTP/1.1(RFC 2616)協(xié)議并沒有對它的定義,它最開始是由 Squid 這個(gè)緩存代理軟件引入,用來表示 HTTP 請求端真實(shí) IP,現(xiàn)在已經(jīng)成為事實(shí)上的標(biāo)準(zhǔn),被各大 HTTP 代理、負(fù)載均衡等轉(zhuǎn)發(fā)服務(wù)廣泛使用,并被寫入 RFC 7239(Forwarded HTTP Extension)標(biāo)準(zhǔn)之中.
X-Forwarded-For請求頭格式非常簡單,就這樣:
X-Forwarded-For:client, proxy1, proxy2
可以看到,XFF 的內(nèi)容由「英文逗號 + 空格」隔開的多個(gè)部分組成,最開始的是離服務(wù)端最遠(yuǎn)的設(shè)備 IP,然后是每一級代理設(shè)備的 IP。
如果一個(gè) HTTP 請求到達(dá)服務(wù)器之前,經(jīng)過了三個(gè)代理 Proxy1、Proxy2、Proxy3,IP 分別為 IP1、IP2、IP3,用戶真實(shí) IP 為 IP0,那么按照 XFF 標(biāo)準(zhǔn),服務(wù)端最終會收到以下信息:
X-Forwarded-For: IP0, IP1, IP2
Proxy3 直連服務(wù)器,它會給 XFF 追加 IP2,表示它是在幫 Proxy2 轉(zhuǎn)發(fā)請求。列表中并沒有 IP3,IP3 可以在服務(wù)端通過 remote_address 來自 TCP 連接,表示與服務(wù)端建立 TCP 連接的設(shè)備 IP,在這個(gè)例子里就是 IP3。
詳細(xì)分析一下,這樣的結(jié)果是經(jīng)過這樣的流程而形成的:
-
用戶IP0—> 代理Proxy1(IP1),Proxy1記錄用戶IP0,并將請求轉(zhuǎn)發(fā)個(gè)Proxy2時(shí),帶上一個(gè)Http Header X-Forwarded-For: IP0
-
Proxy2收到請求后讀取到請求有 X-Forwarded-For: IP0,然后proxy2 繼續(xù)把鏈接上來的proxy1 ip追加到 X-Forwarded-For 上面,構(gòu)造出X-Forwarded-For: IP0, IP1,繼續(xù)轉(zhuǎn)發(fā)請求給Proxy 3
-
同理,Proxy3 按照第二部構(gòu)造出 X-Forwarded-For: IP0, IP1, IP2,轉(zhuǎn)發(fā)給真正的服務(wù)器,比如NGINX,nginx收到了http請求,里面就是 X-Forwarded-For: IP0, IP1, IP2 這樣的結(jié)果。所以Proxy 3 的IP3,不會出現(xiàn)在這里。
-
nginx 獲取proxy3的IP 能通過remote_address就是真正建立TCP鏈接的IP,這個(gè)不能偽造,是直接產(chǎn)生鏈接的IP。$remote_address 無法偽造,因?yàn)榻?TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求。
x-forwarded-for 實(shí)踐研究:
-
uwsgi_pass的情況下,nginx 沒有設(shè)置proxy_pass x-forwarded-for: $proxy_add_x_forwarded_for;
- 如果請求頭傳了XFF,在flask里面能正常讀取請求頭里面的XFF,就是當(dāng)是一個(gè)普通的頭讀出;如果header不傳這個(gè)XFF的話,就讀不到
-
proxy_pass 情況下
-
沒有傳 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的話,跟上面的uwsgi_pass 一樣,都是在沒有設(shè)置header XFF情況下,讀不到。
-
如果傳了 proxy_set_header X-Forwarded-For remote_address),因?yàn)檫@句proxy_set_header 會讓nginx追加一個(gè)$remote_address到XFF。
-
header 傳xff的話, 程序里面可以讀到Xff 頭: X-Forwarded-For: 188.103.19.120, 10.0.2.2 (第一個(gè)是我自己編的,第二個(gè)是proxy_add_x_forwarded_for 這句而追加$remote_addr到XFF。
-
總結(jié):
-
只要nginx前端(例如lvs, varnish)轉(zhuǎn)發(fā)請求給nginx的時(shí)候,帶了x-forwarded-for ,那么程序就一定能讀到這個(gè)字段,如果nginx還設(shè)置了proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, 那么程序能讀到XFF是:ip0, ip1 (客戶端Ip,lvs或者varnishIP)。 如果nginx沒有設(shè)置,那么nginx還是會原樣把http頭傳給程序,也就是說程序也能讀到XFF,而且XFF就是ip0 客戶端IP。
-
proxy_pass 設(shè)置這個(gè)頭 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 是站在一個(gè)作為代理的角度把。能繼續(xù)傳輸多級代理的頭。
-
nginx的日志格式寫了$http_x_forwared_for 說明前端(lvs)確實(shí)傳了這個(gè)頭過來。所以是程序是讀取到的
-
uwsgi_pass 不能設(shè)置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 這個(gè)頭,是因?yàn)檫@個(gè)頭是對http代理來說,用來傳遞IP的,uwsgi 不可能充當(dāng)一個(gè)代理。
-
nginx->程序,這里其實(shí)有兩個(gè)鏈接過程,其他IP與nginx的TCP連接, nginx與程序的TCP連接。所以$remote_addr都是對各自來說的。程序的remote_addr: remote_addr 127.0.0.1 (跟它鏈接的是nginx 內(nèi)網(wǎng)127.0.0.1)nginx的remote_addr : X-Real-Ip: 10.0.2.2 (跟它鏈接的是我的電腦,IP 10.0.2.2)
-
對程序來說,讀取的request.remote_addr 也永遠(yuǎn)是直接跟他鏈接的ip, 也就是反向代理nginx
-
The access_route attribute uses the X-Forwarded-For header, falling back to the REMOTE_ADDRWSGI variable; 也就是說access_route默認(rèn)讀取XFF頭,如果沒有,降級讀取WSGI的REMOTE_ADDR變量,這個(gè) WSGI的REMOTE_ADDR變量 就是 $remote_addr
-
request.envron 是WSGI的變量,都是wsgi server轉(zhuǎn)過來的,普通的頭都是加了HTTP_前綴的 ,包括proxy_set_header Host proxy_add_x_forwarded_for;
添加的頭都會出現(xiàn)在處理,因?yàn)樗麄兙褪瞧胀ǖ膆ttp頭 -
LVS->nginx的情況下, 請求的時(shí)候主動加XFF,程序讀取的時(shí)候沒顯示。因?yàn)長VS設(shè)置XFF的時(shí)候,直接把直連的IP賦值給LVS,忽略掉所有本來有的XFF,要從LVS這里開始。 所以程序讀到的XFF是 :XFF headers 218.107.55.254, 10.120.214.252
前面的是我的IP, 后面的是LVS的IP
X-Forwarded-For和相關(guān)幾個(gè)頭部的理解
-
$remote_addr
是nginx與客戶端進(jìn)行TCP連接過程中,獲得的客戶端真實(shí)地址. Remote Address 無法偽造,因?yàn)榻?TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求
-
X-Real-IP
是一個(gè)自定義頭。X-Real-Ip 通常被 HTTP 代理用來表示與它產(chǎn)生 TCP 連接的設(shè)備 IP,這個(gè)設(shè)備可能是其他代理,也可能是真正的請求端。需要注意的是,X-Real-Ip 目前并不屬于任何標(biāo)準(zhǔn),代理和 Web 應(yīng)用之間可以約定用任何自定義頭來傳遞這個(gè)信息
-
X-Forwarded-For
X-Forwarded-For 是一個(gè)擴(kuò)展頭。HTTP/1.1(RFC 2616)協(xié)議并沒有對它的定義,它最開始是由 Squid 這個(gè)緩存代理軟件引入,用來表示 HTTP 請求端真實(shí) IP,現(xiàn)在已經(jīng)成為事實(shí)上的標(biāo)準(zhǔn),被各大 HTTP 代理、負(fù)載均衡等轉(zhuǎn)發(fā)服務(wù)廣泛使用,并被寫入 RFC 7239(Forwarded HTTP Extension)標(biāo)準(zhǔn)之中.
X-Forwarded-For請求頭格式非常簡單,就這樣:
X-Forwarded-For:client, proxy1, proxy2
可以看到,XFF 的內(nèi)容由「英文逗號 + 空格」隔開的多個(gè)部分組成,最開始的是離服務(wù)端最遠(yuǎn)的設(shè)備 IP,然后是每一級代理設(shè)備的 IP。
如果一個(gè) HTTP 請求到達(dá)服務(wù)器之前,經(jīng)過了三個(gè)代理 Proxy1、Proxy2、Proxy3,IP 分別為 IP1、IP2、IP3,用戶真實(shí) IP 為 IP0,那么按照 XFF 標(biāo)準(zhǔn),服務(wù)端最終會收到以下信息:
X-Forwarded-For: IP0, IP1, IP2
Proxy3 直連服務(wù)器,它會給 XFF 追加 IP2,表示它是在幫 Proxy2 轉(zhuǎn)發(fā)請求。列表中并沒有 IP3,IP3 可以在服務(wù)端通過 remote_address 來自 TCP 連接,表示與服務(wù)端建立 TCP 連接的設(shè)備 IP,在這個(gè)例子里就是 IP3。
詳細(xì)分析一下,這樣的結(jié)果是經(jīng)過這樣的流程而形成的:
-
用戶IP0—> 代理Proxy1(IP1),Proxy1記錄用戶IP0,并將請求轉(zhuǎn)發(fā)個(gè)Proxy2時(shí),帶上一個(gè)Http Header X-Forwarded-For: IP0
-
Proxy2收到請求后讀取到請求有 X-Forwarded-For: IP0,然后proxy2 繼續(xù)把鏈接上來的proxy1 ip追加到 X-Forwarded-For 上面,構(gòu)造出X-Forwarded-For: IP0, IP1,繼續(xù)轉(zhuǎn)發(fā)請求給Proxy 3
-
同理,Proxy3 按照第二部構(gòu)造出 X-Forwarded-For: IP0, IP1, IP2,轉(zhuǎn)發(fā)給真正的服務(wù)器,比如NGINX,nginx收到了http請求,里面就是 X-Forwarded-For: IP0, IP1, IP2 這樣的結(jié)果。所以Proxy 3 的IP3,不會出現(xiàn)在這里。
-
nginx 獲取proxy3的IP 能通過remote_address就是真正建立TCP鏈接的IP,這個(gè)不能偽造,是直接產(chǎn)生鏈接的IP。$remote_address 無法偽造,因?yàn)榻?TCP 連接需要三次握手,如果偽造了源 IP,無法建立 TCP 連接,更不會有后面的 HTTP 請求。
x-forwarded-for 實(shí)踐研究:
-
uwsgi_pass的情況下,nginx 沒有設(shè)置proxy_pass x-forwarded-for: $proxy_add_x_forwarded_for;
- 如果請求頭傳了XFF,在flask里面能正常讀取請求頭里面的XFF,就是當(dāng)是一個(gè)普通的頭讀出;如果header不傳這個(gè)XFF的話,就讀不到
-
proxy_pass 情況下
-
沒有傳 # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for 的話,跟上面的uwsgi_pass 一樣,都是在沒有設(shè)置header XFF情況下,讀不到。
-
如果傳了 proxy_set_header X-Forwarded-For remote_address),因?yàn)檫@句proxy_set_header 會讓nginx追加一個(gè)$remote_address到XFF。
-
header 傳xff的話, 程序里面可以讀到Xff 頭: X-Forwarded-For: 188.103.19.120, 10.0.2.2 (第一個(gè)是我自己編的,第二個(gè)是proxy_add_x_forwarded_for 這句而追加$remote_addr到XFF。
-
總結(jié):
-
只要nginx前端(例如lvs, varnish)轉(zhuǎn)發(fā)請求給nginx的時(shí)候,帶了x-forwarded-for ,那么程序就一定能讀到這個(gè)字段,如果nginx還設(shè)置了proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for, 那么程序能讀到XFF是:ip0, ip1 (客戶端Ip,lvs或者varnishIP)。 如果nginx沒有設(shè)置,那么nginx還是會原樣把http頭傳給程序,也就是說程序也能讀到XFF,而且XFF就是ip0 客戶端IP。
-
proxy_pass 設(shè)置這個(gè)頭 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 是站在一個(gè)作為代理的角度把。能繼續(xù)傳輸多級代理的頭。
-
nginx的日志格式寫了$http_x_forwared_for 說明前端(lvs)確實(shí)傳了這個(gè)頭過來。所以是程序是讀取到的
-
uwsgi_pass 不能設(shè)置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 這個(gè)頭,是因?yàn)檫@個(gè)頭是對http代理來說,用來傳遞IP的,uwsgi 不可能充當(dāng)一個(gè)代理。
-
nginx->程序,這里其實(shí)有兩個(gè)鏈接過程,其他IP與nginx的TCP連接, nginx與程序的TCP連接。所以$remote_addr都是對各自來說的。程序的remote_addr: remote_addr 127.0.0.1 (跟它鏈接的是nginx 內(nèi)網(wǎng)127.0.0.1)nginx的remote_addr : X-Real-Ip: 10.0.2.2 (跟它鏈接的是我的電腦,IP 10.0.2.2)
-
對程序來說,讀取的request.remote_addr 也永遠(yuǎn)是直接跟他鏈接的ip, 也就是反向代理nginx
-
The access_route attribute uses the X-Forwarded-For header, falling back to the REMOTE_ADDRWSGI variable; 也就是說access_route默認(rèn)讀取XFF頭,如果沒有,降級讀取WSGI的REMOTE_ADDR變量,這個(gè) WSGI的REMOTE_ADDR變量 就是 $remote_addr
-
request.envron 是WSGI的變量,都是wsgi server轉(zhuǎn)過來的,普通的頭都是加了HTTP_前綴的 ,包括proxy_set_header Host proxy_add_x_forwarded_for;
添加的頭都會出現(xiàn)在處理,因?yàn)樗麄兙褪瞧胀ǖ膆ttp頭 -
LVS->nginx的情況下, 請求的時(shí)候主動加XFF,程序讀取的時(shí)候沒顯示。因?yàn)長VS設(shè)置XFF的時(shí)候,直接把直連的IP賦值給LVS,忽略掉所有本來有的XFF,要從LVS這里開始。 所以程序讀到的XFF是 :XFF headers 218.107.55.254, 10.120.214.252
前面的是我的IP, 后面的是LVS的IP