一個多月前,我的個人網站遭受 DDOS 攻擊,下線了50多個小時。這篇文章就來談談,如何應對這種攻擊。
需要說明的是,我對 DDOS 並不精通,從沒想過自己會成為攻擊目標。攻擊發生以後,很多素昧平生的朋友提供了各種幫助和建議,讓我學到了很多東西。這裡記錄的就是對我最有幫助的一些解決方案。
一、DDOS 是什麼?
首先,我來解釋一下,DDOS 是什麼。
舉例來說,我開了一家餐廳,正常情況下,最多可以容納30個人同時進餐。你直接走進餐廳,找一張桌子坐下點餐,馬上就可以吃到東西。
很不幸,我得罪了一個流氓。他派出300個人同時湧進餐廳。這些人看上去跟正常的顧客一樣,每個都說"趕快上餐"。但是,餐廳的容量只有30個人,根本不可能同時滿足這麼多的點餐需求,加上他們把門口都堵死了,裡三層外三層,正常用餐的客人根本進不來,實際上就把餐廳癱瘓了。
這就是 DDOS 攻擊,它在短時間內發起大量請求,耗盡伺服器的資源,無法響應正常的訪問,造成網站實質下線。
DDOS 裡面的 DOS 是 denial of service(停止服務)的縮寫,表示這種攻擊的目的,就是使得服務中斷。最前面的那個 D 是 distributed (分散式),表示攻擊不是來自一個地方,而是來自四面八方,因此更難防。你關了前門,他從後門進來;你關了後門,他從視窗跳起來。
二、DDOS 的種類
DDOS 不是一種攻擊,而是一大類攻擊的總稱。它有幾十種型別,新的攻擊方法還在不斷發明出來。網站執行的各個環節,都可以是攻擊目標。只要把一個環節攻破,使得整個流程跑不起來,就達到了癱瘓服務的目的。
其中,比較常見的一種攻擊是 cc 攻擊。它就是簡單粗暴地送來大量正常的請求,超出伺服器的最大承受量,導致當機。我遭遇的就是 cc 攻擊,最多的時候全世界大概20多個 IP 地址輪流發出請求,每個地址的請求量在每秒200次~300次。我看訪問日誌的時候,就覺得那些請求像洪水一樣湧來,一眨眼就是一大堆,幾分鐘的時間,日誌檔案的體積就大了100MB。說實話,這隻能算小攻擊,但是我的個人網站沒有任何防護,伺服器還是跟其他人共享的,這種流量一來立刻就下線了。
本文以下的內容都是針對 cc 攻擊。
三、備份網站
防範 DDOS 的第一步,就是你要有一個備份網站,或者最低限度有一個臨時主頁。生產伺服器萬一下線了,可以立刻切換到備份網站,不至於毫無辦法。
備份網站不一定是全功能的,如果能做到全靜態瀏覽,就能滿足需求。最低限度應該可以顯示公告,告訴使用者,網站出了問題,正在全力搶修。我的個人網站下線的時候,我就做了一個臨時主頁,很簡單的幾行 HTML 程式碼。
這種臨時主頁建議放到 Github Pages 或者 Netlify,它們的頻寬大,可以應對攻擊,而且都支援繫結域名,還能從原始碼自動構建。
四、HTTP 請求的攔截
如果惡意請求有特徵,對付起來很簡單:直接攔截它就行了。
HTTP 請求的特徵一般有兩種:IP 地址和 User Agent 欄位。比如,惡意請求都是從某個 IP 段發出的,那麼把這個 IP 段封掉就行了。或者,它們的 User Agent 欄位有特徵(包含某個特定的詞語),那就把帶有這個詞語的請求攔截。
攔截可以在三個層次做。
(1)專用硬體
Web 伺服器的前面可以架設硬體防火牆,專門過濾請求。這種效果最好,但是價格也最貴。
(2)本機防火牆
作業系統都帶有軟體防火牆,Linux 伺服器一般使用 iptables。比如,攔截 IP 地址1.2.3.4
的請求,可以執行下面的命令。
$ iptables -A INPUT -s 1.2.3.4 -j DROP
iptables 比較複雜,我也不太會用。它對伺服器效能有一定影響,也防不住大型攻擊。
(3)Web 伺服器
Web 伺服器也可以過濾請求。攔截 IP 地址1.2.3.4
,nginx 的寫法如下。
location / { deny 1.2.3.4; }
Apache 的寫法是在.htaccess
檔案裡面,加上下面一段。
<RequireAll> Require all granted Require not ip 1.2.3.4 </RequireAll>
如果想要更精確的控制(比如自動識別並攔截那些頻繁請求的 IP 地址),就要用到 WAF。這裡就不詳細介紹了,nginx 這方面的設定可以參考這裡和這裡。
Web 伺服器的攔截非常消耗效能,尤其是 Apache。稍微大一點的攻擊,這種方法就沒用了。
五、頻寬擴容
上一節的 HTTP 攔截有一個前提,就是請求必須有特徵。但是,真正的 DDOS 攻擊是沒有特徵的,它的請求看上去跟正常請求一樣,而且來自不同的 IP 地址,所以沒法攔截。這就是為什麼 DDOS 特別難防的原因。
當然,這樣的 DDOS 攻擊的成本不低,普通的網站不會有這種待遇。不過,真要遇到了該怎麼辦呢,有沒有根本性的防範方法呢?
答案很簡單,就是設法把這些請求都消化掉。30個人的餐廳來了300人,那就想辦法把餐廳擴大(比如臨時再租一個門面,並請一些廚師),讓300個人都能坐下,那麼就不影響正常的使用者了。對於網站來說,就是在短時間內急劇擴容,提供幾倍或幾十倍的頻寬,頂住大流量的請求。這就是為什麼雲服務商可以提供防護產品,因為他們有大量冗餘頻寬,可以用來消化 DDOS 攻擊。
一個朋友傳授了一個方法,給我留下深刻印象。某雲服務商承諾,每個主機保 5G 流量以下的攻擊,他們就一口氣買了5個。網站架設在其中一個主機上面,但是不暴露給使用者,其他主機都是映象,用來面對使用者,DNS 會把訪問量均勻分配到這四臺映象伺服器。一旦出現攻擊,這種架構就可以防住 20G 的流量,如果有更大的攻擊,那就買更多的臨時主機,不斷擴容映象。
六、CDN
CDN 指的是網站的靜態內容分發到多個伺服器,使用者就近訪問,提高速度。因此,CDN 也是頻寬擴容的一種方法,可以用來防禦 DDOS 攻擊。
網站內容存放在源伺服器,CDN 上面是內容的快取。使用者只允許訪問 CDN,如果內容不在 CDN 上,CDN 再向源伺服器發出請求。這樣的話,只要 CDN 夠大,就可以抵禦很大的攻擊。不過,這種方法有一個前提,網站的大部分內容必須可以靜態快取。對於動態內容為主的網站(比如論壇),就要想別的辦法,儘量減少使用者對動態資料的請求。
上一節提到的映象伺服器,本質就是自己搭建一個微型 CDN。各大雲服務商提供的高防 IP,背後也是這樣做的:網站域名指向高防 IP,它提供一個緩衝層,清洗流量,並對源伺服器的內容進行快取。
這裡有一個關鍵點,一旦上了 CDN,千萬不要洩露源伺服器的 IP 地址,否則攻擊者可以繞過 CDN 直接攻擊源伺服器,前面的努力都白費。搜一下"繞過 CDN 獲取真實 IP 地址",你就會知道國內的黑產行業有多猖獗。
cloudflare 是一個免費 CDN 服務,並提供防火牆,高度推薦。我還要感謝 v2ex.com 的站長 @livid 熱情提供幫助,我現在用的就是他們的 CDN 產品。
更新(6月27日)
攻擊者看來訂閱了我的微博。昨天這篇文章釋出沒多久,我就又遭受了攻擊,他繞過CDN直接攻擊源伺服器(我不知道 IP 地址怎麼洩漏的),流量還大過上一次。
感謝騰訊雲的朋友,提供了一個高防 IP,使得網站可以重新上線。現在,我的防護措施是,源伺服器前面有 CDN。如果攻擊域名,CDN 可以擋住;如果直接攻擊源伺服器,我買了彈性 IP ,可以動態掛載主機例項,受到攻擊就換一個地址。這只是一個技術部落格,內容都是免費的,要防到這種地步,我也是無語了。
(完)