低成本打造一個帶寬無限的網站 —— No.2 緩存防禦攻擊

網站攻擊

有次在和朋友討論網站防護時,提到一個信息發佈的站點 —— 它的結構很簡單,只有幾個頁面而已,正常情況下打開是非常快的。然而一到關鍵時刻,流量如同洪水般湧來。網站無法訪問,那些付費發佈的信息就錯過最佳展現時間了。

對於網站攻擊,現成的解決方案有很多,例如用上 WAF、CDN 等服務,多少能分擔一些。不過,通用的防禦方案,自然就有通用的攻擊方案。

例如通過 DNS 實現的負載均衡,攻擊者使用現成的工具,就能輕易遍歷出對應的 IP。更糟的是,有時域名會緩存很久,使得攻擊都快結束瞭解析還沒生效。

對於前端愛好者來說,這種傳統的方案一點都不 Geek —— 理想的防護,顯然應該從前後端同時入手。

提到前端,也許你會覺得奇怪,網站都被打垮了,還哪來的前端?別急。我們先來思考個本質問題:爲什麼網站容易垮。

相比網頁,傳統的應用程序在網絡不好的情況下,表現的更爲強勁。例如一些網絡視頻播放器,即使沒連網也能啓動,只是不能觀看在線視頻而已,但仍可作爲普通播放器使用;而網頁版的視頻站點,顯然就沒這麼強大了,如果沒連網,連基本界面都看不到。

這個道理大家都懂。因爲應用程序是事先下載到本地的,所以後期運行時,界面、程序可以直接啓動,只有信息才依賴網絡;而網頁的界面、程序、信息,很多時候是混在一起的,每次都得實時傳輸。所以極端情況下,網頁表現得更爲脆弱。

改進

因此,我們需要對網頁做一些改造,將「界面、程序」和「信息」徹底分離。

  • 前者通常較少變動,因此可對相應的資源設置 強緩存。強緩存是不走流量、直接從本地讀取的,所以用戶只要訪問過一次,之後界面就可以瞬間展現、程序可以立即運行 —— 無論網站是否繁忙!

  • 後者是動態加載的數據,存放位置並沒有限制,因此可放在多個後備站點上 —— 無論自己的站點,還是免費空間。

當基本界面展現後,程序通過 AJAX 從外部站點獲取信息,然後填充到頁面裏。如果獲取失敗,則嘗試後備列表 —— 除非所有站點都垮了,否則只要有一個活着,信息仍能展示!

cache-boot.svg

有了這樣的機制,就能降低網站故障的影響了。除了沒有緩存的「新用戶」無法打開網站,那些曾經訪問過的回頭客,仍可正常瀏覽!

再改進

更進一步,只要不是服務崩潰、流量被封那種硬故障,我們還可繼續優化,使新用戶也有機會訪問。

在帶寬喫緊的情況下,我們需要對「界面和程序」進行精簡,使其只需極小的傳輸流量,從而能在夾縫中求生。

那麼,這究竟能精簡到多小?事實上,只需一行 HTML 就夠了:

<script src="//free-host-n/boot.js"></script>

我們可讓網站所有的界面和功能,都由一個外部腳本來創建。這樣,整個站點只需一個幾十字節的頁面,僅僅作爲啓動器而已!

儘管最終 99.99% 的流量都來自其他站點,但瀏覽器的地址欄,顯示的仍是當前站點:)

mini-boot.svg

現在,只要帶寬還有一絲殘喘的餘地,新用戶就有機會獲取到這個迷你啓動頁,進而從互聯網上各個節點加載出完整內容!

由於整個站點只承載一個極小的文件,因此防禦策略可以簡單很多。此外,外部腳本的路徑可通過後端工具隨時改變,用以避開速度緩慢的節點 —— 畢竟 HTTP 控制緩存的能力,比 DNS 豐富多了!

缺陷

當然,這個方案似乎過於激進 —— 不僅需要對業務做大量改造,而且對搜索引擎也不利,因此最終並沒有實際應用。

此外,還有一個大問題也未能解決:用戶刷新頁面,會導致強緩存失效,從而產生網絡請求。如果此時網站掛了,那麼用戶刷新後,不是長時間等待,就是直接顯示錯誤。

如此美妙的防禦方案,最終卻防不住 F5 按鈕。。。這個問題,直到 HTML5 時代的一項新科技才能解決 —— 應用緩存。

應用緩存

關於應用緩存,熟悉前端的小夥伴們都不陌生,它正是爲提高 WebApp 的體驗而設計。

應用緩存的用法很簡單,通過一個列表清單,告訴瀏覽器預先緩存哪些資源:

<html manifest="list.appcache">

之後訪問列表中的資源時,瀏覽器就直接從本地讀取。相比強緩存,應用緩存的離線程度更高 —— 不僅沒連網也能訪問,甚至還可以刷新!

緩存不耐刷的問題,總算是能解決了。只是此時興致已過,並沒有去嘗試改進。對於瀏覽器緩存,當時覺得更好玩的還是攻擊方面 —— 中間人和前端腳本相互結合,批量污染緩存。

也許正是因爲易受中間人污染,以及 不夠靈活 等原因,應用緩存始終存在一些爭議,以至於後來被 Web 標準廢棄了。取而代之的,則是一個更逆天的標準。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章