一、DDOS 是什么?
首先,我來解釋一下,DDOS 是什么。
舉例來說,我開了一家餐廳,正常情況下,最多可以容納30個(gè)人同時(shí)進(jìn)餐。你直接走進(jìn)餐廳,找一張桌子坐下點(diǎn)餐,馬上就可以吃到東西。
很不幸,我得罪了一個(gè)流氓。他派出300個(gè)人同時(shí)涌進(jìn)餐廳。這些人看上去跟正常的顧客一樣,每個(gè)都說"趕快上餐"。但是,餐廳的容量只有30個(gè)人,根本不可能同時(shí)滿足這么多的點(diǎn)餐需求,加上他們把門口都堵死了,里三層外三層,正常用餐的客人根本進(jìn)不來,實(shí)際上就把餐廳癱瘓了。
這就是 DDOS 攻擊,它在短時(shí)間內(nèi)發(fā)起大量請(qǐng)求,耗盡服務(wù)器的資源,無法響應(yīng)正常的訪問,造成網(wǎng)站實(shí)質(zhì)下線。
DDOS 里面的 DOS 是 denial of service(停止服務(wù))的縮寫,表示這種攻擊的目的,就是使得服務(wù)中斷。最前面的那個(gè) D 是 distributed (分布式),表示攻擊不是來自一個(gè)地方,而是來自四面八方,因此更難防。你關(guān)了前門,他從后門進(jìn)來;你關(guān)了后門,他從窗口跳起來。
二、DDOS 的種類
DDOS 不是一種攻擊,而是一大類攻擊的總稱。它有幾十種類型,新的攻擊方法還在不斷發(fā)明出來。網(wǎng)站運(yùn)行的各個(gè)環(huán)節(jié),都可以是攻擊目標(biāo)。只要把一個(gè)環(huán)節(jié)攻破,使得整個(gè)流程跑不起來,就達(dá)到了癱瘓服務(wù)的目的。
其中,比較常見的一種攻擊是 cc 攻擊。它就是簡單粗暴地送來大量正常的請(qǐng)求,超出服務(wù)器的最大承受量,導(dǎo)致宕機(jī)。我遭遇的就是 cc 攻擊,最多的時(shí)候全世界大概20多個(gè) IP 地址輪流發(fā)出請(qǐng)求,每個(gè)地址的請(qǐng)求量在每秒200次~300次。我看訪問日志的時(shí)候,就覺得那些請(qǐng)求像洪水一樣涌來,一眨眼就是一大堆,幾分鐘的時(shí)間,日志文件的體積就大了100MB。說實(shí)話,這只能算小攻擊,但是我的個(gè)人網(wǎng)站沒有任何防護(hù),服務(wù)器還是跟其他人共享的,這種流量一來立刻就下線了。
本文以下的內(nèi)容都是針對(duì) cc 攻擊。
三、備份網(wǎng)站
防范 DDOS 的第一步,就是你要有一個(gè)備份網(wǎng)站,或者最低限度有一個(gè)臨時(shí)主頁。生產(chǎn)服務(wù)器萬一下線了,可以立刻切換到備份網(wǎng)站,不至于毫無辦法。
備份網(wǎng)站不一定是全功能的,如果能做到全靜態(tài)瀏覽,就能滿足需求。最低限度應(yīng)該可以顯示公告,告訴用戶,網(wǎng)站出了問題,正在全力搶修。我的個(gè)人網(wǎng)站下線的時(shí)候,我就做了一個(gè)臨時(shí)主頁,很簡單的幾行 HTML 代碼。
這種臨時(shí)主頁建議放到 Github Pages 或者 Netlify,它們的帶寬大,可以應(yīng)對(duì)攻擊,而且都支持綁定域名,還能從源碼自動(dòng)構(gòu)建。
四、HTTP 請(qǐng)求的攔截
如果惡意請(qǐng)求有特征,對(duì)付起來很簡單:直接攔截它就行了。
HTTP 請(qǐng)求的特征一般有兩種:IP 地址和 User Agent 字段。比如,惡意請(qǐng)求都是從某個(gè) IP 段發(fā)出的,那么把這個(gè) IP 段封掉就行了?;蛘?,它們的 User Agent 字段有特征(包含某個(gè)特定的詞語),那就把帶有這個(gè)詞語的請(qǐng)求攔截。
攔截可以在三個(gè)層次做。
(1)專用硬件
Web 服務(wù)器的前面可以架設(shè)硬件防火墻,專門過濾請(qǐng)求。這種效果最好,但是價(jià)格也最貴。
(2)本機(jī)防火墻
操作系統(tǒng)都帶有軟件防火墻,Linux 服務(wù)器一般使用 iptables。比如,攔截 IP 地址1.2.3.4的請(qǐng)求,可以執(zhí)行下面的命令。
$ iptables -A INPUT -s 1.2.3.4 -j DROP
iptables 比較復(fù)雜,我也不太會(huì)用。它對(duì)服務(wù)器性能有一定影響,也防不住大型攻擊。
(3)Web 服務(wù)器
Web 服務(wù)器也可以過濾請(qǐng)求。攔截 IP 地址1.2.3.4,nginx 的寫法如下。
如果想要更精確的控制(比如自動(dòng)識(shí)別并攔截那些頻繁請(qǐng)求的 IP 地址),就要用到 WAF。這里就不詳細(xì)介紹了,nginx 這方面的設(shè)置可以參考這里和這里。
Web 服務(wù)器的攔截非常消耗性能,尤其是 Apache。稍微大一點(diǎn)的攻擊,這種方法就沒用了。
五、帶寬擴(kuò)容
上一節(jié)的 HTTP 攔截有一個(gè)前提,就是請(qǐng)求必須有特征。但是,真正的 DDOS 攻擊是沒有特征的,它的請(qǐng)求看上去跟正常請(qǐng)求一樣,而且來自不同的 IP 地址,所以沒法攔截。這就是為什么 DDOS 特別難防的原因。
當(dāng)然,這樣的 DDOS 攻擊的成本不低,普通的網(wǎng)站不會(huì)有這種待遇。不過,真要遇到了該怎么辦呢,有沒有根本性的防范方法呢?
答案很簡單,就是設(shè)法把這些請(qǐng)求都消化掉。30個(gè)人的餐廳來了300人,那就想辦法把餐廳擴(kuò)大(比如臨時(shí)再租一個(gè)門面,并請(qǐng)一些廚師),讓300個(gè)人都能坐下,那么就不影響正常的用戶了。對(duì)于網(wǎng)站來說,就是在短時(shí)間內(nèi)急劇擴(kuò)容,提供幾倍或幾十倍的帶寬,頂住大流量的請(qǐng)求。這就是為什么云服務(wù)商可以提供防護(hù)產(chǎn)品,因?yàn)樗麄冇写罅咳哂鄮挘梢杂脕硐?DDOS 攻擊。
一個(gè)朋友傳授了一個(gè)方法,給我留下深刻印象。某云服務(wù)商承諾,每個(gè)主機(jī)保 5G 流量以下的攻擊,他們就一口氣買了5個(gè)。網(wǎng)站架設(shè)在其中一個(gè)主機(jī)上面,但是不暴露給用戶,其他主機(jī)都是鏡像,用來面對(duì)用戶,DNS 會(huì)把訪問量均勻分配到這四臺(tái)鏡像服務(wù)器。一旦出現(xiàn)攻擊,這種架構(gòu)就可以防住 20G 的流量,如果有更大的攻擊,那就買更多的臨時(shí)主機(jī),不斷擴(kuò)容鏡像。
六、CDN
CDN 指的是網(wǎng)站的靜態(tài)內(nèi)容分發(fā)到多個(gè)服務(wù)器,用戶就近訪問,提高速度。因此,CDN 也是帶寬擴(kuò)容的一種方法,可以用來防御 DDOS 攻擊。
網(wǎng)站內(nèi)容存放在源服務(wù)器,CDN 上面是內(nèi)容的緩存。用戶只允許訪問 CDN,如果內(nèi)容不在 CDN 上,CDN 再向源服務(wù)器發(fā)出請(qǐng)求。這樣的話,只要 CDN 夠大,就可以抵御很大的攻擊。不過,這種方法有一個(gè)前提,網(wǎng)站的大部分內(nèi)容必須可以靜態(tài)緩存。對(duì)于動(dòng)態(tài)內(nèi)容為主的網(wǎng)站(比如論壇),就要想別的辦法,盡量減少用戶對(duì)動(dòng)態(tài)數(shù)據(jù)的請(qǐng)求。
上一節(jié)提到的鏡像服務(wù)器,本質(zhì)就是自己搭建一個(gè)微型 CDN。各大云服務(wù)商提供的高防 IP,背后也是這樣做的:網(wǎng)站域名指向高防 IP,它提供一個(gè)緩沖層,清洗流量,并對(duì)源服務(wù)器的內(nèi)容進(jìn)行緩存。