time_wait的快速回收和重用

TCP四次揮手:

 

Time_wait產生緣由及做用:

1. time_wait狀態如何產生? 前端

由上面的變遷圖,首先調用close()發起主動關閉的一方,在發送最後一個ACK以後會進入time_wait的狀態,也就說該發送方會保持2MSL時間以後纔會回到初始狀態。MSL值得是數據包在網絡中的最大生存時間。產生這種結果使得這個TCP鏈接在2MSL鏈接等待期間,定義這個鏈接的四元組(客戶端IP地址和端口,服務端IP地址和端口號)不能被使用。緩存

2.time_wait狀態產生的緣由cookie

1)爲實現TCP全雙工鏈接的可靠釋放網絡

由TCP狀態變遷圖可知,假設發起主動關閉的一方(client)最後發送的ACK在網絡中丟失,因爲TCP協議的重傳機制,執行被動關閉的一方(server)將會重發其FIN,在該FIN到達client以前,client必須維護這條鏈接狀態,也就說這條TCP鏈接所對應的資源(client方的local_ip,local_port)不能被當即釋放或從新分配,直到另外一方重發的FIN達到以後,client重發ACK後,通過2MSL時間週期沒有再收到另外一方的FIN以後,該TCP鏈接才能恢復初始的CLOSED狀態。若是主動關閉一方不維護這樣一個TIME_WAIT狀態,那麼當被動關閉一方重發的FIN到達時,主動關閉一方的TCP傳輸層會用RST包響應對方,這會被對方認爲是有錯誤發生,然而這事實上只是正常的關閉鏈接過程,並不是異常。socket

確保被動關閉方收到ACK,鏈接正常關閉,且不因被動關閉方重傳FIN影響下一個新鏈接tcp

2)爲使舊的數據包在網絡因過時而消失spa

爲說明這個問題,咱們先假設TCP協議中不存在TIME_WAIT狀態的限制,再假設當前有一條TCP鏈接:(local_ip, local_port, remote_ip,remote_port),因某些緣由,咱們先關閉,接着很快以相同的四元組創建一條新鏈接。本文前面介紹過,TCP鏈接由四元組惟一標識,所以,在咱們假設的狀況中,TCP協議棧是沒法區分先後兩條TCP鏈接的不一樣的,在它看來,這根本就是同一條鏈接,中間先釋放再創建的過程對其來講是「感知」不到的。這樣就可能發生這樣的狀況:前一條TCP鏈接由local peer發送的數據到達remote peer後,會被該remot peer的TCP傳輸層當作當前TCP鏈接的正常數據接收並向上傳遞至應用層(而事實上,在咱們假設的場景下,這些舊數據到達remote peer前,舊鏈接已斷開且一條由相同四元組構成的新TCP鏈接已創建,所以,這些舊數據是不該該被向上傳遞至應用層的),從而引發數據錯亂進而致使各類沒法預知的詭異現象。做爲一種可靠的傳輸協議,TCP必須在協議層面考慮並避免這種狀況的發生,這正是TIME_WAIT狀態存在的第2個緣由。server

2MSL:報文最大生存時間,確保舊的數據不會影響新鏈接blog

3)總結 
具體而言,local peer主動調用close後,此時的TCP鏈接進入TIME_WAIT狀態,處於該狀態下的TCP鏈接不能當即以一樣的四元組創建新鏈接,即發起active close的那方佔用的local port在TIME_WAIT期間不能再被從新分配。因爲TIME_WAIT狀態持續時間爲2MSL,這樣保證了舊TCP鏈接雙工鏈路中的舊數據包均因過時(超過MSL)而消失,此後,就能夠用相同的四元組創建一條新鏈接而不會發生先後兩次鏈接數據錯亂的狀況。隊列

快速回收Time_wait:

方法:

  1. vi /etc/sysctl.conf
  2. 編輯文件,加入如下內容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30 

       3.而後執行/sbin/sysctl -p讓參數生效。

net.ipv4.tcp_syncookies = 1表示開啓SYN Cookies。當出現SYN等待隊列溢出時,啓用cookies來處理,可防範少許SYN攻擊,默認爲0,表示關閉;

net.ipv4.tcp_tw_reuse = 1表示開啓重用。容許將TIME-WAIT sockets從新用於新的TCP鏈接,默認爲0,表示關閉;

net.ipv4.tcp_tw_recycle = 1表示開啓TCP鏈接中TIME-WAIT sockets的快速回收,默認爲0,表示關閉。

net.ipv4.tcp_fin_timeout 修改系統默認的TIMEOUT時間

修改以後,再用命令查看TIME_WAIT鏈接數netstat -ant |grep 「TIME_WAIT」 |wc –l。在沒有nat狀況下還須要設置net.ipv4.tcp_timestamps = 1才能生效。關於tcp_tw_recycle參數,TCP有一種行爲,能夠緩存每一個鏈接最新的時間戳,後續請求中若是時間戳小於緩存的時間戳,即視爲無效,相應的數據包會被丟棄。Linux是否啓用這種行爲取決於tcp_timestamps和tcp_tw_recycle,由於tcp_timestamps缺省就是開啓的,因此當tcp_tw_recycle被開啓後,實際上這種行爲就被激活了。在nat環境中會出現時間戳錯亂的狀況,後面的數據包就被丟棄了,具體的 表現一般是是客戶端明明發送的SYN,但服務端就是不響應ACK。由於NAT設備將數據包的源IP地址都改爲了一個地址(或者少許的IP地址),可是卻基本上不修改TCP包的時間戳,則會致使時間戳混亂。建議:若是前端部署了三/四層NAT設備,儘可能關閉快速回收,以避免發生NAT背後真實機器因爲時間戳混亂致使的SYN拒絕問題。

 

重用Time_wait:

net.ipv4.tcp_tw_reuse = 1

若是能保證如下任意一點,一個TW狀態的四元組(即一個socket鏈接)能夠從新被新到來的SYN鏈接使用:

1.初始序列號比TW老鏈接的末序列號大2.若是使能了時間戳,那麼新到來的鏈接的時間戳比老鏈接的時間戳大

相關文章
相關標籤/搜索