反爬蟲和抗DDOS攻擊技術實踐


導語

企鵝媒體平台媒體名片頁反爬蟲技術實踐,分布式網頁爬蟲技術、利用人工智能進行人機識別、圖像識別碼、頻率訪問控制、利用無頭瀏覽器PhantomJS、Selenium 進行網頁抓取等相關技術不在本文討論范圍內。

大家都知道http請求是無狀態的,為了讓http請求從“無狀態” to “有狀態” , W3C 在 rfc6265 中描述了整個http協議的狀態機制,既從客戶端(通常是瀏覽器)到服務器端的流轉過程,cookie 的引入使得 服務器在 接收到請求時可以區分用戶和狀態。

通過上邊這張圖,我們可以容易的發現,這個過程就好像“上車打票”一樣,有普通票(不記名)和 也月票(“記名的票”),有位偉大的程序員曾經說過“如果你的程序邏輯和實際生活中的邏輯反了,就一定是你錯了”。

言歸正傳,為什么反爬蟲

互聯網有很多業務或者說網頁,是不需要用戶進行登錄的(不記名的票),你可以簡單的認為這其實是一個“不需要記錄http狀態的業務場景”(注意這里是簡單認為,但其實並不是無狀態的),那這些不需要登錄的頁面,往往又會包含大量的聚合信息,比如新聞門戶網站、視頻門戶網站、搜索引擎,這些信息是公開的,其實是可以可以被爬蟲抓取的,站長甚至還要做SEO(搜索引擎優化)讓搜索引擎或其他網站更多更經常的去收錄自己的整站,以便推廣,那既然我們要做SEO優化為什么還要 “反爬蟲” ?

因為通過程序進行 URL 請求 去獲得數據的成本是很低的,這就造成大量抵質量網頁爬蟲在網絡橫行,對業務方的服務器造成不必要的流量浪費和資源消耗。

網頁爬蟲到底有多容易

正常打開的界面內容是這樣的

查看網頁源代碼,看看我們要抓取的目標,這里就不在演示了,然后利用Chrome開發者工具提供的 “Copy as curl”

curl 'https://v.qq.com/' -H 'Pragma: no-cache' -H 'DNT: 1' -H 'Accept-Encoding: gzip, deflate, sdch, br' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Cache-Control: no-cache' -H 'Cookie: tvfe_boss_uuid=ad12b5df44c4af49; ad_play_index=34; pgv_info=ssid=s9710442890; ts_last=v.qq.com/; pgv_pvid=7925047056; ts_uid=578794400; qv_als=778esxpJSKmr5N0bA11491899166PnRBKw==' -H 'Connection: keep-alive' --compressed 

然后你會發現,與“查看網頁源代碼” 沒有區別,說明我們已經成功獲得數據內容。

反爬蟲效果是什么樣的?

我們通過瀏覽器直接打開下面這個鏈接 ,會發現請求到的結果是個JSON

現在我們重復剛剛的 “Copy as curl” 的過程,看看是否依然能獲得正確結果 ? 答案是否定的,我們來驗證一下

curl 'https://media.om.qq.com/media/5054675/list' -H 'pragma: no-cache' -H 'dnt: 1' -H 'accept-encoding: gzip, deflate, sdch, br' -H 'accept-language: zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4' -H 'upgrade-insecure-requests: 1' -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36' -H 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'cache-control: no-cache' -H 'authority: media.om.qq.com' -H 'cookie: signiture=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjpbXSwiZWkiOjUsInN0IjoiMTQ5MTg5OTczNjQ3NyIsImlhdCI6MTQ5MTg5OTc0M30.fTAsbJZNOTsHk0QoLfZIA-AXhO6ezaCOiCTj8lYCqO4; tvfe_boss_uuid=ad12b5df44c4af49; pgv_info=ssid=s9710442890; pgv_pvid=7925047056; omuisid=eyJ1aWQiOiI5ZGVjMjRiN2UxM2FiNGUyZWJjNWRhMGU1N2EyYTRkZSJ9; omuisid.sig=5wAr5khpxGvFDp3WpkJ6_QX9iE4' -H 'referer: https://media.om.qq.com/media/5054675/list' --compressed 

我們會發現得到的是一個網頁而不是 JSON,命中了反爬蟲邏輯

到底發生了什么?

前面提到了 “不記名票據” 和 因推廣需求網站不需要登錄的場景,那針對這樣的情況,是否我們就真的不需要對請求進行簽名呢 ? 答案是否定的,不花錢或花很少的錢就可以免費進入公園游玩了,游客可能本身是感受不到“票據”的存在,但其實我們還是需要對用戶進行標記,這里發散一下,其實統計網站在追蹤pv/uv時也是進行了類似的“標記”,下面我們通過一張圖來描述下上面請求發生的過程

這里我們有兩次簽名過程,一次在服務器端進行,一次在客戶端進行,因為在這個頁面是不需要用戶登錄,所以在服務器端進行簽名,對於爬蟲來說是一個幾乎沒有成本的過程,它可以每次來“園子”里玩的時候,都申請一張新的票,偽裝成為一個“新的用戶”,為了應對如此低廉的成本,我們增加“客戶端進行簽名”的流程,有人說“客戶端簽名是不靠譜的,因為你的代碼別人都是可以看到的是可以破解的”,這個地方的客戶端簽名不是為了數據安全,而是為了增加爬蟲進行抓取的成本,因為一般網頁爬蟲都不具備 js 之行能力,這樣就增加了它抓取的成本。

另外一點,簽名雖然是由客戶端簽發的,但是卻是由服務器端進行驗證,我們這里是利用 JWT(JSON WEB TOKEN) 進行了 encode和decode過程,且通過將服務器時間對客戶端進行下發,完成有效期控制。

起到一定的防DDOS攻擊的效果

通過上圖我們可以看到,關鍵就是兩次票據的簽發與驗證,一次由瀏覽器簽發,一次由后台簽發,但是驗證真偽都是在服務端進行,這樣做的最終效果就是,要對我們的界面進行抓取或攻擊的人,必須按照我們設定的套路運轉,就會增加他下載js並執行我們js的過程,如果有攻擊方利用xss 獲的肉機,對我們的域名發起攻擊時,由於我們有兩次票據驗證,而去其中有一個票據的有效期時間很短,基本上不太可能對我們的服務器造成連續傷害了。

如果網頁抓取人,通過使用完全模擬瀏覽器的運行環境的第三方軟件(PhantomJS、Selenium,WEBDRIVER)對我們進行抓取,其實效率是很慢的,基本上需要5-6秒完成一次, 基本上比一個真實的用戶打開網頁還要慢很多,對於這種可以當成是真是用戶一樣對待,數據本來就是開放的

接入這套反爬、防DDOS邏輯后,從模調系統查看數據后台服務被擊穿的現象已經完成消失,異常流量已被隔離。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM