TCP常用命令
了解TCP之前,先了解幾個命令:
linux查看tcp的狀態(tài)命令:
1)、netstat -nat 查看TCP各個狀態(tài)的數(shù)量
2)、lsof -i:port 可以檢測到打開套接字的狀況
3)、 sar -n SOCK 查看tcp創(chuàng)建的連接數(shù)
4)、tcpdump -iany tcp port 9000 對tcp端口為9000的進行抓包
網(wǎng)絡(luò)測試常用命令;
1)ping:檢測網(wǎng)絡(luò)連接的正常與否,主要是測試延時、抖動、丟包率。
但是很多服務(wù)器為了防止攻擊,一般會關(guān)閉對ping的響應。所以ping一般作為測試連通性使用。ping命令后,會接收到對方發(fā)送的回饋信息,其中記錄著對方的IP地址和TTL。TTL是該字段指定IP包被路由器丟棄之前允許通過的最大網(wǎng)段數(shù)量。TTL是IPv4包頭的一個8 bit字段。例如IP包在服務(wù)器中發(fā)送前設(shè)置的TTL是64,你使用ping命令后,得到服務(wù)器反饋的信息,其中的TTL為56,說明途中一共經(jīng)過了8道路由器的轉(zhuǎn)發(fā),每經(jīng)過一個路由,TTL減1。
2)traceroute:raceroute 跟蹤數(shù)據(jù)包到達網(wǎng)絡(luò)主機所經(jīng)過的路由工具
traceroute hostname
3)pathping:是一個路由跟蹤工具,它將 ping 和 tracert 命令的功能與這兩個工具所不提供的其他信息結(jié)合起來,綜合了二者的功能
pathping www.baidu.com
4)mtr:以結(jié)合ping nslookup tracert 來判斷網(wǎng)絡(luò)的相關(guān)特性
5) nslookup:用于解析域名,一般用來檢測本機的DNS設(shè)置是否配置正確。
? ? ?TCP狀態(tài)分析
LISTENING:偵聽來自遠方的TCP端口的連接請求。
首先服務(wù)端需要打開一個socket進行監(jiān)聽,狀態(tài)為LISTEN。
有提供某種服務(wù)才會處于LISTENING狀態(tài),TCP狀態(tài)變化就是某個端口的狀態(tài)變化,提供一個服務(wù)就打開一個端口,例如:提供www服務(wù)默認開的是80端口,提供ftp服務(wù)默認的端口為21,當提供的服務(wù)沒有被連接時就處于LISTENING狀態(tài)。FTP服務(wù)啟動后首先處于偵聽(LISTENING)狀態(tài)。處于偵聽LISTENING狀態(tài)時,該端口是開放的,等待連接,但還沒有被連接。就像你房子的門已經(jīng)敞開的,但還沒有人進來。
看LISTENING狀態(tài)最主要的是看本機開了哪些端口,這些端口都是哪個程序開的,關(guān)閉不必要的端口是保證安全的一個非常重要的方面,服務(wù)端口都對應一個服務(wù)(應用程序),停止該服務(wù)就關(guān)閉了該端口,例如要關(guān)閉21端口只要停止IIS服務(wù)中的FTP服務(wù)即可。關(guān)于這方面的知識請參閱其它文章。
如果你不幸中了服務(wù)端口的木馬,木馬也開個端口處于LISTENING狀態(tài)。
SYN-SENT:客戶端SYN_SENT狀態(tài):
再發(fā)送連接請求后等待匹配的連接請求:客戶端通過應用程序調(diào)用connect進行active open.于是客戶端tcp發(fā)送一個SYN以請求建立一個連接。之后狀態(tài)置為SYN_SENT. /*The socket is actively attempting to establish a connection. 在發(fā)送連接請求后等待匹配的連接請求 */
當請求連接時客戶端首先要發(fā)送同步信號給要訪問的機器,此時狀態(tài)為SYN_SENT,如果連接成功了就變?yōu)镋STABLISHED,正常情況下SYN_SENT狀態(tài)非常短暫。例如要訪問網(wǎng)站http://www.baidu.com,如果是正常連接的話,用TCPView觀察IEXPLORE.EXE(IE)建立的連接會發(fā)現(xiàn)很快從SYN_SENT變?yōu)镋STABLISHED,表示連接成功。SYN_SENT狀態(tài)快的也許看不到。
如果發(fā)現(xiàn)有很多SYN_SENT出現(xiàn),那一般有這么幾種情況,一是你要訪問的網(wǎng)站不存在或線路不好,二是用掃描軟件掃描一個網(wǎng)段的機器,也會出出現(xiàn)很多SYN_SENT,另外就是可能中了病毒了,例如中了“沖擊波”,病毒發(fā)作時會掃描其它機器,這樣會有很多SYN_SENT出現(xiàn)。
SYN-RECEIVED:服務(wù)器端狀態(tài)SYN_RCVD
再收到和發(fā)送一個連接請求后等待對方對連接請求的確認
當服務(wù)器收到客戶端發(fā)送的同步信號時,將標志位ACK和SYN置1發(fā)送給客戶端,此時服務(wù)器端處于SYN_RCVD狀態(tài),如果連接成功了就變?yōu)镋STABLISHED,正常情況下SYN_RCVD狀態(tài)非常短暫。
如果發(fā)現(xiàn)有很多SYN_RCVD狀態(tài),那你的機器有可能被SYN Flood的DoS(拒絕服務(wù)攻擊)攻擊了。
SYN Flood的攻擊原理是:
在進行三次握手時,攻擊軟件向被攻擊的服務(wù)器發(fā)送SYN連接請求(握手的第一步),但是這個地址是偽造的,如攻擊軟件隨機偽造了51.133.163.104、65.158.99.152等等地址。服務(wù)器在收到連接請求時將標志位ACK和SYN置1發(fā)送給客戶端(握手的第二步),但是這些客戶端的IP地址都是偽造的,服務(wù)器根本找不到客戶機,也就是說握手的第三步不可能完成。
這種情況下服務(wù)器端一般會重試(再次發(fā)送SYN+ACK給客戶端)并等待一段時間后丟棄這個未完成的連接,這段時間的長度我們稱為SYN Timeout,一般來說這個時間是分鐘的數(shù)量級(大約為30秒-2分鐘);一個用戶出現(xiàn)異常導致服務(wù)器的一個線程等待1分鐘并不是什么很大的問題,但如果有一個惡意的攻擊者大量模擬這種情況,服務(wù)器端將為了維護一個非常大的半連接列表而消耗非常多的資源----數(shù)以萬計的半連接,即使是簡單的保存并遍歷也會消耗非常多的CPU時間和內(nèi)存,何況還要不斷對這個列表中的IP進行SYN+ACK的重試。此時從正??蛻舻慕嵌瓤磥?,服務(wù)器失去響應,這種情況我們稱做:服務(wù)器端受到了SYN Flood攻擊(SYN洪水攻擊)
ESTABLISHED:代表一個打開的連接。
ESTABLISHED狀態(tài)是表示兩臺機器正在傳輸數(shù)據(jù),觀察這個狀態(tài)最主要的就是看哪個程序正在處于ESTABLISHED狀態(tài)。
服務(wù)器出現(xiàn)很多ESTABLISHED狀態(tài): netstat -nat |grep 9502或者使用lsof -i:9502可以檢測到。
當客戶端未主動close的時候就斷開連接:即客戶端發(fā)送的FIN丟失或未發(fā)送。
這時候若客戶端斷開的時候發(fā)送了FIN包,則服務(wù)端將會處于CLOSE_WAIT狀態(tài);
這時候若客戶端斷開的時候未發(fā)送FIN包,則服務(wù)端處還是顯示ESTABLISHED狀態(tài);
結(jié)果客戶端重新連接服務(wù)器。
而新連接上來的客戶端(也就是剛才斷掉的重新連上來了)在服務(wù)端肯定是ESTABLISHED; 如果客戶端重復的上演這種情況,那么服務(wù)端將會出現(xiàn)大量的假的ESTABLISHED連接和CLOSE_WAIT連接。
最終結(jié)果就是新的其他客戶端無法連接上來,但是利用netstat還是能看到一條連接已經(jīng)建立,并顯示ESTABLISHED,但始終無法進入程序代碼。
FIN-WAIT-1:等待遠程TCP連接中斷請求,或先前的連接中斷請求的確認
主動關(guān)閉(active close)端應用程序調(diào)用close,于是其TCP發(fā)出FIN請求主動關(guān)閉連接,之后進入FIN_WAIT1狀態(tài)。/* The socket is closed, and the connection is shutting down. 等待遠程TCP的連接中斷請求,或先前的連接中斷請求的確認 */
如果服務(wù)器出現(xiàn)shutdown再重啟,使用netstat -nat查看,就會看到很多FIN-WAIT-1的狀態(tài)。就是因為服務(wù)器當前有很多客戶端連接,直接關(guān)閉服務(wù)器后,無法接收到客戶端的ACK。
FIN-WAIT-2:從遠程TCP等待連接中斷請求
主動關(guān)閉端接到ACK后,就進入了FIN-WAIT-2 。/* Connection is closed, and the socket is waiting for a shutdown from the remote end. 從遠程TCP等待連接中斷請求 */
這就是著名的半關(guān)閉的狀態(tài)了,這是在關(guān)閉連接時,客戶端和服務(wù)器兩次握手之后的狀態(tài)。在這個狀態(tài)下,應用程序還有接受數(shù)據(jù)的能力,但是已經(jīng)無法發(fā)送數(shù)據(jù),但是也有一種可能是,客戶端一直處于FIN_WAIT_2狀態(tài),而服務(wù)器則一直處于WAIT_CLOSE狀態(tài),而直到應用層來決定關(guān)閉這個狀態(tài)。
CLOSE-WAIT:等待從本地用戶發(fā)來的連接中斷請求
被動關(guān)閉(passive close)端TCP接到FIN后,就發(fā)出ACK以回應FIN請求(它的接收也作為文件結(jié)束符傳遞給上層應用程序),并進入CLOSE_WAIT. /* The remote end has shut down, waiting for the socket to close. 等待從本地用戶發(fā)來的連接中斷請求 */
CLOSING:等待遠程TCP對連接中斷的確認
比較少見。/* Both sockets are shut down but we still don‘t have all our data sent. 等待遠程TCP對連接中斷的確認 */
LAST-ACK:等待原來的發(fā)向遠程TCP的連接中斷請求的確認
被動關(guān)閉端一段時間后,接收到文件結(jié)束符的應用程序?qū)⒄{(diào)用CLOSE關(guān)閉連接。這導致它的TCP也發(fā)送一個 FIN,等待對方的ACK.就進入了LAST-ACK 。 /* The remote end has shut down, and the socket is closed. Waiting for acknowledgement. 等待原來發(fā)向遠程TCP的連接中斷請求的確認 */
使用并發(fā)壓力測試的時候,突然斷開壓力測試客戶端,服務(wù)器會看到很多LAST-ACK。
TIME-WAIT:等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認
在主動關(guān)閉端接收到FIN后,TCP就發(fā)送ACK包,并進入TIME-WAIT狀態(tài)。/* The socket is waiting after close to handle packets still in the network.等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認 */
TIME_WAIT等待狀態(tài),這個狀態(tài)又叫做2MSL狀態(tài),說的是在TIME_WAIT2發(fā)送了最后一個ACK數(shù)據(jù)報以后,要進入TIME_WAIT狀態(tài),這個狀態(tài)是防止最后一次握手的數(shù)據(jù)報沒有傳送到對方那里而準備的(注意這不是四次握手,這是第四次握手的保險狀態(tài))。這個狀態(tài)在很大程度上保證了雙方都可以正常結(jié)束,但是,問題也來了。
由于插口的2MSL狀態(tài)(插口是IP和端口對的意思,socket),使得應用程序在2MSL時間內(nèi)是無法再次使用同一個插口的,對于客戶程序還好一些,但是對于服務(wù)程序,例如httpd,它總是要使用同一個端口來進行服務(wù),而在2MSL時間內(nèi),啟動httpd就會出現(xiàn)錯誤(插口被使用)。為了避免這個錯誤,服務(wù)器給出了一個平靜時間的概念,這是說在2MSL時間內(nèi),雖然可以重新啟動服務(wù)器,但是這個服務(wù)器還是要平靜的等待2MSL時間的過去才能進行下一次連接。
CLOSED:沒有任何連接狀態(tài)
被動關(guān)閉端在接受到ACK包后,就進入了closed的狀態(tài)。連接結(jié)束。/* The socket is not being used. 沒有任何連接狀態(tài) */
TCP 連接斷鏈分析
在官方的正式文檔中,TCP/IP 協(xié)議簇也稱為國際互聯(lián)網(wǎng)協(xié)議簇。TCP/IP 協(xié)議簇是目前使用最為廣泛的全球互聯(lián)網(wǎng)技術(shù),其分層結(jié)構(gòu)如圖 1 所示:
圖 1. TCP/IP 協(xié)議簇分層結(jié)構(gòu)
如圖 1 所示,數(shù)據(jù)鏈路層主要負責處理傳輸媒介等眾多的物理接口細節(jié);網(wǎng)絡(luò)層負責處理數(shù)據(jù)分組在網(wǎng)絡(luò)中的活動,包括上層數(shù)據(jù)報文的分割、選路 phost2008-08-21T00:00:00 等;傳輸層則負責為兩臺主機提供端到端的通信;應用層將負責處理應用程序的特定細節(jié)。其中,IP 協(xié)議是網(wǎng)絡(luò)層的核心協(xié)議,用來提供不可靠、無連接的數(shù)據(jù)傳遞服務(wù);而 TCP 協(xié)議則處于傳輸層,其基于不可靠無連接的 IP 協(xié)議能夠為兩臺主機提供面向連接的、可靠的通信。UDP?
由于 TCP 是面向連接的協(xié)議,因此在兩臺主機通信之前,需要首先建立起一條連接。下面我們將簡要介紹 TCP 連接的建立以及通信雙方是如何保持已建立的 TCP 連接的。
TCP 連接的建立及保持
一個 TCP 連接的建立需要通過著名的“三次握手”來完成。下面的例子將直觀給出一個 TCP 連接的建立過程。
在本文的下述描述中,客戶端主機均為 testClient.cn.ibm.com(Linux),服務(wù)器主機均為 testServer.cn.ibm.com(AIX)。在 testClient 主機的一終端上執(zhí)行 tcpdump –i eth0 host testServer 命令,啟動 tcpdump 監(jiān)聽網(wǎng)絡(luò)數(shù)據(jù)(其中,eth0 是客戶主機與外部網(wǎng)絡(luò)進行通信所使用的網(wǎng)卡);與此同時,在客戶主機的另一個終端上執(zhí)行下述命令: (root@testClient /)》telnet testServer。此時客戶主機上 tcpdump 的輸出如清單 1 所示。
清單 1. 創(chuàng)建一個 TCP 連接的三次握手
# tcpdump –S -i en0 host testServer
1 14:02:38.384918 IP testClient.cn.ibm.com.43370 》
testServer.cn.ibm.com.telnet: S 3392458353:3392458353(0) …
2 14:02:38.629578 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.43370: S 881279296:881279296(0) ack 3392458354 …
3 14:02:38.629592 IP testClient.cn.ibm.com.43370 》
testServer.cn.ibm.com.telnet: 。 ack 881279297 …
注意:我們刪除了 tcpdump 輸出結(jié)果中的部分無關(guān)信息。為了便于理解,我們將上述輸出轉(zhuǎn)換為實際序列圖 2。
圖 2. TCP 建立創(chuàng)建三次握手的實際序列
從圖 2 中我們可以清楚地看到,在 testClient 與 testServer 之間建立連接時,要經(jīng)過以下三次握手過程:
testClient 向 testServer 主動發(fā)送握手協(xié)議,報文序列號為 3392458353,大小為 1 個字節(jié)。
testServer 向 testClient 主動發(fā)送握手協(xié)議,報文序列號為 881279296,大小為 1 個字節(jié);同時返回 ACK 3392458354,作為對 testClient 發(fā)來的 3392458354 包的應答。
testClient 向 testServer 返回 ACK 881279297,作為對 testServer 發(fā)來的 881279296 包的應答。
一個 TCP 連接在完成上述的三次握手之后便建立完畢;此后,連接的兩端即可進行信息的相互傳遞。因此,TCP 連接可以認為是以兩端 IP 地址和端口進行標識的一個通信信道,而 TCP 連接的建立就是向通信雙方進行上述通信信道注冊的過程。TCP 連接一旦建立,只要通信雙方之間的中間結(jié)點(包括網(wǎng)關(guān)和交換機、路由器等網(wǎng)絡(luò)設(shè)備)工作正常,那么在通信雙方中的任何一方主動關(guān)閉連接之前,TCP 連接都將被一直保持下去。
TCP 連接的這種特性,使得一個長期不交換任何信息的空閑連接可以長期保持數(shù)小時、數(shù)天甚至數(shù)月。中間路由器可以崩潰、重啟,網(wǎng)線可以被掛斷再連通,只要兩端的主機沒有被重啟,TCP 連接就可以被一直保持下來。
導致 TCP 連接斷連的因素
理想狀態(tài)下,一個 TCP 連接可以被長期保持。然而,在實際應用中,客戶端或服務(wù)器端上維持的一個看似正常的 TCP 連接可能已經(jīng)斷連。TCP 連接主要受到兩個方面的影響而導致斷連:網(wǎng)絡(luò)中間節(jié)點和客戶端 / 服務(wù)器節(jié)點參與通信的兩方節(jié)點?
在實際網(wǎng)絡(luò)應用中,兩個主機之間的通信往往需要穿越多個中間節(jié)點,例如路由器、網(wǎng)關(guān)、防火墻等。因此,兩個主機之間 TCP 連接的保持同樣會受到中間節(jié)點的影響,尤其是會受到防火墻(軟件或硬件防火墻)的限制。防火墻是一種裝置,有多種不同的實現(xiàn)方式(軟件實現(xiàn)、硬件設(shè)備實現(xiàn) 或是軟硬件相結(jié)合實現(xiàn)),它需要依據(jù)一系列規(guī)則對進出的信息流進行掃描,并允許安全(符合規(guī)則)的信息交互、阻止不安全(違反規(guī)則)的信息交互。防火墻的 工作特性決定了要維護一個網(wǎng)絡(luò)連接就需要耗費較多的資源,并且企業(yè)防火墻常常位于企業(yè)網(wǎng)絡(luò)的出入口,長時間維護非活躍的 TCP 連接必將導致網(wǎng)絡(luò)性能的下降。因此,大部分防火墻默認會關(guān)閉長時間處于非活躍狀態(tài)的連接而導致 TCP 連接斷連。類似的,如果中間節(jié)點異常導致來自客戶端關(guān)閉連接的請求無法傳遞到服務(wù)器端,也將導致服務(wù)器端的相應連接發(fā)生斷連。
另一方面,對于一個 TCP 連接兩端的主機而言,創(chuàng)建 TCP 連接需要耗費一定的系統(tǒng)資源。如果不再使用某個連接,那么我們總是希望進行通信的兩個主機能夠主動關(guān)閉相應的連接,以便釋放所占用的系統(tǒng)資源。然而,如果 由于客戶端出現(xiàn)異常 ( 例如崩潰或異常重啟 ) 而導致連接未能正常關(guān)閉,這將導致服務(wù)器端的連接斷連。
無論是客戶端節(jié)點或是服務(wù)器端節(jié)點,斷連的 TCP 連接已經(jīng)不能傳遞任何信息,因此,維護大量斷連的 TCP 連接將導致系統(tǒng)資源的浪費。這種系統(tǒng)資源的浪費可能并不會對客戶端節(jié)點帶來太大問題;然而,對于服務(wù)器主機而言,這可能會導致系統(tǒng)資源(尤指內(nèi)存資源和 socket 資源)被耗盡而拒絕為新的用戶請求提供服務(wù)。因此在實際應用中,服務(wù)器端需要采取相應的方法來探測 TCP 連接是否已經(jīng)斷連。
探測 TCP 連接斷連的三種常用方法
探測 TCP 連接是否斷連或是工作正常的原理比較簡單:定期向連接的遠程通信節(jié)點發(fā)送一定格式的信息并等待遠程通信節(jié)點的反饋,如果在規(guī)定時間內(nèi)收到來自遠程節(jié)點的正 確的反饋信息,那么該連接就是正常的,否則該連接已經(jīng)斷連。依據(jù)該原理,目前常用的探測方法有以下三種。
應用程序的自我探測
應用程序本身附帶探測其自身建立的 TCP 連接的功能。這種方法具有極大的靈活性,可以依據(jù)應用本身的特點選擇相應的探測機制和功能實現(xiàn)。然而,實際應用中,大部分應用程序均沒有附帶自我探測的功能。
第三方應用程序的探測
此種方法就是在服務(wù)節(jié)點上安裝相應的第三方應用程序來探測該節(jié)點上所有的 TCP 連接是否正?;蚴且呀?jīng)斷連。該方法最大的不足就是需要所有支持探測的客戶端能夠識別來自該探測應用的數(shù)據(jù)報文,因此,實際應用中比較少見。
TCP 協(xié)議層的?;钐綔y
最常用的探測方法就是采用 TCP 協(xié)議層提供的?;钐綔y功能即 TCP 連接保活定時器。盡管該功能并不是 RFC 規(guī)范的一部分,但是幾乎所有的類 Unix 系統(tǒng)均實現(xiàn)了該功能,所以使得該探測方法被廣泛使用。
接下來的部分,我們將重點討論來自 TCP 協(xié)議層的保活探測方法。
類 Unix 系統(tǒng)上的 TCP 連接?;疃〞r器
TCP 連接的?;疃〞r器可以在應用層實現(xiàn),也可以在 TCP 中提供。這個問題存在爭議,因此 TCP 連接的?;钐綔y并不是 TCP 規(guī)范中的一部分。但為了方便,幾乎所有類 Unix 系統(tǒng)均在 TCP 中提供了相應的功能。
清單 2. 常見 Unix 系統(tǒng)上的?;疃〞r器
操作系統(tǒng) ?;疃〞r器
AIX# no -a | grep keep
tcp_keepcnt = 8
tcp_keepidle = 14400
tcp_keepintvl = 150
Linux# sysctl -A | grep keep
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200
FreeBSD#sysctl -A | grep net.inet.tcp
net.inet.tcp.keepidle=…
net.inet.tcp.keepintvl=…
不同系統(tǒng)上的各參數(shù)的時間單位不盡相同。在 AIX 上,tcp_keeidle/tcp_keepinit/tcp_keepintvl 的時間單位是 0.5 秒;而在 Linux 上,net.ipv4.tcp_keepalive_intvl 和 net.ipv4.tcp_keepalive_time 的時間單位則為秒。并且,上述參數(shù)僅對運行在其上的服務(wù)器應用連接有效。
注:在 Solaris 上可通過“ndd /dev/tcp \?”命令顯示上述類似參數(shù)信息,而在 HP Unix 上則可通過 nettune 或 ndd 命令進行查詢。
由于所有類 Unix 系統(tǒng)上均支持這種功能,因此,在接下來的部分中我們將基于 AIX 系統(tǒng)具體講述上述參數(shù)的意義和作用機制。
AIX 中的 TCP 連接?;钐綔y機制及原理
正如清單 2 中列出的一樣,AIX 上的保活探測機制由 4 個參數(shù)來控制,其具體意義見清單 3:
清單 3. AIX 上的保活定時器控制參數(shù)
控制參數(shù) 參數(shù)說明
tcp_keepcnt關(guān)閉一個非活躍連接之前進行探測的最大次數(shù),默認為 8 次
tcp_keepidle對一個連接進行有效性探測之前運行的最大非活躍時間間隔,默認值為 14400(即 2 個小時)
tcp_keepintvl兩個探測的時間間隔,默認值為 150 即 75 秒
我們來看一個具體的例子。在 testServer 端(AIX 主機)采用 tcp_keepidel=240(即 2 分鐘):tcp_keepcnt=8:tcp_keepintvl=150(即 75 秒)的參數(shù)值;啟動 testServer 上的 tcpdump 查看網(wǎng)絡(luò)包的交互情況;從 testClient 端發(fā)起請求建立和 testServer 之間的一個 telnet 連接。在連接建立完成之后,拔出 testClient 端的網(wǎng)線并觀察服務(wù)器端的數(shù)據(jù)輸出(見清單 4)。
清單 4. telnet 連接在服務(wù)器端的 tcpdump 輸出
1 # tcpdump -i en1 host testServer.cn.ibm.com
2 04:51:51.379716 IP testClient.cn.ibm.com.telnet.40621 》
testServer.cn.ibm.com.telnet: S 4097149880:4097149880(0)
3 04:51:51.379755 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: S 2543529892:2543529892(0) ack 4097149881
4 04:51:51.380609 IP testClient.cn.ibm.com.telnet.40621 》
testServer.cn.ibm.com.telnet: 。 ack 1
5 。。。
6 04:51:54.924058 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: P 676:696(20) ack 87
7 04:51:54.924909 IP testClient.cn.ibm.com.telnet.40621 》
testServer.cn.ibm.com.telnet: 。 ack 696
8 04:53:54.550192 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
9 04:55:09.550997 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
10 04:56:24.552053 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
11 04:57:39.552615 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
12 04:58:54.553446 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
13 05:00:09.554287 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
14 05:01:24.555117 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
15 05:02:39.555958 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
16 05:03:54.557282 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: 。 695:696(1) ack 86
17 05:05:09.559795 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.40621: R 696:696(0) ack 87
從清單 4 中可以看出,第 6 行的報文是本連接發(fā)送的最后數(shù)據(jù),而第 7 行則是對第 6 行數(shù)據(jù)的確認。其后,該連接上沒有任何數(shù)據(jù)交互,從而使得該連接一直處于非活躍狀態(tài)。經(jīng)過 2 分鐘(第 8 行數(shù)據(jù)報時間 04:53:54 和第 7 行數(shù)據(jù)報時間 04:51:54 之差,即 tcp_keepidle 的值)的非活躍時間后,第 8 行是服務(wù)器端發(fā)起第一個?;钐綔y數(shù)據(jù)報。由于服務(wù)器端沒有收到客戶端關(guān)于探測報文的相應,因此再經(jīng)過 tcp_keepintvl 的時間間隔(75 秒)之后,第 9 行顯示服務(wù)器端再次發(fā)起?;钐綔y數(shù)據(jù)報。服務(wù)器端持續(xù)發(fā)送了 tcp_keepcnt 個探測報文(上面結(jié)果顯示,在 AIX 上是持續(xù)發(fā)送 tcp_keepcnt+1 個探測報文)之后,仍然沒有收到來自客戶端的任何回應,所以服務(wù)器在第 17 行向客戶端發(fā)送復位報文同時在服務(wù)器端關(guān)閉了該連接。
需要注意的是,?;钐綔y雖然通過發(fā)送 TCP 探測報文,但探測報文不會對正常的 TCP 連接產(chǎn)生任何影響。從清單 4 可以看出,第 8 行發(fā)送數(shù)據(jù)的 TCP 報文序號為 695 起始的 1Byte 數(shù)據(jù),而該數(shù)據(jù)在第 6 行已經(jīng)發(fā)送并被客戶端確認。對于正常狀態(tài)的連接,客戶端在收到探測報文之后將返回一個第 7 行所示的 ACK 報文并借此向服務(wù)器端表明連接工作正常。
接下來,我們將通過一個實際的 TCP 斷連的例子來分析上述機制對 TCP 連接保持的影響,并針對需要長時間保持 TCP 連接的應用提出兩種可選的解決方案。
AIX 上的 TCP 斷連及數(shù)據(jù)分析
圖 3. 出現(xiàn) TCP 斷連的網(wǎng)絡(luò)拓撲結(jié)構(gòu)示意圖
所有服務(wù)器主機均劃為一個局域網(wǎng),并處于防火墻 B 之后。由于工作需要,來自工作區(qū)局域網(wǎng)的主機 testClient 需和服務(wù)器局域網(wǎng)內(nèi)的 testServer 上的數(shù)據(jù)庫使用 TCP/IP 建立一個連接,testClient 上的上層應用將通過該連接對 testServer 上的數(shù)據(jù)庫進行相應操作。
在實際測試中,我們發(fā)現(xiàn),在 testClient 和 testServer 均工作正常的情況下,testClient 上的客戶端在事先沒有收到任何異常信息的情況下,所持有的連接會出現(xiàn)非預期的斷連現(xiàn)象(在試圖通過連接進行數(shù)據(jù)庫操作時,會被告知 connection is reset by foreign host 的錯誤)。
由于該現(xiàn)象不斷出現(xiàn),并且網(wǎng)絡(luò)內(nèi)的中間節(jié)點(路由器和交換機等)均工作正常,因此可以排除物理因素(如掉電、宕機等)的可能。為了便于分析斷連原因,我們首先查看了 testServer 機器上的默認保活設(shè)置:
# no -a | grep keep
tcp_keepcnt = 8
tcp_keepidle = 14400
tcp_keepintvl = 150
testServer 上的 tcp_keepidle 為 14400,即 2 個小時。既然中間節(jié)點工作正常,為什么?;顧C制沒有其作用呢?為了進行分析,我們采用 tcpdump 工具捕獲 testClient 和 testServer 上的報文信息,見清單 5 和清單 6 所示。
清單 5. 服務(wù)器端的 tcpdump 數(shù)據(jù)輸出
1 10:18:58.881950 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: S 1182666808:1182666808(0) 。。。
2 10:18:58.882001 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.59098: S 3333341833:3333341833(0) ack 1182666809 。。。
3 10:18:58.882845 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: 。 ack 1 。。。
4 。。。
5 10:19:03.165568 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.59098: P 1010:1032(22) ack 87 。。。
6 10:19:03.166457 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: 。 ack 1032 。。。
7 12:19:05.445336 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.59098: 。 1031:1032(1) ack 86 。。。
8 12:19:05.445464 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: R 86:87(1) ack 1031 。。。
清單 6. 客戶端的 tcpdump 數(shù)據(jù)輸出
1 # tcpdump -e -i eth0 host testServer.cn.ibm.com
2 10:18:55.800553 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: S 1182666808:1182666808(0) 。。。
3 10:18:55.801778 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.59098: S 3333341833:3333341833(0) ack 1182666809 。。。
4 10:18:55.801799 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: 。 ack 1 。。。
5 。。。
6 10:19:00.084662 IP testServer.cn.ibm.com.telnet 》
testClient.cn.ibm.com.59098: P 1010:1032(22) ack 87 。。。
7 10:19:00.084678 IP testClient.cn.ibm.com.59098 》
testServer.cn.ibm.com.telnet: 。 ack 1032 。。。
從清單 5 中可以看出,在該連接處于非活躍狀態(tài)的時間達到 tcp_keepidle 設(shè)定的 2 小時時,服務(wù)器主機發(fā)出了第一個連接?;畹奶綔y報文(清單 5 中的第 7 行)。緊接著,服務(wù)器主機就收到了來自 testClient 的連接復位報文(清單 5 中的第 8 行)。之后,服務(wù)器便關(guān)閉了該連接(可以通過 netstat –ni 來查看)。然而,從清單 6 的 tcpdump 數(shù)據(jù)可以看出, testClient 端并未發(fā)送任何報文。那么,是誰向 testServer 發(fā)送了復位報文呢?
為了查看上述復位報文的發(fā)送者,同樣采用上述 tcpdump 命令再次捕獲服務(wù)器端和防火墻 B 的報文信息(注意:通常需要捕獲防火墻主機上網(wǎng)絡(luò)數(shù)據(jù)的出口網(wǎng)卡和入口網(wǎng)卡數(shù)據(jù)),結(jié)果顯示,防火墻 B 在收到來自 testServer 的第一個探測報文之后就立刻向 testServer 發(fā)送了一個復位報文。
上述分析說明,在連接傳遞完最后一個交互數(shù)據(jù)之后到服務(wù)器端發(fā)送第一個?;钐綔y之間,該連接已經(jīng)被防火墻 B 終止;在此之后,基于該連接的任何報文傳遞在試圖穿過防火墻的時候均會被防火墻丟棄并發(fā)送復位報文。
兩種常用的解決方案
針對上述 TCP 斷連現(xiàn)象,有兩種常用的解決方案可供選擇:
方案 1、延長防火墻終止非活躍的 TCP 連接的時間。例如,針對上述案例,可以調(diào)節(jié)防火墻設(shè)置,將時間設(shè)置為大于服務(wù)器端設(shè)定的 2 小時。
方案 2、縮短服務(wù)器端的 TCP 連接?;顣r間??s短該時間的目的是為了在連接被防火墻終止之前發(fā)送保活探測報文,既可以探測客戶端狀態(tài),又可以使連接變?yōu)榛钴S狀態(tài)。
對于第一種方案而言,延長 TCP 連接的保持時間可能會導致防火墻性能的降低,尤其是在維持大量長時間處于非活躍狀態(tài)的連接的情況下更是如此;而對于第二種方案,如果縮短服務(wù)器端的 TCP 連接?;顣r間,意味著會增加網(wǎng)絡(luò)中的數(shù)據(jù)報文數(shù)而占用額外的網(wǎng)絡(luò)帶寬。因此,兩種方案各有利弊,需要依據(jù)不同的實際應用情況進行選擇。
總結(jié)
本文介紹了 TCP 連接的建立和保持的相關(guān)概念以及影響 TCP 連接保持的常見因素。給出了常見的類 Unix 系統(tǒng)上 TCP 連接保活探測的相關(guān)配置參數(shù),并基于 AIX 借助 tcpdump 工具分析了一個實際的 TCP 斷連的案例。最后,針對 TCP 斷連的情況給出了兩種可行的解決方案。
評論