1. 程式人生 > >【TCP/IP】TCP連線的建立與終止

【TCP/IP】TCP連線的建立與終止

        TCP是一個面向連線的協議。無論哪一方想另一方傳送資料之前,都必須現在雙方之間建立一條連線。這種兩端間連線的建立與無連線協議如UDP不同。一端使用UDP想另一端傳送資料報時,無需任何預先的握手。

連線建立與終止的時間系列

       傳送第一個SYN的一端將執行主動開啟(active open)。接收這個SYN併發回下個一SYN的另一端執行被動開啟(passive open)

        建立一個連線需要三次握手,而終止一個連線要經過四次握手。這由TCP的半關閉(half-close)造成的。既然一個TCP連線時全雙工,因此每個方向必須單獨的進行關閉。這原則就是當一方完成它的資料傳送任務後就能傳送一個FIN來終止這個方向連線。當一端收到一個FIN,它必須通知應用層另一端已經終止了那個方向的資料傳送。傳送FIN通常是應用層進行關閉的結果。

        收到一個FIN只意味著在這一方向上沒有資料流動,一個TCP連線在收到一個FIN後任能傳送資料。而這對利用半關閉的應用來說是可能的,儘管在實際應用中只有很少的TCP應用程式這樣做。

        首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。通常一方完成主動關閉而另一方完成被動關閉。

        傳送FIN將導致應用程式關閉它們的連線,這些FIN的ACK是由TCP軟體自動產生的。

       當一端為建立連線傳送它的SYN時,它為連線選擇一個初始序號。ISN隨時間而變化,因此每個連線都將具有不同的ISN。RFC 793 【Postel 1981c】指出ISN可看作時一個32位元的計數器,每4ms加1.這樣選擇序號的目的在於防止網路中被延遲的分組在以後又被傳送,而導致某個連線的一方對它作錯誤的解釋。

       初始化序列號(ISN),在開機的時候,它就有一個函式,每個作業系統不一樣,來不斷的增加初始序列號的值。因為它的最大值為2的32次方,所以當達到最大值後,會又從0開始計數。

       當在T1時間客戶端要向伺服器建立TCP,傳送三次握手,就需要發一個SYN包。這時客戶端就會擷取T1時間的ISN作為SYN包的序列號,當伺服器收到SYN包,在T2時間要回送SYN,ACK的時候,它就會擷取T2時間的ISN作為SYN的序列號。ACK序列號為T1時間的ISN+1.

       ASA的一個功能,隨機初始化序列號擾亂。為什麼需要擾亂初始化序列號,

1.    一臺PC它的ISN有自己的增長規律,如果它在ASA裡面,有些攻擊者他會不斷的去連線PC,PC這時候就會不斷的回覆SYN,ACK。攻擊者就能得到不同節點時間段的ISN,然後用這些不同時間段的ISN來計算出PC的ISN增長規律,通過判斷ISN增長規律,攻擊者就有可能判斷出你的作業系統。

2.     一臺PC和某個主機已經建立了TCP連線,攻擊者想做一個會話劫持,它需要偽裝PC的IP地址、埠號、協議號。這些偽裝了還是不行,還得知道你的序列號在什麼範圍。所以攻擊者這時候也會通過多次探測來猜測ISN的增長規律,當得到ISN的增長規律會就會把PC幹掉,攻擊者自己連線到相應的主機。

        所以ASA就要防止這些攻擊者通過多次試探來獲取PC的ISN增長規律,因為一旦PC的ISN增長規律被獲取後,攻擊者就可以對我的作業系統進行判斷,而且還有可能造成更嚴重的會話劫持。所以ASA會對初始化序列號進行擾亂。

        當PC在T1時刻傳送SYN的時候,經過ASA,ASA會把T1時刻的ISN隨機加一個數發走,在T2時刻傳送SYN的時候,經過ASA,ASA又會把T2時刻的ISN隨機加一個會減去一個數發走。由於ASA總是會在ISN的數上隨機加上一個或者減去一個數,這樣的話,攻擊者在看你的ISN的時候就會覺得沒有規律可尋。

2MSL等待時間

        TIMA_WAIT狀態也稱為2MSL等待狀態,每個具體TCP實現必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime)。它時任何報文段被丟棄前在網路內的最長時間。

           RFC 793【Postel 1981c】指出MSL為2分鐘。然而,現實中的常用值是30秒,1分鐘,或2分鐘。

        對一個具體實現所給定的MSL值,處理的原則是:當TCP執行一個主動關閉,併發回最後一個ACK,該連線必須在TIME_WAIT狀態停留的時間為2倍的MSL。這樣可讓TCP再次傳送最後的ACK以防止這個ACK丟失(另一端超時並重發最後的FIN)。

        這種2MSL等待的另一個結果是這個TCP連線在2MSL等待期間,定義這個連線的插口(客戶的IP地址和埠號,伺服器的IP地址和埠號)不能再被使用。這個連線只能在2MSL結束後才能再被使用

       在連線處於2MSL等待時,任何遲到的報文段將被丟棄。因為處於2MSL等待時,由該插口對定義的連線在這段時間內不能再被使用。如果使用這個插口對建立新的連線,在收到來自這個插口對的包時,就會不知道,這個包是老的發的還是新的發的。

平靜時間的概念

       對於來自某個連線的較早替身的遲到報文段,23MSL等待課防止將它解釋成使用相同插口對的新連線的一部分。但這隻有在處於2MSL等待連線中的主機處於正常工作狀態時才有效。

       如果使用處於2MSL等待埠的主機出現故障,它會在MSL秒內重新啟動,並立即使用故障前仍處於2MSL的插口對來建立一個新的連結嗎?如果這樣,在故障前從這個連線發出而遲到的報文段會被錯誤地當作屬於重啟後新連線的報文段。無論如何選擇重啟後新連線的初始序號,都會發生這種情況

       為了防止這種情況,RFC 793指出TCP在重啟後的MSL秒內不能建立任何連線。這就稱為平靜時間。

       只有極少的現實版遵守這一原則,因為大多數主機重啟的時間都比MSL秒要長。

FIN_WAIT_2狀態

       在FIN_WAIT_2狀態我們已經發送除了FIN,並且另一端也已對它進行確認。除非我們在實行半關閉,否則將等待另一端的應用層意識到它已收到一個檔案結束符說明,並向我們傳送一個FIN來關閉另一方向的連線。只有當另一端的程序完成這個關閉,我們這段才會從FIN_WAIT_2狀態進入TIME_WAIT狀態

       這意味著我們這端可能永遠保持這個狀態。另一端也將處於CLOSE_WAIT狀態,並一直保持這個狀態直到應用層決定進行關閉。

在ASA中,ASA認為這樣會消耗客戶端資源。ASA發現只要有一邊做了FIN,並在一定時間內,遠端並沒有再來發送一個FIN來進行關閉的話,那麼ASA將傳送一個RST置位把客戶端的資源給釋放掉。

復位報文段

       無論何時一個報文段發往基準的連接出現錯誤,TCP都會發出一個復位報文段。當telnet一個遠端主機沒有開放的埠時,TCP就會發出一個復位報文段來斷開這個請求,而UDP是傳送一個ICMP埠不可達差錯。

異常終止一個連線

       終止一個連線的正常方式是一方傳送FIN。有時這也稱為有序釋放

       有可能傳送一個復位報文段而不是FIN來中途釋放一個連線。有時稱這為異常釋放

       異常終止一個連線對應用程式來說有兩個優點

(1)    丟棄任何待發送資料並立即傳送復位報文段;

(2)    RST的接收方會區分另一端執行的是異常關閉還是正常關閉。

應用程式使用的API必須提供產生異常關閉而不是正常關閉的手段。

檢查半開啟連線

        如果一方已經關閉或異常終止連線而另一方卻還不知道,我們將這樣的TCP連線稱為半開啟的(Half-Open)。任何一端的主機異常都可能導致發生這種情況。只要不打算在半開啟連線上傳輸資料,仍處於連線狀態的一方就不會檢測另一方已經出現異常。

        半開啟連線的另一個常見原因是當客戶主機突然掉電而不是正常的結束客戶應用程式後再關機。此時如果伺服器又重新啟動,它將丟失復位前連線的所有資訊,因此它不知道資料報文段中提到的連線。此時TCP處理的原則是接收方傳送RST置位作為應答。

同時開啟

        兩個應用程式同時彼此執行主動開啟的情況是可能的,TCP特意設計可以處理同時開啟,對於同時開啟它僅建立一條連線而不是兩條連線。

        同時開啟時,兩端幾乎同時傳送SYN,並進入SYN_SENT狀態。當每一端收到SYN時,狀態變為SYN_RCVD,同時它們都再發SYN並對收到的SYN進行確認。當雙方都收到SYN相應的ACK時,狀態都變遷為ESTABLISH。

        一個同時開啟的連線需要交換4個報文段,比正常的三次握手多1個,

同時關閉

        雙方同時執行主動關閉是可能的,TCP協議也允許這樣的同時關閉。

        當應用層發出關閉命令時,兩端均從ESTABLISH變為FIN_WAIT1,這將導致雙方各發送一個FIN,兩個FIN經過網路傳送後分別到達另一端。收到FIN後,狀態由FIN_WAIT1變遷到CLOSING,併發達最後的ACK,狀態變化為TIME_WAIT。