1 序言
本次文章系列将會(huì)逐步分享作(zuò)者親身經曆以及解決思路,讓大(dà)家(jiā)一起身臨其境,作(zuò)為(wèi)開(kāi)篇,會(huì)先和(hé)大(dà)家(jiā)聊點有(yǒu)趣的,做(zuò)這件事的動機,對我的職業道(dào)路有(yǒu)什麽影(yǐng)響等,大(dà)家(jiā)可(kě)以仁者見仁智者見智。
其實對我們正常程序員的工作(zuò)流程來(lái)說,網絡這塊對我們來(lái)說基本不會(huì)涉及,因為(wèi)公司的職責分配,大(dà)家(jiā)都會(huì)隻負責自己的部分,例如ui隻負責ui,測試隻負責功能測試性能測試,軟件開(kāi)發隻負責軟件開(kāi)發,運維隻負責服務器(qì)資源調配整合管理(lǐ),網絡管理(lǐ)等等,但(dàn)是其實對于大(dà)多(duō)數(shù)程序員來(lái)說,公司的規模不大(dà)的情況下,一般都會(huì)身兼數(shù)職,又是軟件開(kāi)發,又是測試,還(hái)需要去部署項目。那(nà)麽既然大(dà)家(jiā)都有(yǒu)機會(huì)橫向拓展自身的技(jì)能,其實真的可(kě)以利用好機會(huì)去學習,去實踐,看的再多(duō),了解的再多(duō)不如實際去試試。
又到了我最喜歡的講故事環節啦~ 曾經我也是一名普通(tōng)的Java程序開(kāi)發,每天寫寫bug,調試一下代碼,和(hé)産品鬥鬥嘴,日子一天天這樣愉快的過去。
突然一天,接到公司電(diàn)話(huà):"大(dà)事不好了,所有(yǒu)用戶都無法正常使用應用啦,用戶投訴已經快把公司電(diàn)話(huà)打爆了。你(nǐ)趕快解決!" 當時(shí)還(hái)在休周末假期的我,一下就從床上(shàng)挺直了身闆,心想:不會(huì)吧(ba),代碼應該沒問題啊,我不可(kě)能錯的啊(ps:程序員的蜜汁自信) 緊接着馬上(shàng)打開(kāi)筆記本電(diàn)腦(nǎo),開(kāi)始排查問題,首先從用戶反饋的截圖來(lái)看,應用其實連接超時(shí),沒有(yǒu)任何響應。那(nà)此時(shí)可(kě)以排除掉app應用本身的問題,然後立馬使用接口測試工具postman測試一個(gè)線上(shàng)的接口,發現确實無任何響應了,糟糕,難道(dào)我的Java服務挂了?然後懷着忐忑的心情登錄遠程服務器(qì),發現服務器(qì)居然也無法登錄了,這是什麽情況?
由于我使用的是阿裏雲的雲産品,所以立馬登錄阿裏雲賬号,發起一個(gè)工單咨詢阿裏雲的技(jì)術(shù)支持,在明(míng)确告知了雲服務器(qì)實例id以及無法訪問的異常情況後,等待對方的反饋。在這裏給阿裏雲技(jì)術(shù)支持點個(gè)贊,技(jì)術(shù)反饋很(hěn)快,并且态度十分友(yǒu)好。最後阿裏雲技(jì)術(shù)支持反饋工單說我們的服務器(qì)請(qǐng)求流量異常,進入他們的黑(hēi)洞機制(zhì)了。wtf?說的白話(huà)一點就是有(yǒu)人(rén)在對我們服務器(qì)進行(xíng)ddos攻擊,我們服務器(qì)的資源被耗盡并且觸發了阿裏雲的黑(hēi)洞機制(zhì),我們服務器(qì)被丢進"小(xiǎo)黑(hēi)屋"了,什麽都做(zuò)不了,第一次進入黑(hēi)洞就是兩個(gè)小(xiǎo)時(shí),後面在進入黑(hēi)洞就會(huì)逐漸時(shí)長增加。
這可(kě)不得(de)了,首先在聯系客戶,安撫客戶的同時(shí),也馬上(shàng)開(kāi)始針對這次攻擊做(zuò)出反應。期間(jiān)黑(hēi)客甚至還(hái)匿名聯系過我們,态度十分嚣張,說什麽不給"保護費"就會(huì)一直對我們服務器(qì)進行(xíng)攻擊,不讓我們正常營業,還(hái)趾高(gāo)氣昂的說什麽今天不交5k的保護費,明(míng)天再交那(nà)就是一個(gè)達不溜,這話(huà)聽(tīng)着怎麽這麽耳熟呢?今日割五城,明(míng)日割十城,然後得(de)一夕安寝。取自<<六國論>>中的經典短(duǎn)句,今日你(nǐ)割讓5個(gè)城池,明(míng)天再讓你(nǐ)割讓10個(gè)城池,以此換來(lái)睡一個(gè)安穩的覺,然而第二天一看,秦國的軍隊又來(lái)了。
壞人(rén)的欲望是無法滿足的。于是我緊急查找做(zuò)網絡防火(huǒ)牆的解決方案提供商,阿裏雲的高(gāo)防,一年40多(duō)萬的費用,讓我們望而卻步,畢竟公司的業務暫時(shí)沒有(yǒu)這麽大(dà)的量級,這個(gè)方案屬于不适合當前的,最後接入了一家(jiā)小(xiǎo)衆公司的網絡防火(huǒ)牆方案,最後以一個(gè)月599的價格購買了一個(gè)标準套餐的防火(huǒ)牆,測試通(tōng)過後就将流量全部轉移到他們的防火(huǒ)牆進行(xíng)流量清洗和(hé)監控,最後回源到我們服務中,而攻擊我們的黑(hēi)客最後也是費勁心思的攻擊幾次後,眼看攻擊無果,最後灰溜溜的消失在了我們視(shì)線中。
在經曆了服務不可(kě)用之後再恢複正常使用的這段黑(hēi)暗時(shí)刻後,其實心裏還(hái)是很(hěn)緊張的,首先就是自身處于舒适圈,沒有(yǒu)保持一個(gè)良好的學習熱忱,導緻技(jì)術(shù)棧相對狹隘,認為(wèi)一個(gè)軟件應用從開(kāi)發好後,把服務部署到服務器(qì)上(shàng),解析一個(gè)域名綁定服務器(qì)ip,然後讓app調用這個(gè)域名跟服務接口就完成了任務,認為(wèi)自己這樣做(zuò)開(kāi)發效率還(hái)很(hěn)快,沾沾自喜,其實正是落入自己給自己設下的糖衣陷阱,限制(zhì)了自己的思想,阻礙了自己思考的能力,于是我利用接入了第三方的防火(huǒ)牆這段時(shí)間(jiān),自己也在惡補網絡相關的知識,彌補自己對互聯網中的知識匮乏。
首先這次攻擊,再通(tōng)過第三方防火(huǒ)牆的管理(lǐ)後台中,我們可(kě)以清楚的看到所有(yǒu)的請(qǐng)求ip以及各個(gè)ip的請(qǐng)求次數(shù),可(kě)以看到正常ip的請(qǐng)求頻率在一分鍾以內(nèi)一般也就幾十個(gè)連接請(qǐng)求,但(dàn)是有(yǒu)一批ip的請(qǐng)求都是幾萬次,明(míng)顯不正常,通(tōng)過百度搜索這些(xiē)ip,無一例外都是海外的ip,也就是什麽馬來(lái)西亞啊,柬埔寨啊等等是非之地的ip,這一看就是被控制(zhì)了肉雞對我們同時(shí)進行(xíng)的ddos攻擊,導緻我們服務的癱瘓。
引用百度百科中,DDOS一般指分布式拒絕服務攻擊,分布式拒絕服務攻擊(英文意思是Distributed Denial of Service,簡稱DDoS)是指處于不同位置的多(duō)個(gè)攻擊者同時(shí)向一個(gè)或數(shù)個(gè)目标發動攻擊,或者一個(gè)攻擊者控制(zhì)了位于不同位置的多(duō)台機器(qì)并利用這些(xiē)機器(qì)對受害者同時(shí)實施攻擊。由于攻擊的發出點是分布在不同地方的,這類攻擊稱為(wèi)分布式拒絕服務攻擊,其中的攻擊者可(kě)以有(yǒu)多(duō)個(gè)。也就是上(shàng)面我們所遇到的對方使用非法技(jì)術(shù)手段控制(zhì)多(duō)台計(jì)算(suàn)機,同時(shí)對我們的這台服務進行(xíng)攻擊。而單一的DoS攻擊一般是采用一對一方式的,它利用網絡協議和(hé)操作(zuò)系統的一些(xiē)缺陷,采用欺騙和(hé)僞裝的策略來(lái)進行(xíng)網絡攻擊,使網站(zhàn)服務器(qì)充斥大(dà)量要求回複的信息,消耗網絡帶寬或系統資源,導緻網絡或系統不勝負荷以至于癱瘓而停止提供正常的網絡服務。也就是dos就是1v1單挑,拼的是誰的主機資源性能更好,而ddos就是不講武德,多(duō)人(rén)運動,以多(duō)欺少(shǎo)。
既然知道(dào)了攻擊手段,那(nà)如何防範呢?那(nà)就要說說防火(huǒ)牆的分類了,一般防火(huǒ)牆是有(yǒu)物理(lǐ)硬件防火(huǒ)牆和(hé)軟件防火(huǒ)牆兩種,硬件防火(huǒ)牆代表有(yǒu)著名的F5,Symantec等,這類軟硬一體(tǐ)防火(huǒ)牆,國內(nèi)也有(yǒu)很(hěn)多(duō)做(zuò)硬件防火(huǒ)牆的廠家(jiā),例如天融信,啓明(míng)星辰,聯想網禦,華為(wèi),深信服等等。軟件防火(huǒ)牆有(yǒu)firewall,iptables等等
其中軟件防火(huǒ)牆也稱為(wèi)個(gè)人(rén)防火(huǒ)牆,它是最常用的防火(huǒ)牆,通(tōng)常作(zuò)為(wèi)計(jì)算(suàn)機系統上(shàng)的程序運行(xíng),它是可(kě)定制(zhì)的,允許用戶控制(zhì)其功能。軟件防火(huǒ)牆單獨使用軟件系統來(lái)完成防火(huǒ)牆功能,将軟件部署在系統主機上(shàng),其安全性較硬件防火(huǒ)牆差,同時(shí)占用系統資源,在一定程度上(shàng)影(yǐng)響系統性能。硬件防火(huǒ)牆是指把防火(huǒ)牆程序做(zuò)到芯片裏面,由硬件執行(xíng)這些(xiē)功能,能減少(shǎo)CPU的負擔,使路由更穩定。一般的軟件安全廠商所提供的硬件防火(huǒ)牆便是在硬件服務器(qì)廠商定制(zhì)硬件,然後再把linux系統與自己的軟件系統嵌入。(Symantec的SGS便是DELL+Symantec的軟件防火(huǒ)牆)這樣做(zuò)的好處是linux相對Windows的server相對安全。
至于價格高(gāo),原因在于,軟件防火(huǒ)牆隻有(yǒu)包過濾的功能,硬件防火(huǒ)牆中可(kě)能還(hái)有(yǒu)除軟件防火(huǒ)牆以外的其他功能,例如CF(內(nèi)容過濾)IDS(入侵偵測)IPS(入侵防護)以及VPN等等的功能。軟件防火(huǒ)牆一般可(kě)以是包過濾機制(zhì)。包過濾過濾規則簡單,隻能檢查到第三層網絡層,隻對源或目的IP做(zuò)檢查,防火(huǒ)牆的能力遠不及狀态檢測防火(huǒ)牆,連最基本的黑(hēi)客攻擊手法IP僞裝都無法解決,并且要對所經過的所有(yǒu)數(shù)據包做(zuò)檢查,所以速度比較慢。硬件防火(huǒ)牆主要采用第四代狀态檢測機制(zhì)。狀态檢測是在通(tōng)信發起連接時(shí)就檢查規則是否允許建立連接,然後在緩存的狀态檢測表中添加一條記錄,以後就不必去檢查規則了隻要查看狀态監測表就OK了,速度上(shàng)有(yǒu)了很(hěn)大(dà)的提升。
軟件防火(huǒ)牆隻能保護安裝它的系統。硬件防火(huǒ)牆保障整個(gè)內(nèi)部網絡安全。它的安全和(hé)穩定,直接關系到整個(gè)內(nèi)部網絡的安全。如果所在的網絡環境中,攻擊頻度不是很(hěn)高(gāo),用軟件防火(huǒ)牆就能滿足要求了。軟件防火(huǒ)牆的優點是定制(zhì)靈活,升級快捷。倘若攻擊頻度很(hěn)高(gāo),建議用硬件來(lái)實現。
硬件防火(huǒ)牆的抗攻擊能力比軟件防火(huǒ)牆的高(gāo)很(hěn)多(duō),通(tōng)過硬件實現的功能,效率高(gāo),專門(mén)為(wèi)了防火(huǒ)牆這一個(gè)任務設計(jì)的,內(nèi)核針對性很(hěn)強。軟件防火(huǒ)牆在遇到密集的DDOS攻擊的時(shí)候,它所能承受的攻擊強度遠遠低(dī)于硬件防火(huǒ)牆。因為(wèi)硬件防火(huǒ)牆将防火(huǒ)牆功能集成到芯片中,有(yǒu)硬件執行(xíng),對于計(jì)算(suàn)機的cpu使用可(kě)以算(suàn)是0占用,穩定性要高(gāo)得(de)多(duō),而軟件防火(huǒ)牆是安裝和(hé)運行(xíng)在計(jì)算(suàn)機中,在運行(xíng)時(shí)是會(huì)占用當前計(jì)算(suàn)機的cpu以及內(nèi)存,所以相對硬件要差一些(xiē)。
不用說,那(nà)肯定是硬件防火(huǒ)牆的成本是最高(gāo)的,畢竟設備廠商是靠買這些(xiē)硬件掙錢(qián)的,一般的硬件防火(huǒ)牆在1到幾萬不等,好點的都是十萬開(kāi)外了,而軟件防火(huǒ)牆相對就要友(yǒu)好的多(duō)了,隻需要能安裝軟件防火(huǒ)牆能力的主機即可(kě),成本直線下降。對于小(xiǎo)型企業或者個(gè)人(rén)用戶來(lái)說,使用軟件防火(huǒ)牆是最适合的。
那(nà)麽此次的防火(huǒ)牆集群搭建的第一小(xiǎo)步,就是先在單機上(shàng)部署好一個(gè)軟件防火(huǒ)牆并且設定規則。我先是在阿裏雲上(shàng)購買了一台1核1g的雲服務器(qì),系統鏡像選擇centos 7.5 64位的。磁盤由于可(kě)能隻需要存一點點日志(zhì),對于磁盤要求不大(dà),所以選擇40G的一個(gè)磁盤挂載,網絡帶寬我們選擇按量付費,最高(gāo)帶寬值拉滿100M,這樣的配置,一台服務器(qì)的費用僅僅需要53塊一個(gè)月!流量費用在超過每月贈送的固定值後按照每GB8毛錢(qián)來(lái)結算(suàn)。
centos7.5版本以後系統內(nèi)核編譯的防火(huǒ)牆默認是firewall,而本次我們使用的是iptables,所以我們需要先關閉原本的firewall,然後下載安裝iptables,再使用iptables命令來(lái)進行(xíng)添加規則,最後安裝一個(gè)nginx做(zuò)前置網關,負載均衡到自己軟件服務主機上(shàng),以此來(lái)完成軟件防火(huǒ)牆的閉環搭建。
systemctl stop firewalld
systemctl mask firewalld
yum install -y iptables
yum update iptables
yum install iptables-services
iptables -P INPUT ACCEPT
iptables -F
iptables -X
iptables -Z
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
service iptables save
systemctl enable iptables.service
systemctl start iptables.service
yum install -y nginx
systemctl start nginx.service
systemctl enable nginx.service
客戶端的請(qǐng)求直接通(tōng)過域名解析訪問到實際業務主機上(shàng),形同裸體(tǐ),不設防備,所有(yǒu)請(qǐng)求直接打在業務服務器(qì)上(shàng),在沒有(yǒu)架設後置網關的情況,沒有(yǒu)負載均衡能力,服務容易被攻擊,不安全。并且服務器(qì)的真實ip暴露,容易被不法分子進行(xíng)ssh爆破攻擊,對服務器(qì)運行(xíng)帶來(lái)許多(duō)不穩定因素。
客戶端的請(qǐng)求通(tōng)過域名解析來(lái)到了防火(huǒ)牆所在的主機上(shàng),在驗證了請(qǐng)求ip是否符合規範等情況後,由nginx轉發請(qǐng)求到業務服務器(qì)上(shàng),返回地址也使用防火(huǒ)牆的ip地址信息,從而隐藏了真實的服務ip,避免暴露。本篇文章作(zuò)為(wèi)第一章節,隻介紹單機版本的搭建,以及實現邏輯,下一章節便給大(dà)家(jiā)帶來(lái)集群如何實現,以及為(wèi)什麽要用集群的防火(huǒ)牆,單機的為(wèi)什麽不行(xíng)。
既然我們已經搭建好并且啓動了上(shàng)述iptables,我們知道(dào)iptables也能拒絕連接,甚至可(kě)以拒接指定ip的連接,那(nà)我們隻需要寫一個(gè)腳本,每次啓動都檢測一下當前的ip連接數(shù),對于單個(gè)ip連接數(shù)異常高(gāo)的進行(xíng)一個(gè)封禁,那(nà)這個(gè)ip所有(yǒu)的請(qǐng)求在達到防火(huǒ)牆這一層就會(huì)被自動丢棄,不占用系統的資源了,也不影(yǐng)響正常的用戶ip的請(qǐng)求。
#iptables 禁用單個(gè)ip連接
iptables -I INPUT -s 1.2.3.4 -j DROP
#或
iptables -A INPUT -s 1.2.3.4 -j DROP
-A 指定規則應該添加到的 chain 的名稱。例如,使用 INPUT 将會(huì)把規則添加到默認的 INPUT(入站(zhàn))鏈的末尾,而使用 OUTPUT 則會(huì)将規則添加到出站(zhàn)鏈的末尾。
-I 将規則添加為(wèi) chain 中的第 rulenum 條規則,原先的第 rulenum 條及以後各條的需要順次 +1。如上(shàng)面一樣,1 表示該 chain 中第一條。默認為(wèi) 1,即,如果沒有(yǒu)指定 rulenum 則将該 chain 中第一條規則替換掉。
wget 'http://blog.houlangmark.com/ddos.sh' -O /etc/ddos/ddos.sh
vim 這個(gè)ddos腳本,主要的命令為(wèi)下面這行(xíng)
cd /etc/ddos
vim ddos.sh
netstat -an |grep ^tcp.*:80|egrep -v 'LISTEN|127.0.0.1'|awk -F"[ ]+|[:]" '{print $6}'|sort|uniq -c|sort -rn
此時(shí)便可(kě)以通(tōng)過定時(shí)啓動腳本一直檢測網絡連接的ip,找到非法的ip進行(xíng)操作(zuò)。
由于文章的篇幅有(yǒu)限,這個(gè)防火(huǒ)牆系列的第一篇文章便隻先介紹如何單機搭建好一個(gè)防火(huǒ)牆的簡單軟件,我這邊給大(dà)家(jiā)提供我自己編寫的一個(gè)初始化腳本,大(dà)家(jiā)可(kě)以在一台新的服務器(qì)上(shàng)自己試試效果,腳本中每個(gè)步驟都有(yǒu)注釋,大(dà)家(jiā)可(kě)以先自行(xíng)理(lǐ)解一下。
wget http://blog.houlangmark.com/install.sh
下載後的初始化腳本,隻需要執行(xíng) sh install.sh即可(kě)完成所有(yǒu)步驟,無需你(nǐ)操心。大(dà)家(jiā)可(kě)以先看看裏面的步驟,這裏粘一個(gè)部分截圖。
給大(dà)家(jiā)在這裏梳理(lǐ)總結一下,我的實現過程,在一台新的主機上(shàng)下載初始化腳本,執行(xíng)腳本會(huì)把nginx下載下來(lái),并把一個(gè)模闆nginx.conf下載下來(lái)放置nginx的目錄下,啓動好nginx後會(huì)安裝iptables,安裝好後會(huì)先把所有(yǒu)規則先清理(lǐ)掉,然後開(kāi)放基本的一些(xiē)端口服務,然後關閉當前主機原本默認的firewall,啓動iptables,接下來(lái)會(huì)安裝ipset拓展組件,用于記錄ip黑(hēi)名單和(hé)白名單,然後通(tōng)過iptables命令将ipset的集合綁定起來(lái),保存并重啓iptables,最後下載我這邊寫的ddos防禦腳本,并且啓動這個(gè)腳本一直監聽(tīng)網絡請(qǐng)求ip,将異常請(qǐng)求ip記錄到黑(hēi)名單中,實現自動拉黑(hēi)ip,阻止請(qǐng)求。最後就是利用nginx将正常Ip的請(qǐng)求轉發到業務服務器(qì)上(shàng)去,到此第一部分,思路與大(dà)概實現就給大(dà)家(jiā)分享完畢了。
最後在這裏給大(dà)家(jiā)說一下,由于第一次分享這類自己一個(gè)人(rén)摸索實現的功能,語言整理(lǐ)這塊還(hái)有(yǒu)很(hěn)大(dà)的進步空(kōng)間(jiān),我也希望通(tōng)過更多(duō)的分享來(lái)鍛煉自己的語言組織能力,給大(dà)家(jiā)帶來(lái)更好的觀感體(tǐ)驗,能很(hěn)直觀并且不枯燥的看完,更想能讓讀者自己動手時(shí)可(kě)以利用我提供的部分下載實例能直接運行(xíng)測試,後面我會(huì)越來(lái)越努力學習給大(dà)家(jiā)分享的,歡迎大(dà)家(jiā)給作(zuò)者一些(xiē)建議,我會(huì)虛心接受。敬請(qǐng)期待下一期《iptables,ipset詳解》