在正常的TCP/IP 通信中乏梁,是可以偽造數(shù)據(jù)包來源 IP 的贷帮,但這會(huì)讓發(fā)送出去的數(shù)據(jù)包返回到偽造的IP上,無法實(shí)現(xiàn)正常的通信犬缨。
實(shí)現(xiàn)TCP/IP層級(jí)別的偽造很難,因?yàn)楹茈y實(shí)現(xiàn)正常的TCP連接捧请;但是在應(yīng)用層協(xié)議HTTP上的實(shí)現(xiàn)較容易锋喜,通過偽造IP些己,能欺騙多數(shù)服務(wù)器應(yīng)用程序?qū)崿F(xiàn)通信豌鸡。對(duì)于繞過服務(wù)器的IP地址過濾或者偽造來源IP特別有用,導(dǎo)致的后果就是非授權(quán)IP能訪問服務(wù)器段标,甚至能鉆服務(wù)器的漏洞涯冠。
這其中的關(guān)鍵就是偽造X-Forwarded-For。
一逼庞、X-Forwarded-For介紹
我們知道 HTTP 連接基于 TCP 連接蛇更,HTTP 協(xié)議中沒有 IP 的概念,只能通過X-Forwarded-For來實(shí)現(xiàn)赛糟。
X-Forwarded-For位于HTTP協(xié)議的請(qǐng)求頭派任, 是一個(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
字段獲得啸箫。Remote Address
來自 TCP 連接耸彪,表示與服務(wù)端建立 TCP 連接的設(shè)備 IP,在這個(gè)例子里就是 IP3忘苛。
Remote Address 無法偽造蝉娜,因?yàn)榻?TCP 連接需要三次握手唱较,如果偽造了源 IP,無法建立 TCP 連接召川,更不會(huì)有后面的 HTTP 請(qǐng)求南缓。不同語言獲取Remote Address
的方式不一樣,例如Node.js 是req.connection.remoteAddress
荧呐,原理都一樣汉形。
二、X-Forwarded-For偽造
這里我用node.js進(jìn)行測(cè)試
node.js路由級(jí)中間件:
模板引擎:
運(yùn)行node.js應(yīng)用后坛增,node.js監(jiān)聽3000端口获雕。用Firefox請(qǐng)求鏈接,結(jié)果如下(由于是本機(jī)瀏覽器訪問本機(jī)搭建的服務(wù)器收捣,地址為空届案。本機(jī)地址為127.0.0.1):
很明顯,X-Forwarded-For
參數(shù)并不是瀏覽器當(dāng)前的地址罢艾,在這個(gè)例子中成功偽造了X-Forwarded-For
信息楣颠。如果服務(wù)器以X-Forwarded-For
中的地址(而不是remote address
)作為用戶的IP地址實(shí)行IP地址過濾,很可能讓用戶通過偽造X-Forwarded-For
獲取權(quán)限咐蚯,從而導(dǎo)致服務(wù)器應(yīng)用出現(xiàn)漏洞童漩。
三、結(jié)語
目前很多Web 應(yīng)用(例如獲取用戶所在地區(qū)春锋,基于 IP 做訪問頻率控制矫膨,禁止某些IP訪問等等),為了獲取用戶真正的 IP期奔,從 HTTP 請(qǐng)求頭中獲取 IP地址侧馅。這些情況下,必須確保獲取到的IP地址是真實(shí)可靠的呐萌。
經(jīng)過前面的分析和測(cè)試馁痴,
1.對(duì)于直接使用的 Web 應(yīng)用,必須使用從TCP連接中得到的 Remote Address肺孤,才是用戶真實(shí)的IP罗晕;
2.對(duì)于使用 nginx 反向代理服務(wù)器的Web應(yīng)用,nginx必須使用Remote Address正確配置set Headers赠堵,后端服務(wù)器則使用nginx傳過來的相應(yīng)IP地址作為用戶真實(shí)IP小渊;同時(shí),后端服務(wù)器應(yīng)使用X-Real-IP 或 X-Forwarded-For最后1段IP作為限制茫叭,允許自己的nginx服務(wù)器訪問酬屉,禁止其它IP訪問,禁止對(duì)外提供服務(wù)杂靶。