概述
總結一下TCP中3次握手過程,以及其原生的缺陷 引起的SYN Flood的介紹
【1】TCP三次握手
【2】SYN Flood
【3】TCP4次握手
1、TCP連接建立——三次握手
幾個概念:
【1】seq:序號,占4個字節,范圍[0,4284967296],由于TCP是面向字節流的,在一個1個TCP連接中傳送字節流中國的每一個字節都按照順序編號,此外序號是循環使用的
【2】ACK: 僅當ACK=1時確認字段才有效,當ACK=0時確認字段無效,并且TCP規定,在連接建立后所有的傳送報文段都必須要把ACK置為1
【3】SYN:同步序列號,用來發起一個連接。當SYN=1而ACK=0時表明這是一個請求報文段;若對方同意連接,則響應報文中SYN=1,ACK=1
【4】FIN :用來釋放一個連接,當FIN=1表示此報文段的發送方已經發送完畢。并要求釋放鏈接
1.1、3次握手過程
服務端的TCP進程先創建傳輸控制塊TCB,準備接受客戶端進程的連接請求,然后服務端進程處于LISTEN狀態,等待客戶端的連接請求,如有,則作出響應。 1、客戶端的TCP進程也首先創建傳輸控制模塊TCB,然后向服務端發出連接請求報文段,該報文段首部中的SYN=1,ACK=0,同時選擇一個初始序號 seq=i。TCP規定,SYN=1的報文段不能攜帶數據,但要消耗掉一個序號。這時,TCP客戶進程進入SYN—SENT(同步已發送)狀態,這是 TCP連接的第一次握手。 2、服務端收到客戶端發來的請求報文后,如果同意建立連接,則向客戶端發送確認。確認報文中的SYN=1,ACK=1,確認號ack=i+1,同時為自己 選擇一個初始序號seq=j。同樣該報文段也是SYN=1的報文段,不能攜帶數據,但同樣要消耗掉一個序號。這時,TCP服務端進入SYN—RCVD(同 步收到)狀態,這是TCP連接的第二次握手。 3、TCP客戶端進程收到服務端進程的確認后,還要向服務端給出確認。確認報文段的ACK=1,確認號ack=j+1,而自己的序號為seq=i+1。 TCP的標準規定,ACK報文段可以攜帶數據,但如果不攜帶數據則不消耗序號,因此,如果不攜帶數據,則下一個報文段的序號仍為seq=i+1。這 時,TCP連接已經建立,客戶端進入ESTABLISHED(已建立連接)狀態。這是TCP連接的第三次握手,可以看出第三次握手客戶端已經可以發送攜帶 數據的報文段了。 當服務端收到確認后,也進入ESTABLISHED(已建立連接)狀態。
1.2、關于第三次握手的解釋
根據一般的思路,我們可能會覺得只要兩次握手就可以了,第三步確認看似是多余的。那么 TCP 協議為什么還要費力不討好的加上這一次握手呢?
這是因為在網絡請求中,我們應該時刻記住:“網絡是不可靠的,數據包是可能丟失的”。假設沒有第三次確認,客戶端向服務端發送了 SYN,請求建立連接。由于延遲,服務端沒有及時收到這個包。于是客戶端重新發送一個 SYN 包。回憶一下介紹 TCP 首部時提到的序列號,這兩個包的序列號顯然是相同的。
假設服務端接收到了第二個 SYN 包,建立了通信,一段時間后通信結束,連接被關閉。這時候最初被發送的 SYN 包剛剛抵達服務端,服務端又會發送一次 ACK 確認。由于兩次握手就建立了連接,此時的服務端就會建立一個新的連接,然而客戶端覺得自己并沒有請求建立連接,所以就不會向服務端發送數據。從而導致服務端建立了一個空的連接,白白浪費資源。
在三次握手的情況下,服務端直到收到客戶端的應答后才會建立連接。因此在上述情況下,客戶端會接受到一個相同的 ACK 包,這時候它會拋棄這個數據包,不會和服務端進行第三次握手,因此避免了服務端建立空的連接。
ACK 確認包丟失怎么辦
三次握手其實解決了第二步的數據包丟失問題。那么第三步的 ACK 確認丟失后,TCP 協議是如何處理的呢?
按照 TCP 協議處理丟包的一般方法,服務端會重新向客戶端發送數據包,直至收到 ACK 確認為止。但實際上這種做法有可能遭到 SYN 泛洪攻擊。所謂的泛洪攻擊,是指發送方偽造多個 IP 地址,模擬三次握手的過程。當服務器返回 ACK 后,攻擊方故意不確認,從而使得服務器不斷重發 ACK。由于服務器長時間處于半連接狀態,最后消耗過多的 CPU 和內存資源導致死機。
正確處理方法是服務端發送 RST 報文,進入 CLOSE 狀態。這個 RST 數據包的 TCP 首部中,控制位中的 RST 位被設置為 1。這表示連接信息全部被初始化,原有的 TCP 通信不能繼續進行。客戶端如果還想重新建立 TCP 連接,就必須重新開始第一次握手。
2、 缺陷引起的SYN Flood
2.1、SYN Flood 攻擊
SYN- Flood攻擊是當前網絡上最為常見的DDoS攻擊,也是最為經典的拒絕服務攻擊,它就是利用了TCP協議實現上的一個缺陷,通過向網絡服務所在端口發送 大量 的偽造源地址的攻擊報文,就可能造成目標服務器中的半開連接隊列被占滿,從而阻止其他合法用戶進行訪問。這種攻擊早在1996年就被發現,但至今仍然顯示 出強大的生命力。很多操作系統,甚至防火墻、路由器都無法有效地防御這種攻擊,而且由于它可以方便地偽造源地址,追查起來非常困難。它的數據包特征通常 是,源發送了大量的SYN包,并且缺少三次握手的最后一步握手ACK回復。
原理:攻擊者首先偽造地址對 服務器發起SYN請求,服務器回應(SYN+ACK)包,而真實的IP會認為,我沒有發送請求,不作回應。服務 器沒有收到回應,這樣的話,服務器不知 道(SYN+ACK)是否發送成功,默認情況下會重試5次(tcp_syn_retries)。這樣的話,對于服務器的內存,帶寬都有很大的消耗。攻擊者 如果處于公網,可以偽造IP的話,對于服務器就很難根據IP來判斷攻擊者,給防護帶來很大的困難。
2.2、SYN Flood 防護措施
主要通過以下3種方式
1. 無效連接監視釋放
這種方法不停的監視系統中半開連接和不活動連接,當達到一定閾值時拆除這些連接,釋放系統資源。這種絕對公平的方法往往也會將正常的連接的請求也會被釋放掉,”傷敵一千,自損八百“
2. 延緩TCB分配方法
SYN Flood關鍵是利用了,SYN數據報文一到,系統立即分配TCB資源,從而占用了系統資源,因此有倆種技術來解決這一問題
Syn Cache技術
這種技術在收到SYN時不急著去分配TCB,而是先回應一個ACK報文,并在一個專用的HASH表中(Cache)中保存這種半開連接,直到收到正確的ACK報文再去分配TCB
Syn Cookie技術
Syn Cookie技術則完全不使用任何存儲資源,它使用一種特殊的算法生成Sequence Number,這種算法考慮到了對方的IP、端口、己方IP、端口的固定信息,以及對方無法知道而己方比較固定的一些信息,如MSS、時間等,在收到對方 的ACK報文后,重新計算一遍,看其是否與對方回應報文中的(Sequence Number-1)相同,從而決定是否分配TCB資源
3. 使用SYN Proxy防火墻
原理:對試圖穿越的SYN請求進行驗證之后才放行
3、四次握手關閉連接
這個過程可以用以下四句形象的對話表示:
(客戶端):我要關閉連接了。
(服務端):你那邊的連接可以關閉了。
(服務端):我這邊也要關閉連接了。
(客戶端):你那邊的連接可以關閉了。
由于TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的數據發送任務后就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數據流動,一個TCP連接在收到一個FIN后仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
具體過程解釋如下:
CP連接的拆除需要發送四個包,因此稱為四次握手(four-way handshake)。客戶端或服務器均可主動發起揮手動作,在socket編程中,任何一方執行close()操作即可產生揮手操作。
(1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送。
(2)服務器B收到這個FIN,它發回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將占用一個序號。
(3)服務器B關閉與客戶端A的連接,發送一個FIN給客戶端A。
(4)客戶端A發回ACK報文確認,并將確認序號設置為收到序號加1。
關閉連接的最后一個 ACK 丟失怎么辦
實際上,在第三步中,客戶端收到 FIN 包時,它會設置一個計時器,等待相當長的一段時間。如果客戶端返回的 ACK 丟失,那么服務端還會重發 FIN 并重置計時器。假設在計時器失效前服務器重發的 FIN 包沒有到達客戶端,客戶端就會進入 CLOSE 狀態,從而導致服務端永遠無法收到 ACK 確認,也就無法關閉連接。
示意圖如下: