天天給 App 抓包,還不懂 HTTP 代理嗎?
一、序
有段時(shí)間沒(méi)寫 HTTP 協(xié)議相關(guān)的文章了,突然發(fā)現(xiàn)文章選題池里, 《實(shí)用 HTTP》 系列中還躺了個(gè) HTTP 代理的主題沒(méi)有寫,那今天就來(lái)聊聊 HTTP 代理吧。
在 HTTP 協(xié)議中,最基礎(chǔ)的就是請(qǐng)求和響應(yīng)的報(bào)文,而報(bào)文又由報(bào)文頭和報(bào)文實(shí)體組成。大多數(shù) HTTP 協(xié)議的使用場(chǎng)景,都是依賴設(shè)置不同的 HTTP 請(qǐng)求/響應(yīng) 的 Header 來(lái)實(shí)現(xiàn)的。
既然要說(shuō)到代理,先提兩個(gè)問(wèn)題來(lái)當(dāng)主線,從問(wèn)題出發(fā)講解 HTTP 代理。
- 抓包工具是如何實(shí)現(xiàn) HTTP 抓包的。
- 對(duì)于 HTTPS 流量,不安裝證書的情況下,通過(guò)抓包工具,請(qǐng)求和響應(yīng)依然正常。
今天說(shuō)的 HTTP 代理,更多的是一種抽象概念,其中的原理才是最關(guān)鍵的。
二、HTTP 代理
2.1 什么 HTTP 代理?
說(shuō)到 HTTP 代理,作為客戶端開(kāi)發(fā),最熟悉的就是使用 Fiddler、Charles 等工具進(jìn)行抓包時(shí),需要在手機(jī)上掛個(gè)代理,來(lái)方便我們排查一些網(wǎng)絡(luò)問(wèn)題,這只是代理眾多使用場(chǎng)景中的一個(gè)。
實(shí)際上,HTTP 代理(Web 代理)是一種存在于網(wǎng)絡(luò)中間的實(shí)體,可以提供各種功能。如果沒(méi)有 HTTP 代理,客戶終端就要直接與終端服務(wù)器進(jìn)行交互。而有了 HTTP 代理后,客戶終端就可以與代理通信,然后由代理代表客戶端與服務(wù)器進(jìn)行交互。
HTTP 代理算是最容易理解的一個(gè) HTTP 協(xié)議概念,它和我們的生活最貼近。在我們的生活中,存在各種代辦的服務(wù)。
例如你和女友準(zhǔn)備出國(guó)游,一些不免簽的國(guó)家,就需要提前辦理簽證。我們不熟悉自然覺(jué)得流程很復(fù)雜,這時(shí)就可以選擇交由旅行社來(lái)代理辦理簽證,你只需要根據(jù)對(duì)方提供的清單準(zhǔn)備材料,就可以很方便的獲得簽證。在這個(gè)過(guò)程中,你節(jié)省了時(shí)間,而旅行社賺了你一點(diǎn)錢。
代理服務(wù),就是代理客戶端完成事務(wù)處理的中間人,它接管客戶端的事務(wù),代替客戶端與服務(wù)端交互。
代理服務(wù)是一個(gè)抽象的中間實(shí)體,可以存在網(wǎng)絡(luò)的各個(gè)中間點(diǎn),瀏覽器、路由器、代理服務(wù)器、Web 服務(wù)器的反向代理等,
2.2 HTTP 代理的分類
從最熟悉的抓包工具說(shuō)起,F(xiàn)iddler、Charles 這種抓包工具,封裝的都非常好,哪怕我們完全不理解 HTTP 代理的細(xì)節(jié),簡(jiǎn)單配置就可以使用。
在使用過(guò)程中,你會(huì)發(fā)現(xiàn)兩種場(chǎng)景:
- 對(duì)于 HTTP 協(xié)議請(qǐng)求,可以直接顯示請(qǐng)求/響應(yīng)報(bào)文的細(xì)節(jié)
- 對(duì)于 HTTPS ,如果沒(méi)有導(dǎo)入證書,請(qǐng)求依然可以發(fā)送至服務(wù)器,并且也可以正常返回?cái)?shù)據(jù),但是不會(huì)顯示報(bào)文細(xì)節(jié)。
在沒(méi)有導(dǎo)入證書的情況下,HTTPS 請(qǐng)求我們無(wú)法獲知細(xì)節(jié),但是并不影響我們的請(qǐng)求和響應(yīng)。
這個(gè)兩種不同的表現(xiàn),也對(duì)應(yīng)了兩種不同的 HTTP 代理:
- 普通代理。基于修訂后的 RFC 2616 在 HTTP/1.1 中被定義。這種代理扮演的是「中間人」的角色。對(duì)客戶端來(lái)說(shuō),它是服務(wù)端,而對(duì)真正的服務(wù)端來(lái)說(shuō),它又是客戶端,它就是負(fù)責(zé)在兩端之間傳遞 HTTP 報(bào)文。
- 隧道代理。這種一種基于 TCP 協(xié)議的隧道傳輸代理,它通過(guò) HTTP 協(xié)議的 CONNECT 方法完成通信,以 HTTP 的方式,實(shí)現(xiàn)任意基于 TCP 的應(yīng)用層協(xié)議代理。
接下來(lái)我們就分別對(duì)這兩種代理進(jìn)行講解。
2.3 普通代理
普通代理,理解起來(lái)并不復(fù)雜,它是網(wǎng)絡(luò)中的中間實(shí)體,位于客戶端和服務(wù)端之間,扮演「中間人」的角色,在兩端之間來(lái)回傳遞報(bào)文。
這個(gè)「中間人」左手牽著客戶端,右手牽著服務(wù)端,在收到客戶端發(fā)送的請(qǐng)求報(bào)文時(shí),需要正確的處理請(qǐng)求和連接狀態(tài),同時(shí)向服務(wù)器發(fā)送新的請(qǐng)求,在收到響應(yīng)后,將響應(yīng)結(jié)果包裝成一個(gè)響應(yīng)體返回給客戶端。
在普通代理的流程中,代理兩端都是有可能察覺(jué)不到「中間人」的存在。
舉個(gè)例子,我們要訪問(wèn) A 網(wǎng)站,實(shí)際上我們是向代理服務(wù)器發(fā)送請(qǐng)求,而代理服務(wù)器又再向 A 網(wǎng)站發(fā)起請(qǐng)求,最終將響應(yīng)體通過(guò)代理服務(wù)器,返回給我們。在我們的角度,我們正常的向一個(gè)網(wǎng)站服務(wù)器發(fā)起請(qǐng)求,并且對(duì)方也返回給我們正確的數(shù)據(jù),在這個(gè)過(guò)程中,我作為客戶端,會(huì)認(rèn)為代理服務(wù)器就是 A 網(wǎng)站的服務(wù)器,而 A 網(wǎng)站的服務(wù)器,又認(rèn)為代理服務(wù)器是一個(gè)真實(shí)的用戶。
這里說(shuō)到,代理服務(wù)器作為「中間人」是可以隱藏自己的存在,但是如果我們作為一個(gè)“守規(guī)矩”的代理服務(wù)器,想要將客戶端的 IP 傳遞給服務(wù)端,可以通過(guò) X-Forwarded-IP 這個(gè)自定義的 Header,來(lái)告訴服務(wù)端真正的客戶端 IP 地址。
HTTP 協(xié)議作為一種松散的協(xié)議,服務(wù)器在接收到 X-Forwarded-IP 這個(gè)請(qǐng)求頭時(shí),是無(wú)法驗(yàn)證其真?zhèn)蔚?。它可能是代理服?wù)器偽造的,也可能是真實(shí)的。所以服務(wù)端從 HTTP 頭部獲取 IP 時(shí),就需要格外小心。
普通代理很好理解,但是它也有缺陷,它只適用于 HTTP 協(xié)議。
在普通代理模式下,所有請(qǐng)求響應(yīng)的數(shù)據(jù),對(duì)于代理這個(gè)「中間人」來(lái)說(shuō),都是透明并且可以任意操作,這就會(huì)帶來(lái)各種數(shù)據(jù)安全的隱患。
說(shuō)到網(wǎng)絡(luò)數(shù)據(jù)安全,首先想到的就是 HTTPS,但是 HTTPS 這種證書認(rèn)證的機(jī)制,又是中間人劫持的克星。
嚴(yán)格上來(lái)說(shuō),HTTPS 下不存在中間人攻擊,除非是人為的犯錯(cuò)了,沒(méi)有對(duì)證書嚴(yán)格校驗(yàn),或者證書被泄露。
在普通的 HTTPS 請(qǐng)求中,服務(wù)端不驗(yàn)證客戶端的證書,中間人可以作為客戶端與服務(wù)端完成 TLS 握手。
但是由于代理中間人沒(méi)有證書密鑰,也就無(wú)法偽造服務(wù)端和客戶端簡(jiǎn)歷的 TLS 連接,這會(huì)導(dǎo)致請(qǐng)求失敗。
這個(gè)場(chǎng)景,對(duì)標(biāo)到抓包工具的工作流程中,你會(huì)發(fā)現(xiàn),如果想用 Charles(或Fiddler) 抓 HTTPS 的網(wǎng)絡(luò)數(shù)據(jù)包,就需要在手機(jī)上安裝一個(gè) Charles 的 CA 證書,讓手機(jī)設(shè)備信任此證書,才可以完成抓包,此時(shí)走的就是普通代理的模式。
那換個(gè)角度,假如在手機(jī)上沒(méi)有安裝 Charles 提供的證書,也并沒(méi)有影響到請(qǐng)求和響應(yīng),Charles 只是無(wú)法解密 HTTPS 數(shù)據(jù),這是如何做到的呢?
這就需要用到隧道代理。
2.4 隧道代理
隧道代理,又稱為 Web 隧道(Web tunnel),這種方式可以通過(guò) HTTP 連接發(fā)送非 HTTP 流量,這樣可以在 HTTP 上捎帶其他協(xié)議的數(shù)據(jù)。
隧道代理是利用 HTTP 的 CONNECT 方法建立起來(lái)的。CONNECT 方法,最初并不是 HTTP/1.1 的核心規(guī)范,但卻是一種得到廣泛使用的擴(kuò)展,它在 2014 年發(fā)布的 HTTP/1.1 修訂版中,才對(duì) CONNECT 及隧道代理有了清晰的描述。
HTTP 隧道代理的工作流程是什么樣的?
一次普通的 HTTP 請(qǐng)求,Header 部分以連續(xù)的兩組 CRLF(\r\n)作為結(jié)束標(biāo)記,如果后面還有內(nèi)容,就是 Content 部分的內(nèi)容,也稱為請(qǐng)求/響應(yīng)體(Content),如果存在 Content 內(nèi)容,就需要在 Header 中增加 Content-Length 來(lái)標(biāo)記 Content 部分的長(zhǎng)度。接收方(服務(wù)端)會(huì)根據(jù)這個(gè)長(zhǎng)度來(lái)讀取數(shù)據(jù)。
CONNECT 報(bào)文的請(qǐng)求,是沒(méi)有 Content 部分的,只有 Request-Line 和 Header,他們僅供代理服務(wù)器使用,并不會(huì)傳遞給終端服務(wù)器。請(qǐng)求的 Header 部分一旦結(jié)束(兩組連續(xù)的 CRLF),后面的所有數(shù)據(jù),都被視為應(yīng)該轉(zhuǎn)發(fā)給終端服務(wù)器的數(shù)據(jù),代理需要把他們無(wú)腦的直接轉(zhuǎn)發(fā),并且不限制長(zhǎng)度,直到從客戶端的 TCP 讀通道關(guān)閉。
CONNECT 的響應(yīng)報(bào)文,在代理服務(wù)器和終端服務(wù)器建立連接后,可以向客戶端返回一個(gè) 200 Connect established 的狀態(tài)碼,以此表示和終端服務(wù)器的連接,建立成功。這個(gè) 200 Connect established 的 Header 部分一旦結(jié)束(兩組連續(xù)的 CRLF),后面所有的數(shù)據(jù)均為遠(yuǎn)端服務(wù)器返回的數(shù)據(jù),同理,代理服務(wù)器會(huì)直接轉(zhuǎn)發(fā)終端服務(wù)器的數(shù)據(jù)給客戶端,直到終端服務(wù)器的 TCP 讀通道關(guān)閉。
了解清楚 HTTP 隧道的工作流程之后,就知道 CONNECT 方法請(qǐng)求隧道網(wǎng)管創(chuàng)建一條到達(dá)任意目的服務(wù)器和端口的 TCP 連接,并對(duì)客戶端和服務(wù)端之間的后續(xù)數(shù)據(jù),進(jìn)行無(wú)腦的盲轉(zhuǎn)發(fā)。
通過(guò)隧道代理,代理服務(wù)器不再作為中間人,不再需要改寫瀏覽器的請(qǐng)求,而是把瀏覽器和終端服務(wù)器的數(shù)據(jù),原樣轉(zhuǎn)發(fā),這樣瀏覽器就可以直接和終端服務(wù)器進(jìn)行 TLS 握手,并傳輸加密的數(shù)據(jù)。
2.4 導(dǎo)入證書后,Charles 抓 HTTPS 流程
Charles 作為抓包工具,在手機(jī)上沒(méi)有導(dǎo)入證書的時(shí)候,是通過(guò)隧道代理來(lái)保證數(shù)據(jù)的傳輸。一旦導(dǎo)入證書之后,Charles 就又切換到普通代理的工作模式,此時(shí)我們就可以解析 HTTPS 的流量數(shù)據(jù)。
這里簡(jiǎn)單說(shuō)一下原理。
在導(dǎo)入證書后,請(qǐng)求時(shí)手機(jī)就會(huì)信任 Charles 偽造的證書,而 Charles 又偽裝成真實(shí)的客戶端與服務(wù)端之間建立正確的 TLS 連接。此時(shí),Charles 作為「中間人」,兩端的 TLS 流量都是可以被解密的。
三、總結(jié)時(shí)刻
到這里就了解清楚 HTTP 代理的細(xì)節(jié),其實(shí)很抽象的概念,也很好理解。
簡(jiǎn)單來(lái)說(shuō),HTTP 代理可以分為兩類,普通代理和隧道代理。
普通代理作為「中間人」存在,在一次請(qǐng)求中,客戶端明文請(qǐng)求代理服務(wù)器,在收到請(qǐng)求后,代理服務(wù)器又明文去請(qǐng)求終端服務(wù)器。在這整個(gè)過(guò)程中,數(shù)據(jù)都是明文傳輸,中間人可以對(duì)其中傳遞的數(shù)據(jù)進(jìn)行改寫,這就是著名的中間人攻擊,可見(jiàn)其有多不安全。
這就引申出了支持 HTTPS 的隧道代理,此時(shí)代理服務(wù)器就不再作為中間人,無(wú)法改寫客戶端的請(qǐng)求,而僅僅是在建立連接后,將客戶端的請(qǐng)求,通過(guò)建立好的隧道,無(wú)腦的轉(zhuǎn)發(fā)給終端服務(wù)器。
【本文為51CTO專欄作者“張旸”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)微信公眾號(hào)聯(lián)系作者獲取授權(quán)】