在我的上一篇文章談到了如何使用tcpdump和wireshark,并帶您了解了幾個用例。今天我們來看看另一個常見的問題,如何緩解 DDoS(分布式拒絕服務)導致的性能下降。
什么是 DDoS?
DDoS 的前身是 DoS(Denial of Service),即拒絕服務攻擊,是指利用大量合理請求占用過多目標資源,使目標服務無法響應正常的請求.
DDoS(Distributed Denial of Service)采用基于 DoS 的分布式架構,利用多臺主機同時攻擊目標主機。這樣,即使目標服務部署了網絡防御設備,仍然無法應對大量的網絡請求。
從攻擊原理來看,DDoS 可分為以下幾種。
用盡帶寬:無論是服務器還是路由器、交換機等網絡設備,帶寬都有一個固定的上限。當帶寬耗盡時,會出現網絡擁塞,無法傳輸其他正常的網絡數據包。
耗盡系統資源:網絡服務的正常運行需要一定的系統資源,如CPU、內存等物理資源,以及連接表等軟件資源。一旦資源耗盡,系統將無法處理其他正常的網絡連接。
耗盡應用資源:應用程序的運行通常還需要與其他資源或系統進行交互。如果應用程序一直忙于處理無效請求,也會導致正常請求的處理速度變慢,甚至沒有響應。
無論哪種類型的 DDoS,危害都是巨大的。那么,如何發現系統遭受了 DDoS 攻擊,如何應對這種攻擊呢?讓我帶您了解一個現實生活中的用例。
案例準備
您需要遵循:
3 臺 Linux 主機:應用程序、攻擊者、客戶端
預安裝docker、sar、hping3、tcpdump、curl。
應用服務器
讓我們在應用主機上啟動一個簡單的nginx服務:
[root@app~]#dockerrun-itd--name=nginx--network=hostnginx a8b3685d5eef0ffa2dead081b88d50d777db04bedbdb77ba886ca89b4bb690d2 [root@app~]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES a8b3685d5eefnginx"/docker-entrypoint.…"24secondsagoUp21secondsnginx
客戶端
然后,在客戶端主機中,使用curl訪問 Nginx 正在監聽的端口,并確認 Nginx 已經正常啟動:
[root@client~]#curl-s-w'Httpcode:%{http_code} Totaltime:%{time_total}s '-o/dev/nullhttp://172.31.88.139 Httpcode:200 Totaltime:0.002437s
從這里可以看出,正常情況下,我們訪問 Nginx 只需要 2ms(0.002s)。
攻擊者
現在,讓我們從攻擊者主機那里運行hping3命令來模擬 Dos 攻擊:
#-Smeanssetsyn,-pmeansport80 #-iu10sendapacketframeevery10m-seconds $hping3-S-p80-iu10--flood192.168.0.30 HPING172.31.88.139(eth0172.31.88.139):Sset,40headers+0databytes hpinginfloodmode,noreplieswillbeshown
緩解攻擊
現在讓我們回到客戶端主機,再次嘗試curl命令:
[root@client~]#curl-s-w'Httpcode:%{http_code} Totaltime:%{time_total}s '-o/dev/nullhttp://172.31.88.139 Httpcode:000 Totaltime:10.001s curl:(28)Connectiontimedoutafter10000milliseconds
這次普通客戶端的連接超時,其并沒有收到 Nginx 服務的響應。
這里發生了什么事呢?讓我們回到主機應用程序,并檢查當前的網絡狀態:
[root@app~]#sar-nDEV1 0849IFACErxpck/stxpck/srxkB/stxkB/srxcmp/stxcmp/srxmcst/s%ifutil 0850docker00.000.000.000.000.000.000.000.00 0850eth022274.00629.001174.6437.780.000.000.000.02 0850lo0.000.000.000.000.000.000.000.00
從這次sar的輸出可以看出,網絡接收到的 PPS 已經達到 2 萬多,但是 BPS 只有 1174kB。因此,可以計算每個包的大小只有54B()。
包大小不算大,但這是個什么樣的包呢?讓我們使用tcpdump來捕獲:
[root@app~]#tcpdump-ieth0-ntcpport80 0948.287047IP172.31.82.28.27095>172.31.88.139:Flags[S],seq1288268370,win512,length0 0948.287050IP172.31.82.28.27131>172.31.88.139:Flags[S],seq2084255254,win512,length0 0948.287052IP172.31.82.28.27116>172.31.88.139:Flags[S],seq677393791,win512,length0 0948.287055IP172.31.82.28.27141>172.31.88.139:Flags[S],seq1276451587,win512,length0 0948.287068IP172.31.82.28.27154>172.31.88.139:Flags[S],seq1851495339,win512,length0 ...
在該輸出中,Flags [S]表示這是一個 SYN 數據包。而大量的 SYN 數據包表明這是一次 SYN Flood 攻擊。如果我們用wireshark來觀察,可以更加直觀地看到 SYN Flood 的過程:
事實上,SYN Flood 是互聯網上最經典的 DDoS 攻擊。從上圖也可以看出它的原理:
客戶端構造大量 SYN 包,請求建立 TCP 連接;
服務器收到包后,會向源 IP 發送一個 SYN+ACK 包,并等待三次握手的最后一個 ACK 包,直到鏈接超時。
這種等待狀態的 TCP 連接通常也稱為半開連接(Half-Open Connection)。由于連接表(Connection Table)的大小是有限的,而大量的半開連接會導致連接表快速填滿,從而無法建立新的 TCP 連接。
從下面的 TCP 狀態圖可以看到,此時服務器端的 TCP 連接會處于SYN_RECEIVED狀態:
我們可以使用netstat來查看所有連接的狀態,但需要注意的是SYN_REVEIVED的狀態通常縮寫為SYN_RECV。
[root@app~]#netstat-n-p|grepSYN_REC tcp00172.31.88.139:80172.31.82.28:12503SYN_RECV- tcp00172.31.88.139:80172.31.82.28:13502SYN_RECV- tcp00172.31.88.139:80172.31.82.28:15256SYN_RECV- tcp00172.31.88.139:80172.31.82.28:18117SYN_RECV- ...
從結果中可以發現,存在大量的SYN_RECV狀態的連接,源 IP 地址為172.31.82.28。現在,讓我們統計一下正處于SYN_RECV狀態的連接數:
[root@app~]#netstat-n-p|grepSYN_REC|wc-l 193
找出源 IP 后,只需丟棄相關數據包即可解決 SYN 攻擊的問題。此時,iptables可以幫你完成這個任務:(注意:Serban 在評論中建議“在這種情況下,DROP比可能REJECT更好”)
[root@app~]#iptables-IINPUT-s172.31.82.28-ptcp-jREJECT
執行上述命令后,讓我們再次從客戶端主機嘗試curl:
$curl-w'Httpcode:%{http_code} Totaltime:%{time_total}s '-o/dev/null--connect-timeout10http://172.31.88.139 Httpcode:200 Totaltime:1.572171s
但一般來說,SYN Flood 攻擊中的源 IP 是不固定的(例如,您可以通過將--rand-source選項添加到hping3命令來隨機化源 IP)。此時,剛才的方法并不適用。
幸運的是,我們還有許多其他方法可以達到類似的目的。例如,我們可以通過兩種方式限制同步數據包的速率:
#Limitthenumberofsynconcurrencyto1persecond $iptables-AINPUT-ptcp--syn-mlimit--limit1/s-jACCEPT #LimitthenumberofnewlyestablishedconnectionsforasingleIPin60secondsto10 $iptables-IINPUT-ptcp--dport80--syn-mrecent--nameSYN_FLOOD--update--seconds60--hitcount10-jREJECT
到目前為止,我們已經初步限制了 SYN Flood 攻擊。但這還不夠,因為我們的案例只是單一的攻擊源。
如果多臺機器同時發送 SYN Flood,則該方法可能直接失效。因為您可能無法通過 SSH 連接到機器(SSH 也是基于 TCP 的),更不用說執行上面的那些排查命令了。
TCP 優化
為了緩解多臺機器的 SYN Flood 攻擊,我們可以將半開連接容量從默認的 256 增加到 1024:
$sysctlnet.ipv4.tcp_max_syn_backlog net.ipv4.tcp_max_syn_backlog=256 $sysctl-wnet.ipv4.tcp_max_syn_backlog=1024net.ipv4.tcp_max_syn_backlog=1024
另外,每當連接狀態為 SYN_RECV 的連接時,如果連接失敗,內核會自動重試,默認重試次數為 5 次。您可以通過執行以下命令將其減少到 1 次:
$sysctl-wnet.ipv4.tcp_synack_retries=1 net.ipv4.tcp_synack_retries=1
此外,TCP SYN Cookies 也是一種特殊的防御 SYN Flood 攻擊的機制。SYN Cookies 根據連接信息(包括源地址、源端口、目的地址、目的端口等)和加密種子(如系統啟動時間)計算哈希值(SHA1)。該哈希值稱為 cookie。啟用 SYN Cookies 后,無需再保持半開連接狀態,同時半開連接的數量也將沒有限制。
$sysctl-wnet.ipv4.tcp_syncookies=1 net.ipv4.tcp_syncookies=1
需要注意的是,上面sysctl命令所修改的配置是臨時的,重啟后將會丟失。您可以通過將它們添加到/etc/sysctl.conf文件中使其持久化。例如:
$cat/etc/sysctl.conf net.ipv4.tcp_syncookies=1 net.ipv4.tcp_synack_retries=1 net.ipv4.tcp_max_syn_backlog=1024 $sysctl-p
結論
今天,我們談到了在分布式拒絕服務 (DDoS) 情況下的緩解措施。DDoS 利用大量偽造請求,使目標服務消耗大量資源來處理這些無效的請求,進而無法正常響應正常用戶請求。
由于 DDoS 分布的流量大和難以追蹤等特點,目前沒有辦法完全防御 DDoS 帶來的問題,因此只能緩解其造成的影響。
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11294瀏覽量
209344 -
DDoS
+關注
關注
3文章
171瀏覽量
23064 -
服務器
+關注
關注
12文章
9124瀏覽量
85332 -
路由器
+關注
關注
22文章
3728瀏覽量
113706
原文標題:如何在 Linux 上模擬和緩解 DDoS 攻擊
文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論