LInux高級網絡編程篇-TCP連接的狀態詳解以及故障排查

在開始講解故障排查之前,我們先看下幾個命令.

linux查看tcp的狀態命令:

1)、netstat -nat 查看TCP各個狀態的數量

2)、lsof -i:port 可以檢測到打開套接字的狀況

3)、 sar -n SOCK 查看tcp創建的連接數

4)、tcpdump -iany tcp port 9000 對tcp端口為9000的進行抓包

網絡測試常用命令;

1)ping:檢測網絡連接的正常與否,主要是測試延時、抖動、丟包率。

但是很多服務器為了防止攻擊,一般會關閉對ping的響應。所以ping一般作為測試連通性使用。ping命令後,會接收到對方發送的回饋信息,其中記錄著對方的IP地址和TTL。TTL是該字段指定IP包被路由器丟棄之前允許通過的最大網段數量。TTL是IPv4包頭的一個8 bit字段。例如IP包在服務器中發送前設置的TTL是64,你使用ping命令後,得到服務器反饋的信息,其中的TTL為56,說明途中一共經過了8道路由器的轉發,每經過一個路由,TTL減1。

2)traceroute:raceroute 跟蹤數據包到達網絡主機所經過的路由工具

traceroute hostname

3)pathping:是一個路由跟蹤工具,它將 ping 和 tracert 命令的功能與這兩個工具所不提供的其他信息結合起來,綜合了二者的功能

pathping www.baidu.com

4)mtr:以結合ping nslookup tracert 來判斷網絡的相關特性

5) nslookup:用於解析域名,一般用來檢測本機的DNS設置是否配置正確。

LInux高級網絡編程篇-TCP連接的狀態詳解以及故障排查

狀態故障分析

LISTENING:偵聽來自遠方的TCP端口的連接請求.

  1. 首先服務端需要打開一個socket進行監聽,狀態為LISTEN。
  2. 有提供某種服務才會處於LISTENING狀態,TCP狀態變化就是某個端口的狀態變化,提供一個服務就打開一個端口,例如:提供www服務默認開的是80端口,提供ftp服務默認的端口為21,當提供的服務沒有被連接時就處於LISTENING狀態。FTP服務啟動後首先處於偵聽(LISTENING)狀態。處於偵聽LISTENING狀態時,該端口是開放的,等待連接,。
  3. 看LISTENING狀態最主要的是看本機開了哪些端口,這些端口都是哪個程序開的,關閉不必要的端口是保證安全的一個非常重要的方面,服務端口都對應一個服務(應用程序),停止該服務就關閉了該端口。
  4. 如果你不幸中了服務端口的木馬,木馬也開個端口處於LISTENING狀態。

SYN-SENT:客戶端SYN_SENT狀態:

  1. 在發送連接請求後等待匹配的連接請求:客戶端通過應用程序調用connect進行active open。於是客戶端tcp發送一個SYN以請求建立一個連接,之後狀態置為SYN_SENT。
  2. 當請求連接時客戶端首先要發送同步信號給要訪問的機器,此時狀態為SYN_SENT,如果連接成功了就變為ESTABLISHED,正常情況下SYN_SENT狀態非常短暫。例如要訪問網站http://www.baidu.com,如果是正常連接的話,用TCPView觀察IEXPLORE.EXE(IE)建立的連接會發現很快從SYN_SENT變為ESTABLISHED,表示連接成功。SYN_SENT狀態快的也許看不到。
  3. 如果發現有很多SYN_SENT出現,那一般有這麼幾種情況,一是你要訪問的網站不存在或線路不好,二是用掃描軟件掃描一個網段的機器,也會出出現很多SYN_SENT,另外就是可能中了病毒了,例如中了"衝擊波",病毒發作時會掃描其它機器,這樣會有很多SYN_SENT出現。

SYN-RECEIVED:服務器端狀態SYN_RCVD

  1. 收到和發送一個連接請求後等待對方對連接請求的確認
  2. 當服務器收到客戶端發送的同步信號時,將標誌位ACK和SYN置1發送給客戶端,此時服務器端處於SYN_RCVD狀態,如果連接成功了就變為ESTABLISHED,正常情況下SYN_RCVD狀態非常短暫。
  3. 如果發現有很多SYN_RCVD狀態,那你的機器有可能被SYN Flood的DoS(拒絕服務攻擊)攻擊了。

SYN Flood的攻擊原理是:

  • 在進行三次握手時,攻擊軟件向被攻擊的服務器發送SYN連接請求(握手的第一步),但是這個地址是偽造的,如攻擊軟件隨機偽造了51.133.163.104、65.158.99.152等等地址。服務器在收到連接請求時將標誌位ACK和SYN置1發送給客戶端(握手的第二步),但是這些客戶端的IP地址都是偽造的,服務器根本找不到客戶機,也就是說握手的第三步不可能完成。
  • 這種情況下服務器端一般會重試(再次發送SYN+ACK給客戶端)並等待一段時間後丟棄這個未完成的連接,這段時間的長度我們稱為SYN Timeout,一般來說這個時間是分鐘的數量級(大約為30秒-2分鐘);一個用戶出現異常導致服務器的一個線程等待1分鐘並不是什麼很大的問題,但如果有一個惡意的攻擊者大量模擬這種情況,服務器端將為了維護一個非常大的半連接列表而消耗非常多的資源----數以萬計的半連接,即使是簡單的保存並遍歷也會消耗非常多的
    CPU時間和內存,何況還要不斷對這個列表中的IP進行SYN+ACK的重試。此時從正常客戶的角度看來,服務器失去響應,這種情況我們稱做:服務器端受到了SYN Flood攻擊(SYN洪水攻擊

ESTABLISHED:代表一個打開的連接。

  1. ESTABLISHED狀態是表示兩臺機器正在傳輸數據,觀察這個狀態最主要的就是看哪個程序正在處於ESTABLISHED狀態。
  2. 服務器出現很多ESTABLISHED狀態: netstat -nat |grep 9502或者使用lsof -i:9502可以檢測到。
  3. 當客戶端未主動close的時候就斷開連接:即客戶端發送的FIN丟失或未發送。 這時候若客戶端斷開的時候發送了FIN包,則服務端將會處於CLOSE_WAIT狀態;

這時候若客戶端斷開的時候未發送FIN包,則服務端處還是顯示ESTABLISHED狀態;

結果客戶端重新連接服務器。

而新連接上來的客戶端(也就是剛才斷掉的重新連上來了)在服務端肯定是ESTABLISHED; 如果客戶端重複的上演這種情況,那麼服務端將會出現大量的假的ESTABLISHED連接和CLOSE_WAIT連接。

最終結果就是新的其他客戶端無法連接上來,但是利用netstat還是能看到一條連接已經建立,並顯示ESTABLISHED,但始終無法進入程序代碼。

FIN-WAIT-1:等待遠程TCP連接中斷請求,或先前的連接中斷請求的確認

主動關閉(active close)端應用程序調用close,於是其TCP發出FIN請求主動關閉連接,之後進入FIN_WAIT1狀態./* The socket is closed, and the connection is shutting down. 等待遠程TCP的連接中斷請求,或先前的連接中斷請求的確認 */

如果服務器出現shutdown再重啟,使用netstat -nat查看,就會看到很多FIN-WAIT-1的狀態。就是因為服務器當前有很多客戶端連接,直接關閉服務器後,無法接收到客戶端的ACK。

FIN-WAIT-2:從遠程TCP等待連接中斷請求

主動關閉端接到ACK後,就進入了FIN-WAIT-2 ./* Connection is closed, and the socket is waiting for a shutdown from the remote end. 從遠程TCP等待連接中斷請求 */

這就是著名的半關閉的狀態了,這是在關閉連接時,客戶端和服務器兩次握手之後的狀態。在這個狀態下,應用程序還有接受數據的能力,但是已經無法發送數據,但是也有一種可能是,客戶端一直處於FIN_WAIT_2狀態,而服務器則一直處於WAIT_CLOSE狀態,而直到應用層來決定關閉這個狀態。

CLOSE-WAIT:等待從本地用戶發來的連接中斷請求

被動關閉(passive close)端TCP接到FIN後,就發出ACK以回應FIN請求(它的接收也作為文件結束符傳遞給上層應用程序),並進入CLOSE_WAIT. /* The remote end has shut down, waiting for the socket to close. 等待從本地用戶發來的連接中斷請求 */

CLOSING:等待遠程TCP對連接中斷的確認

比較少見./* Both sockets are shut down but we still don't have all our data sent. 等待遠程TCP對連接中斷的確認 */

LAST-ACK:等待原來的發向遠程TCP的連接中斷請求的確認

被動關閉端一段時間後,接收到文件結束符的應用程序將調用CLOSE關閉連接。這導致它的TCP也發送一個 FIN,等待對方的ACK.就進入了LAST-ACK . /* The remote end has shut down, and the socket is closed. Waiting for acknowledgement. 等待原來發向遠程TCP的連接中斷請求的確認 */

使用併發壓力測試的時候,突然斷開壓力測試客戶端,服務器會看到很多LAST-ACK。

TIME-WAIT:等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認

在主動關閉端接收到FIN後,TCP就發送ACK包,並進入TIME-WAIT狀態。/* The socket is waiting after close to handle packets still in the network.等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認 */

TIME_WAIT等待狀態,這個狀態又叫做2MSL狀態,說的是在TIME_WAIT2發送了最後一個ACK數據報以後,要進入TIME_WAIT狀態,這個狀態是防止最後一次握手的數據報沒有傳送到對方那裡而準備的(注意這不是四次握手,這是第四次握手的保險狀態)。這個狀態在很大程度上保證了雙方都可以正常結束,但是,問題也來了。

由於插口的2MSL狀態(插口是IP和端口對的意思,socket),使得應用程序在2MSL時間內是無法再次使用同一個插口的,對於客戶程序還好一些,但是對於服務程序,例如httpd,它總是要使用同一個端口來進行服務,而在2MSL時間內,啟動httpd就會出現錯誤(插口被使用)。為了避免這個錯誤,服務器給出了一個平靜時間的概念,這是說在2MSL時間內,雖然可以重新啟動服務器,但是這個服務器還是要平靜的等待2MSL時間的過去才能進行下一次連接。

CLOSED:沒有任何連接狀態

被動關閉端在接受到ACK包後,就進入了closed的狀態。連接結束./* The socket is not being used. 沒有任何連接狀態 */

下面是本人整理的鏈接,能夠幫助大家快速尋找文章

linux系統篇鏈接:

C++的知識點,下面幾篇文章鏈接:

網絡編程方面,可以查看以下幾篇文章鏈接:

喜歡我的文章的話,就關注我吧!不要只收藏和轉發哦,每天至少兩篇編程知識給大家,都是本人多年的經驗總結!


分享到:


相關文章: