TCP的三次握手與四次揮手

TCP的三次握手與四次揮手

關於題目的這個問題,在網絡中有着非常重要的地位。因爲客戶端與服務端之間通過TCP協議,爲了進行數據的傳輸會進行一系列的操作,這中間的操作就是TCP的三次握手與四次揮手。

重新回顧TCP協議

TCP協議稱爲數據傳輸協議,是可靠傳輸,面向連接的,並且面向字節流的。

面向連接:通信之前先建立連接,確保雙方在線。

可靠傳輸:在網絡正常的情況下,數據不會丟失。

面向字節流:傳輸靈活,但是TCP的傳輸存在粘包問題,沒有明顯的數據約定。

TCP協議的傳輸過程

先通過總體圖來總的給一個傳輸過程印象。

網絡-三次握手-四次揮手

三次握手

我們已客戶端先發送連接請求爲前提進行連接。

SYN:同步序列編號(Synchronize Sequence Numbers),是TCP/IP建立連接時使用的握手信號

ACK:確認字符,在數據通信中,接收站發給發送站的一種傳輸類控制字符。表示發來的數據已確認接收無誤。

首先客戶端進行套接字編程操作創建套接字,再進行綁定地址操作,然後開始向服務端進行連接請求。

與此同時,服務端也創建套接字,也進行綁定地址,然後開始進行監聽套接字操作。

握手過程:

客戶端先向服務端發送一個SYN消息,此時客戶端處於SYN_SEND狀態。服務端此時接收到了該消息,這時服務端會發送SYN+ACK,進行消息回覆確認。回覆完之後,此時服務端處於SYN_RCVD狀態,等待客戶端進行最後一次確認。這個時候客戶端接收到了SYN+ACK包之後,再給服務端發送一個ACK包,此時客戶端將處於ESTABLISH狀態(就緒狀態),代表了客戶端此時可以進行收發數據。服務端接受了ACK包之後,此時連接建立成功,服務端也處於ESTABLISH狀態,也可以進行收發消息了。

此時客戶端與服務端的連接建立完成。它們之間可以進行數據的發送與接收…

但是人有悲歡離合,月有陰晴圓缺,網絡遲早斷開連接!!!

發送了一段時間後,它們之間要斷開連接…

四次揮手

我們再次已客戶端先發送斷開請求爲前提。

FIN:表示斷開連接

RST:表示復位,用來異常的關閉連接

揮手過程:

客戶端發送完數據之後,關閉了網絡套接字,此時客戶端向服務端發送了一個FIN包,發送完畢之後,客戶端處於FIN_WAIT_1狀態。服務端接收到了之後,處於CLOSE_WAIT狀態。服務端這時會向客戶端發送一個ACK包,發送完了進入LAST_ACK狀態進行最後一次等待確認狀態,此時伴隨着close()關閉套接字。因爲服務端還要再確認一次是否斷開連接,此時服務端向客戶端再發送一個FIN包。客戶端接收到了該FIN包之後,再給服務端發送ACK包,代表確認關閉,執行完該操作之後,客戶端並沒有直接CLOSED並且回收資源,此時客戶端處於**TIME_WAIT狀態,等待時間爲兩個MSL(最大報文段生存週期,一個大約30s)。**服務端此時接收到了該ACK包,進入了CLOSED狀態並且回收資源。客戶端等待了兩個MSL時間之後,也進入了CLOSED狀態並且回收資源。

這時客戶端與服務端之間斷開連接。

TIME_WAIT狀態:

在斷開的過程中有一個TIME_WAIT狀態,爲什麼會有該狀態?

假設沒有TIME_WAIT會有什麼情況:最後一個ACK丟失,被動關閉方重發FIN包,沒有等待直接關閉。若直接啓動的客戶端此時使用了相同的端口信息,有可能收到FIN包,此時就對新連接造成影響。

若新啓動客戶端使用了相同的端口信息,向服務器發送了SYN請求,但是服務端因爲沒有受到最後一個ACK包而一直處於LAST_ACK狀態,受到SYN後判定狀態錯誤,回覆RST報文重置連接,也對新連接造成了影響。

所以主動關閉方發送最後一個ACK之後需要等待一段時間:兩個MSL時間(最大報文等待時間)

1、處理ACK丟失,導致對端重發FIN包

2、等待雙方延遲的報文全部消失在網絡中,不會對後續連接造成影響。

常見問題

爲什麼握手是三次,揮手是四次?

在握手過程中,爲了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤。

當客戶端發出的第一個連接請求報文段並沒有丟失,而是在網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達服務端。本來這是一個早已失效的報文段。但是服務端收到此失效的連接請求報文段之後,就誤認爲是客戶端再次發出的一個新的連接請求。於是就向客戶端發出確認報文段,同意建立連接。假設我們不採用“三次握手”,那麼服務端發出確認,新的連接就建立成功了。由於現在client並沒有發出建立連接的請求,因此不會理睬服務端的確認,也不會像服務端發送數據。但是服務端卻以爲新的建立已經完成,一直等待消息發送到來。這樣,服務端的數據很多數據被白白浪費了。採用“三次握手”可以有效的避免這種情況。客戶端不會向服務端的確認發出確認,服務端由於收不到確認,就認爲客戶端沒有建立連接。

所以,三次握手也可以看作爲了防止服務端的一直等待而浪費資源。

揮手過程是一個相互的確認過程,首先我們都已知TCP的連接是全雙工的,既可以發送也可以接收。那麼當雙方都確認自己沒有數據可以發送,並且都互相表示雙方知道對方沒有數據之後,那麼連接也就斷開了。

假設揮手在第三次結束。客戶端發送了一個FIN就打算斷開連接。那麼客戶端又如何知道服務端想要斷開連接?有可能客戶端剛發送完了數據,但是服務端並沒有。服務端打算髮完了剩下的數據在跟客戶端”拜拜“。

此時就出現了矛盾。所以揮手有第四次來進行雙發的確認。確認雙方的工作都做完了。

SYN泛洪攻擊

SYN泛洪攻擊利用TCP三次握手協議的缺陷,向目標主機發送大量的僞造源地址的SYN連接請求,使得被攻擊方資源耗盡,從而不能夠爲正常用戶提供服務。

在TCP協議中被稱爲三次握手(Three-way Handshake)的連接過程中,如果一個用戶向服務器發送了SYN報文,服務器又發出 SYN+ACK 應答報文後未收到客戶端的 ACK 報文,這種情況下服務器端會再次發送SYN+ACK給客戶端,並等待一段時間後丟棄這個未完成的連接,這段時間的長度稱爲SYN Timeout,一般來說這個時間是分鐘的數量級。

SYN 泛洪攻擊所做的就是利用這個SYN Timeout和TCP/IP協議族中的另一個漏洞: 報文傳輸過程中對報文的源 IP 地址完全信任進行攻擊。SYN 泛洪攻擊通過發送大量的僞造 TCP 鏈接報文而造成大量的 TCP 半連接,服務器端將爲了維護這樣一個龐大的半連接列表而消耗非常多的資源。這樣服務器端將忙於處理攻擊者僞造的TCP連接請求而無法處理正常連接請求,甚至會導致堆棧的溢出崩潰

造成SYN洪泛攻擊最主要的原因是TCP/IP協議的脆弱性。TCP/IP是一個開放的協議平臺,它將越來越多的網絡連接在一起,它基於的對象是可信用戶羣,所以缺少一些必要的安全機制,帶來很大的安全威脅。例如常見的IP欺騙、TCP連接的建立、ICMP數據包的發送都存在巨大的安全隱患,給SYN洪泛攻擊帶來可乘之機。

防範方法

1、縮短SYN Timeout時間,短時間內收不到客戶端的ACK回覆報文直接丟棄,防止被攻擊

2、設置SYN cookie,給每一個請求連接的IP地址分配一個cookie,如果短時間內連續受到某個IP的重複SYN文,認定是受到了攻擊,以後從這個IP地址來的包會被丟棄。

3、設置SYN可疑隊列

4、使用防火牆

推薦博客鏈接:https://blog.csdn.net/justenjoyitpy/article/details/78151239

若服務端出現了大量的TIME_WAIT連接,爲什麼?如何解決?

這種情況比較常見,一些爬蟲服務器或者WEB服務器(如果網管在安裝的時候沒有做內核參數優化的話)上經常會遇到這個問題,在四次的揮手過程中我們已經可以瞭解TIME_WAIT狀態的出現情況。

1、防止上一次連接的包迷路後重新出現,影響新連接,所以等待被動方發來的FIN包

2、可靠的關閉TCP連接。在主動方發送的最後一個ACK,有可能丟失,這時被動方會重新發FIN包,如果這時主動方處於CLOSED狀態,就會響應RST而不是ACK。所以主動方要處於TIME_WAIT,而不能是CLOSED。

解決的方案就是讓服務器能夠快速回收和重用那些TIME_WAIT資源

這裏推薦一篇博客鏈接:https://www.cnblogs.com/whx7762/p/9413787.html

下面是一篇文章中提到的/etc/sysctl.conf文件的修改

//對於一個新建連接,內核要發送多少個 SYN 連接請求才決定放棄,不應該大於255,默認值是5,對應於180秒左右時間
net.ipv4.tcp_syn_retries=2
net.ipv4.tcp_synack_retries=2
//表示當keepalive起用的時候,TCP發送keepalive消息的頻度。缺省是2小時,改爲300秒
net.ipv4.tcp_keepalive_time=1200
net.ipv4.tcp_orphan_retries=3
//表示如果套接字由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間
net.ipv4.tcp_fin_timeout=30
//表示SYN隊列的長度,默認爲1024,加大隊列長度爲8192,可以容納更多等待連接的網絡連接數
net.ipv4.tcp_max_syn_backlog = 4096
//表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少量SYN攻擊,默認爲0,表示關閉 
net.ipv4.tcp_syncookies = 1
//表示開啓重用。允許將TIME-WAIT sockets重新用於新的TCP連接,默認爲0,表示關閉 
net.ipv4.tcp_tw_reuse = 1
//表示開啓TCP連接中TIME-WAIT sockets的快速回收,默認爲0,表示關 
net.ipv4.tcp_tw_recycle = 1
//減少超時前的探測次數
net.ipv4.tcp_keepalive_probes=5
//優化網絡設備接收隊列
net.core.netdev_max_backlog=3000

修改完之後執行/sbin/sysctl -p讓參數生效。

net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle的開啓都是爲了回收處於TIME_WAIT狀態的資源。

net.ipv4.tcp_fin_timeout這個時間可以減少在異常情況下服務器從FIN-WAIT-2轉到TIME_WAIT的時間。

net.ipv4.tcp_keepalive_*一系列參數,是用來設置服務器檢測連接存活的相關配置。

在TCP的傳輸過程中最重要的就是三次握手與四次揮手,但是TCP的傳輸過程是面向可信任羣體的,安全性相對較弱,會受到一些攻擊,不過有方法可以解決。都是根據傳輸過程進行範圍內的防禦措施。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章