I. 對(duì)項(xiàng)目時(shí)發(fā)現(xiàn)一直是xff優(yōu)先于remote address垫竞,以前項(xiàng)目也是澎粟。
既然產(chǎn)品問到了哪個(gè)優(yōu)先就查了下。
最后果然是 RemoteAddress 優(yōu)先欢瞪,xff包含經(jīng)過的每一個(gè)代理的ip(除了最后一個(gè)捌议,remote address里就是最后一個(gè)).
II. https://imququ.com/post/x-forwarded-for-header-in-http.html
通過名字就知道,X-Forwarded-For 是一個(gè) HTTP 擴(kuò)展頭部引有。HTTP/1.1(RFC 2616)協(xié)議并沒有對(duì)它的定義,它最開始是由 Squid 這個(gè)緩存代理軟件引入倦逐,用來表示 HTTP 請(qǐng)求端真實(shí) IP譬正。如今它已經(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 請(qǐng)求頭格式非常簡(jiǎn)單健民,就這樣:
X-Forwarded-For: client, proxy1, proxy2
可以看到抒巢,XFF 的內(nèi)容由「英文逗號(hào) + 空格」隔開的多個(gè)部分組成,最開始的是離服務(wù)端最遠(yuǎn)的設(shè)備 IP秉犹,然后是每一級(jí)代理設(shè)備的 IP蛉谜。
如果一個(gè) HTTP 請(qǐng)求到達(dá)服務(wù)器之前,經(jīng)過了三個(gè)代理 Proxy1崇堵、Proxy2型诚、Proxy3,IP 分別為 IP1鸳劳、IP2狰贯、IP3,用戶真實(shí) IP 為 IP0,那么按照 XFF 標(biāo)準(zhǔn)涵紊,服務(wù)端最終會(huì)收到以下信息:
X-Forwarded-For: IP0, IP1, IP2
Proxy3 直連服務(wù)器傍妒,它會(huì)給 XFF 追加 IP2,表示它是在幫 Proxy2 轉(zhuǎn)發(fā)請(qǐng)求摸柄。列表中并沒有 IP3颤练,IP3
可以在服務(wù)端通過 Remote Address 字段獲得。我們知道 HTTP 連接基于 TCP 連接塘幅,HTTP 協(xié)議中沒有 IP
的概念昔案,Remote Address 來自 TCP 連接,表示與服務(wù)端建立 TCP 連接的設(shè)備 IP电媳,在這個(gè)例子里就是 IP3踏揣。
Remote Address 無法偽造,因?yàn)榻?TCP 連接需要三次握手匾乓,如果偽造了源 IP捞稿,無法建立 TCP 連接,更不會(huì)有后面的 HTTP 請(qǐng)求拼缝。不同語(yǔ)言獲取 Remote Address 的方式不一樣娱局,例如 php 是$_SERVER["REMOTE_ADDR"],Node.js 是req.connection.remoteAddress咧七,但原理都一樣衰齐。
2017-04-20 補(bǔ)充 :
項(xiàng)目實(shí)測(cè)的時(shí)候才發(fā)現(xiàn)轉(zhuǎn)發(fā)的ip全都是nginx服務(wù)器的ip。然后趕緊查nginx的配置继阻。奇怪啊耻涛,已經(jīng)配置了轉(zhuǎn)發(fā)請(qǐng)求的時(shí)候自動(dòng)添加xff的啊,為何沒有把客戶端的真實(shí)ip獲取到呢瘟檩?
最后看項(xiàng)目發(fā)現(xiàn)抹缕,之前覺得remote address的準(zhǔn)確性高于xff,項(xiàng)目里面直接使用了remote address而沒有用xff和nginx轉(zhuǎn)發(fā)加上的x-real-ip墨辛。
趕緊修改項(xiàng)目使用xff優(yōu)先卓研,這才減少了廣告業(yè)務(wù)對(duì)ip問題的依賴導(dǎo)致的損失。