反爬蟲和抗DDOS攻擊技術實踐
來自專欄 伺服器運維與安全
導語
企鵝媒體平台媒體名片頁反爬蟲技術實踐,分散式網頁爬蟲技術、利用人工智慧進行人機識別、圖像識別碼、頻率訪問控制、利用無頭瀏覽器PhantomJS、Selenium 進行網頁抓取等相關技術不在本文討論範圍內。
Cookie是什麼
大家都知道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邏輯後,從模調系統查看數據後台服務被擊穿的現象已經完成消失,異常流量已被隔離。
作者 | 張寧
編輯 | 迷鹿此文已由作者授權騰訊雲技術社區發布,轉載請註明文章出處
推薦閱讀:
※現在比較好用的漏洞掃描和注入攻擊的工具?
※手游棋牌高防解決方案
※Linux伺服器如何預防DDoS攻擊
※因為DDoS 芬蘭某地停止供暖一周多
※Memcache-DRDos實踐-實現核彈級DDoS攻擊