TCP連接三次握手和四次斷開分析

CP/IP 協議簇中TCP提供可靠的服務連接,採用三次握手建立一個連接,如下圖所示:

wKioL1R6ejDB0xuxAAAdByATNBk639.gif

在客戶端A和服務端B之間建立一條tcp連接,主要經過一下三步:

          一  客戶端 A發起建立連接的請求,向服務端B發一個SYN(seq=x)包。

          二  服務端B收到SYN(seq=x)包後,必須對客戶端發來的SYN(seq=x)包進行確認,向客戶端A發送一個ACK(ack=x+1)包,同時自己也要發一個SYN(seq=y)包,這樣等於服務端B就發了一個SYN+ACK的包。

          三   客戶端A收到服務端B發的SYN+ACK的包之後,必須向服務端B發送一個確認包ACK(ack=y+1),至此發包完畢,客戶端進入鏈接狀態,三次握手完畢。 

          在三次握手中客戶端和服務端的狀態變化如下:

                                        客戶端A                                    服務端B

           A未發請求前                                                            LISTEN       

                               (在A未發請求前,B監聽某個特定的服務端口)

          A發送SYN             SYN_SENT                                   SYN_RECV   

                                (A發送SYN後,B成功收到SYN後,狀態變爲 SYN_RECV,並且給A 發送ACK+SYN包)      

          A發送ACK            ESTABLISHED                             ESTABLISHED

                                (A收到ACK+SYN後,給B發送ACK,B收到A發送的ACK後變爲ESTABLISHED狀態)


         下面說說會影響tcp建立連接三次握手的一些因素:

        1  /proc/sys/net/ipv4/tcp_max_syn_backlog    (1024)--->8192

            該變量控制每個監聽端口接收的客戶端發送的SYN隊列的長度,輸入的SYN報文段連接請求需要排隊,直到本地服務端接收,如果連接數多於默認值,則新來的 連接請求會被丟棄,在服務端會維護一個未連接隊列,該隊列爲每個客戶端發送的SYN包開設一個條目,說明已經收到SYN包,並且向客戶端發出 SYN+ACK包,等待客戶端的確認SYN包,這時服務端出於SYN_RECV狀態,如果tcp_max_syn_backlog過小,一直收不到客戶端最後發來的SYN確認包,服務端就會一直出於SYN_RECV狀態,查看netstat -an的時候如果SYN_RECV過多有可能就是tcp_max_syn_backlog過小。增大爲8192,可以容納更多的等待連接的網絡連接數

        2  /proc/sys/net/ipv4/tcp_synack_retries    (5)

           該變量控制內核向某個輸入的SYN/ACK段重新發送響應的次數,降低取值可以更早的檢測到客戶端連接失敗的嘗試。

        3  /proc/sys/net/ipv4/tcp_retries2   (15)

           該變量控制內核向已經建立連接的遠程主機重新發送數據的次數,降低取值可以更早的檢測到與遠程主機的連接失效,從而可以快速釋放該鏈接的資源。

         4  /proc/sys/net/ipv4/ip_local_port_range   (32768   61000)

            該變量控制系統上可用的臨時端口的範圍。端口是ip協議對各個socket加以區分的地址的邏輯抽象。

        5  /proc/sys/net/ipv4/tcp_retries1   (3)

            該變量設置放棄迴應一個tcp連接請求前,需要進行多少次重試。

        6  /proc/sys/net/ipv4/tcp_syncookies  (0 關閉  1 打開)

            該參數主要用來防止SYN FLOOD***。SYN Cookie是對TCP服務器端的三次握手協議作一些修改,專門用來防範SYN Flood***的一種手段。它的原理是,在TCP服務器收到TCP SYN包並返回TCP SYN+ACK包時,不分配一個專門的數據區,而是根據這個SYN包計算出一個cookie值。在收到TCP ACK包時,TCP服務器在根據那個cookie值檢查這個TCP ACK包的合法性。如果合法,再分配專門的數據區進行處理未來的TCP連接。

             SYN Flood***是一種典型的拒絕服務型(Denial of Service)***。所謂拒絕服務型***就是通過進行***,使受害主機或網絡不能夠良好的提供服務,從而間接達到***的目的。

            SYN Flood***利用的是IPv4中TCP協議的三次握手(Three-Way Handshake)過程進行的***。大家知道協議規定,如果一端想向另一端發起TCP連接,它需要首先發送TCP SYN 包到對方,對方收到後發送一個TCP SYN+ACK包回來,發起方再發送TCP ACK包回去,這樣三次握手就結束了。我們把TCP連接的發起方叫作"TCP客戶機(TCP Client)",TCP連接的接收方叫作"TCP服務器(TCP Server)"。值得注意的是在TCP服務器收到TCP SYN request包時,在發送TCP SYN+ACK包回TCP客戶機前,TCP服務器要先分配好一個數據區專門服務於這個即將形成的TCP連接。一般把收到SYN包而還未收到ACK包時的連 接狀態成爲半開連接(Half-open Connection)。

            在最常見的SYN Flood***中,***者在短時間內發送大量的TCP SYN包給受害者,這時***者是TCP客戶機,受害者是TCP服務器。根據上面的描述,受害者會爲每個TCP SYN包分配一個特定的數據區,只要這些SYN包具有不同的源地址(這一點對於***者來說是很容易僞造的)。這將給TCP服務器系統造成很大的系統負擔, 最終導致系統不能正常工作。

           TCP三次握手建立連接後,並沒有規定必須立即進行數據交換,連接可以永久保持空閒狀態,如果客戶端發生故障,則將無法被其他主機檢測到,而tcp的連接保持機制允許服務端對連接加以監視並在合理的時間內獲知這種故障,影響參數有下:

         1  /proc/sys/net/ipv4/tcp_keepalive_time   (7200)

             如果在該參數指定的秒數內連接始終處於空閒狀態,則內核向客戶端發起對該主機的探測.tcp發送keepalive消息的頻度.默認是2小時.就改爲10分鐘

         2  /proc/sys/net/ipv4/tcp_keepalive_intvl       (75)

            該參數以秒爲單位,規定內核向遠程主機發送探測指針的時間間隔

         3  /proc/sys/net/ipv4/tcp_keepalive_probes     (9)

            該參數規定內核爲了檢測遠程主機的存活而發送的探測指針的數量,如果探測指針的數量已經使用完畢仍舊沒有得到客戶端的響應,即斷定客戶端不可達,關閉與該客戶端的連接,釋放相關資源。

          以上三個參數 7500+9*75 導致一條失效的連接在經過2小時11分鐘後才被丟棄,降低上述數值可以減少失效連接所佔資源的時間

 

       TCP斷開連接的四次握手,過程如下:

wKioL1R6elrSbQLXAAKicBtIWb8126.jpg

初始時客戶端和服務端都處於ESTABLISHED狀態。

        1   客戶端先發送一個FIN包,告訴服務端他要斷開連接。

        2   服務端收到FIN包後,給客戶端發送一個確認包ACK,告訴應用程序他要關閉連接了。

        3   當應用程序準備好斷開後,服務端給客戶端發送FIN包。

         4  客戶端收到服務端發來的FIN包後,給服務端發送ACK確認包。服務端收到之後就關閉連接。


          四次握手斷開連接狀態分析:

          1   當服務端收到客戶端發來的FIN包後,給客戶端發送一個ACK確認包,然後通知應用程序準備關閉,因爲應用程序可能還有些數據需要發送給客戶端,所以這時服務端是CLOSE_WAIT狀態,而不是CLOSED狀態。

          2   客戶端發送FIN包要求斷開連接後就進入了FIN-WAIT-1狀態,當收到服務端發送的ACK包後就進入到FIN-WAIT-2狀態,而在實際情況下FIN-WAIT-1比較難見,因爲客戶端發送FIN包後服務端會立刻發送ACK包。

          3  客戶端進入FIN-WAIT-2狀態時,表示是半連接,即一方要求關閉連接後,另一方回覆說我還有點數據要傳輸,稍後再關閉,這就是服務端發送ACK之後不立即進入CLOSED狀態,而是通知應用程序準備關閉。

           4  服務端應用程序準備好之後,內核發送FIN給客戶端,等待客戶端的ACK包,服務端進入LAST_ACK狀態,這時候客戶端收到FIN後,發送ACK報 文給服務端,客戶端進入TIME-WAIT狀態,TIME-WAIT等待2MSL後進入CLOSED狀態,服務端收到客戶端發送的ACK包之後進入 CLOSED狀態。


             2MSL時間,當客戶端最後給服務端發送ACK後,不立即進入CLOSED狀態,這2MSL時間是爲了防止客戶端發送的ACK包丟失而讓服務端一直處於LAST_ACK狀態,讓服務端處於LAST_ACK超時重發FIN。

            影響斷開連接的參數:

           1  /proc/sys/net/ipv4/tcp_max_tw_buckets    (18000)

              該參數設置系統的TIME_WAIT的數量,如果超過默認值則會被立即清除。

           2  /proc/sys/net/ipv4/tcp_tw_reuse  (0 關閉  1 打開)

               該參數設置TIME_WAIT重用,可以讓處於TIME_WAIT的連接用於新的tcp連接

            3  /proc/sys/net/ipv4/tcp_tw_recycle  ( 0 關閉  1 打開)

                該參數設置tcp連接中TIME_WAIT的快速回收。

            4  /proc/sys/net/ipv4/tcp_fin_timeout   (60)

                設置FIN-WAIT-2進入CLOSED的等待時間。


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