http代理如何抓取數(shù)據(jù)? Web代理是存在于網(wǎng)絡(luò)中間并提供各種功能的實(shí)體。 在現(xiàn)代網(wǎng)絡(luò)系統(tǒng)中,Web 代理無(wú)處不在。 在我之前關(guān)于 HTTP 的博文中,我多次提到代理對(duì) HTTP 請(qǐng)求和響應(yīng)的影響。 在今天的文章中,我打算談?wù)凥TTP代理本身的一些原理以及如何用Node.js快速實(shí)現(xiàn)代理。
HTTP代理有兩種形式,簡(jiǎn)單介紹如下:
第一種是RFC 7230-HTTP/1.1: 消息語(yǔ)法和路由(即修訂后的 RFC 2616,HTTP/1.1 協(xié)議的第一部分)描述了普通代理。 這種代理扮演著“中間人”的角色。 對(duì)于連接到它的客戶端來(lái)說(shuō),它是服務(wù)器; 對(duì)于要連接的服務(wù)器,它是客戶端。 它負(fù)責(zé)在兩端之間來(lái)回發(fā)送 HTTP 消息。
第二個(gè)是通過(guò) Web 代理服務(wù)器通過(guò)基于 TCP 的隧道協(xié)議描述的隧道代理。 它通過(guò)HTTP協(xié)議體完成通信,以HTTP的方式實(shí)現(xiàn)任何基于TCP的應(yīng)用層協(xié)議代理。 此代理使用 HTTP CONNECT 方法建立連接,但 CONNECT 最初不是 RFC 2616-HTTP/1.1 的一部分。 直到 2014 年發(fā)布的 HTTP/1.1 修訂版才添加了 CONNECT 和隧道代理的描述。 請(qǐng)參閱 RFC 7231-HTTP/1.1:語(yǔ)義和內(nèi)容。 事實(shí)上,這種機(jī)構(gòu)早已廣泛實(shí)施。
第一種Web代理原理很簡(jiǎn)單:
HTTP客戶端向代理發(fā)送請(qǐng)求消息,代理服務(wù)器需要正確處理請(qǐng)求和連接(例如正確處理Connection:keep-alive),同時(shí)向服務(wù)器發(fā)送請(qǐng)求,將接收到的響應(yīng)轉(zhuǎn)發(fā)給客戶端。
下圖來(lái)自《HTTP權(quán)威指南》,直觀演示了上述行為:
訪問(wèn)A的網(wǎng)站,對(duì)于A來(lái)說(shuō),它把代理當(dāng)成一個(gè)客戶端,完全不知道真實(shí)客戶端的存在。 這樣就達(dá)到了隱藏客戶端IP的目的。 當(dāng)然,代理也可以修改HTTP請(qǐng)求頭,通過(guò)自定義的頭,比如X-Forwarded-IP,告訴服務(wù)器真實(shí)的客戶端IP。 但是,服務(wù)器無(wú)法驗(yàn)證這個(gè)自定義頭是否真的是代理添加的,還是客戶端修改了請(qǐng)求頭,因此從HTTP頭字段中獲取IP時(shí)需要格外小心。 這部分內(nèi)容可以參考我之前的文章《X-Forwarded-For in HTTP Request Header》。
為瀏覽器顯式指定代理,需要手動(dòng)修改瀏覽器或操作系統(tǒng)相關(guān)設(shè)置,或者指定PAC的自動(dòng)設(shè)置(Proxy Auto-Configuration,自動(dòng)配置 proxy) 文件,并且某些瀏覽器支持 WPAD(Web 代理自動(dòng)發(fā)現(xiàn)協(xié)議)。 顯式指定瀏覽器代理的方法一般稱(chēng)為正向代理。 瀏覽器啟用轉(zhuǎn)發(fā)代理后,會(huì)對(duì)HTTP請(qǐng)求報(bào)文做一些修改,避免舊代理服務(wù)器的一些問(wèn)題。 這部分內(nèi)容可以參考。 我之前的文章“Http 請(qǐng)求頭中的代理連接”。
另一種情況是,當(dāng)你訪問(wèn)A網(wǎng)站時(shí),你實(shí)際上訪問(wèn)了代理。 代理收到請(qǐng)求消息后,向?qū)嶋H提供服務(wù)的服務(wù)器發(fā)起請(qǐng)求,并響應(yīng)轉(zhuǎn)發(fā)給瀏覽器。 這種情況一般稱(chēng)為反向代理,可以用來(lái)隱藏服務(wù)器IP和端口。 一般使用反向代理后,需要修改DNS,將域名解析為代理服務(wù)器IP。 此時(shí)瀏覽器無(wú)法檢測(cè)到真實(shí)服務(wù)器的存在。無(wú)需修改配置。 反向代理是 Web 系統(tǒng)最常見(jiàn)的部署方式。 比如本篇博客使用Nginx的proxy_pass函數(shù)將瀏覽器請(qǐng)求轉(zhuǎn)發(fā)給它背后的Node.js服務(wù)。
隧道代理
第二個(gè)Web代理的原理也是 很簡(jiǎn)單:
HTTP客戶端通過(guò)CONNECT方法請(qǐng)求隧道代理建立到任意目的服務(wù)器和端口的TCP連接,在客戶端和服務(wù)器之間盲目轉(zhuǎn)發(fā)后續(xù)數(shù)據(jù)。
下圖同樣來(lái)自《HTTP權(quán)威指南》,直觀地展示了上述行為:
如果我通過(guò)代理訪問(wèn)A網(wǎng)站,瀏覽器首先通過(guò)CONNECT請(qǐng)求請(qǐng)求代理建立到A網(wǎng)站的TCP連接; 一旦TCP連接建立,代理就可以不假思索地轉(zhuǎn)發(fā)后續(xù)流量。 所以這種代理理論上適用于任何基于TCP的應(yīng)用層協(xié)議。 當(dāng)然也可以使用HTTPS網(wǎng)站使用的TLS協(xié)議。 這就是為什么這種代理被稱(chēng)為隧道的原因。 (部分轉(zhuǎn)載)