TCP协议三次握手连接四次握手断开和DOS攻击
生活随笔
收集整理的這篇文章主要介紹了
TCP协议三次握手连接四次握手断开和DOS攻击
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
轉載:
http://hi.baidu.com/xgdcisco/blog/item/60da65f70fd8145d342acc28.html;
http://blog.csdn.net/lostyears/article/details/7104349
TCP連接的狀態(tài)圖
TCP建立連接的三次握手過程,以及關閉連接的四次握手過程
貼一個telnet建立連接,斷開連接的使用wireshark捕獲的packet截圖。
1、建立連接協(xié)議(三次握手)
(1)客戶 端發(fā)送一個帶SYN標志的TCP報文到服務器。這是三次握手過程中的報文1。
(2) 服務器端回應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ACK標志和SYN標志。因此它表示對剛才客戶端SYN報文的回應;同時又標志SYN給客戶端,詢問客戶端是否準備好進行數(shù)據(jù)通 訊。
(3) 客戶必須再次回應服務段一個ACK報文,這是報文段3。
2、連接終止協(xié)議(四次握手)
由于TCP連 接是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數(shù)據(jù)發(fā)送任務后就能發(fā)送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數(shù)據(jù)流動,一個TCP連接在收到一個FIN后仍能發(fā)送數(shù)據(jù)。首先進行關閉的一方將執(zhí)行主動關閉,而另一方執(zhí)行被動關閉。
(1) TCP客 戶端發(fā)送一個FIN,用來關閉客戶到服務器的數(shù)據(jù)傳送(報文段4)。
(2) 服務器收到這個FIN,它發(fā)回一個ACK,確認序號為收到的序號加1(報文段5)。和SYN一樣,一個FIN將占用一個序號。
(3) 服務器關閉客戶端的連接,發(fā)送一個FIN給客戶端(報文段6)。
(4) 客戶段發(fā)回ACK報文確認,并將確認序號設置為收到序號加1(報文段7)。
CLOSED: 這個沒什么好說的了,表示初始狀態(tài)。
LISTEN: 這個也是非常容易理解的一個狀態(tài),表示服務器端的某個SOCKET處 于監(jiān)聽狀態(tài),可以接受連接了。
SYN_RCVD: 這個狀態(tài)表示接受到了SYN報文,在正常情況下,這個狀態(tài)是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一個中間狀態(tài),很短暫,基本上用netstat你是很難看到這種狀態(tài)的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最后一個ACK報文不予發(fā)送。因此這種狀態(tài)時,當收到客戶端的ACK報文 后,它會進入到ESTABLISHED狀態(tài)。
SYN_SENT: 這個狀態(tài)與SYN_RCVD遙想呼應,當客戶端SOCKET執(zhí)行CONNECT連接時,它首先發(fā)送SYN報文,因此也隨即它會進入到了SYN_SENT狀態(tài),并等待服務端的發(fā)送三次握手中的第2個報文。SYN_SENT狀態(tài)表示客戶端已發(fā)送SYN報文。
ESTABLISHED:這個容易理解了,表示連接已經建立了。
FIN_WAIT_1: 這個狀態(tài)要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對方的FIN報文。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實際上是當SOCKET在ESTABLISHED狀態(tài)時,它想主動關閉連接,向對方發(fā)送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態(tài)。而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態(tài),當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態(tài)一般是比較難見到的,而FIN_WAIT_2狀態(tài)還有時常常可以用netstat看到。
FIN_WAIT_2:上面已經詳細解釋了這種狀態(tài),實際上FIN_WAIT_2狀態(tài)下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數(shù)據(jù)需要傳送給你,稍后再關閉連接。
TIME_WAIT: 表示收到了對方的FIN報文,并發(fā)送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態(tài),而無須經過FIN_WAIT_2狀態(tài)。
CLOSING: 這種狀態(tài)比較特殊,實際情況中應該是很少見,屬于一種比較罕見的例外狀態(tài)。正常情況下,當你發(fā)送FIN報文后,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態(tài)表示你發(fā)送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什么情況下會出現(xiàn)此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close一個SOCKET的話,那么就出現(xiàn)了雙方同時發(fā)送FIN報文的情況,也即會出現(xiàn)CLOSING狀態(tài),表示雙方都正在關閉SOCKET連接。
CLOSE_WAIT: 這種狀態(tài)的含義其實是表示在等待關閉。怎么理解呢?當對方close一個SOCKET后發(fā)送FIN報文給自己,你系統(tǒng)毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態(tài)。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有的話,那么你也就可以close這個SOCKET,發(fā)送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態(tài)下,需要完成的事情是等待你去關閉連接。
LAST_ACK: 這個狀態(tài)還是比較容易好理解的,它是被動關閉一方在發(fā)送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態(tài)了。
補充:
a. 默認情況下(不改變socket選項),當你調用close( or closesocket,以下說close不再重復)時,如果發(fā)送緩沖中還有數(shù)據(jù),TCP會繼續(xù)把數(shù)據(jù)發(fā)送完。
b. 發(fā)送了FIN只是表示這端不能繼續(xù)發(fā)送數(shù)據(jù)(應用層不能再調用send發(fā)送),但是還可以接收數(shù)據(jù)。
c. 應用層如何知道對端關閉?通常,在最簡單的阻塞模型中,當你調用recv時,如果返回0,則表示對端關閉。在這個時候通常的做法就是也調用close,那么TCP層就發(fā)送FIN,繼續(xù)完成四次握手。如果你不調用close,那么對端就會處于FIN_WAIT_2狀態(tài),而本端則會處于CLOSE_WAIT狀態(tài)。這個可以寫代碼試試。
d. 在很多時候,TCP連接的斷開都會由TCP層自動進行,例如你CTRL+C終止你的程序,TCP連接依然會正常關閉,你可以寫代碼試試。
1、 為什么建立連接協(xié)議是三次握手,而關閉連接卻是四次握手呢?
這是因為服務端的LISTEN狀態(tài)下的SOCKET當收到SYN報文的建連請求后,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文里來發(fā)送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后,再發(fā)送FIN報文給對方來表示你同意現(xiàn)在可以關閉連接了,所以它這里的ACK報文和FIN報文多數(shù)情況下都是分開發(fā)送的。
2、 為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)?
什么是2MSL?MSL即Maximum Segment Lifetime,也就是報文最大生存時間,引用《TCP/IP詳解》中的話:“它(MSL)是任何報文段被丟棄前在網絡內的最長時間。”那么,2MSL也就是這個時間的2倍,當TCP連接完成四個報文段的交換時,主動關閉的一方將繼續(xù)等待一定時間(2-4分鐘),即使兩端的應用程序結束。例如在上面的telnet程序客戶端關閉后,使用netstat查看的結果:
C:\>netstat -na | find "172.29.21.25"
TCP 172.29.132.60:2795 172.29.21.25:23 TIME_WAIT
為什么需要這個2MSL呢,
第一,雖然雙方都同意關閉連接了,而且握手的4個報文也都協(xié)調和發(fā)送完畢,按理可以直接回到CLOSED狀態(tài)(就好比從SYN_SEND狀態(tài)到ESTABLISH狀態(tài)那樣);但是因為我們必須要假想網絡是不可靠的,你無法保證你最后發(fā)送的ACK報文會一定被對方收到,因此對方處于LAST_ACK狀態(tài)下的SOCKET可能會因為超時未收到ACK報文,而重發(fā)FIN報文,所以這個TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報文。
第二,報文可能會被混淆,意思是說,其他時候的連接可能會被當作本次的連接。直接引用《The TCP/IP Guide》的說法:The second is to provide a “buffering period” between the end of this connection and any subsequent ones. If not for this period, it is possible that packets from different connections could be mixed, creating confusion.
當某個連接的一端處于TIME_WAIT狀態(tài)時,該連接將不能再被使用。事實上,對于我們比較有現(xiàn)實意義的是,這個端口將不能再被使用。某個端口處于TIME_WAIT狀態(tài)(其實應該是這個連接)時,這意味著這個TCP連接并沒有斷開(完全斷開),那么,如果你bind這個端口,就會失敗。對于服務器而言,如果服務器突然crash掉了,那么它將無法在2MSL內重新啟動,因為bind會失敗。解決這個問題的一個方法就是設置socket的SO_REUSEADDR選項。這個選項意味著你可以重用一個地址。
當建立一個TCP連接時,服務器端會繼續(xù)用原有端口監(jiān)聽,同時用這個端口與客戶端通信。而客戶端默認情況下會使用一個隨機端口與服務器端的監(jiān)聽端口通信。有時候,為了服務器端的安全性,我們需要對客戶端進行驗證,即限定某個IP某個特定端口的客戶端。客戶端可以使用bind來使用特定的端口。對于服務器端,當設置了SO_REUSEADDR選項時,它可以在2MSL內啟動并listen成功。但是對于客戶端,當使用bind并設置SO_REUSEADDR時,如果在2MSL內啟動,雖然bind會成功,但是在windows平臺上connect會失敗。而在linux上則不存在這個問題。(我的實驗平臺:winxp, ubuntu7.10)
要解決windows平臺的這個問題,可以設置SO_LINGER選項。SO_LINGER選項決定調用close時TCP的行為。SO_LINGER涉及到linger結構體,如果設置結構體中l(wèi)_onoff為非0,l_linger為0,那么調用close時TCP連接會立刻斷開,TCP不會將發(fā)送緩沖中未發(fā)送的數(shù)據(jù)發(fā)送,而是立即發(fā)送一個RST報文給對方,這個時候TCP連接(關閉時)就不會進入TIME_WAIT狀態(tài)。如你所見,這樣做雖然解決了問題,但是并不安全。通過以上方式設置SO_LINGER狀態(tài),等同于設置SO_DONTLINGER狀態(tài)。
當TCP連接發(fā)生一些物理上的意外情況時,例如網線斷開,linux上的TCP實現(xiàn)會依然認為該連接有效,而windows則會在一定時間后返回錯誤信息。這似乎可以通過設置SO_KEEPALIVE選項來解決,不過不知道這個選項是否對于所有平臺都有效。
3. 為什么不能用兩次握手進行連接?
我們知道,3次握手完成兩個重要的功能,既要雙方做好發(fā)送數(shù)據(jù)的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協(xié)商,這個序列號在握手過程中被發(fā)送和確認。
現(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。作為例子,考慮計算機S和C之間的通信,假定C給S發(fā)送一個連接請求分組,S收到了這個分組,并發(fā)送了確認應答分組。按照兩次握手的協(xié)定,S認為連接已經成功地建立了,可以開始發(fā)送數(shù)據(jù)分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S是否已準備好,不知道S建立什么樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認為連接還未建立成功,將忽略S發(fā)來的任何數(shù)據(jù)分組,只等待連接確認應答分組。而S在發(fā)出的分組超時后,重復發(fā)送同樣的分組。這樣就形成了死鎖。
DoS攻擊
DoS攻擊、DDoS攻擊和DRDoS攻擊相信大家已經早有耳聞了吧!DoS是Denial of Service的簡寫就是拒絕服務,而DDoS就是Distributed Denial of Service的簡寫就是分布式拒絕服務,而DRDoS就是Distributed Reflection Denial of Service的簡寫,這是分布反射式拒絕服務的意思。
不過這3中攻擊方法最厲害的還是DDoS,那個DRDoS攻擊雖然是新近出的一種攻擊方法,但它只是DDoS攻擊的變形,它的唯一不同就是不用占領大量的“肉雞”。這三種方法都是利用TCP三次握手的漏洞進行攻擊的,所以對它們的防御辦法都是差不多的。
DoS攻擊是最早出現(xiàn)的,它的攻擊方法說白了就是單挑,是比誰的機器性能好、速度快。但是現(xiàn)在的科技飛速發(fā)展,一般的網站主機都有十幾臺主機,而且各個主機的處理能力、內存大小和網絡速度都有飛速的發(fā)展,有的網絡帶寬甚至超過了千兆級別。這樣我們的一對一單挑式攻擊就沒有什么作用了,搞不好自己的機子就會死掉。舉個這樣的攻擊例子,假如你的機器每秒能夠發(fā)送10個攻擊用的數(shù)據(jù)包,而被你攻擊的機器(性能、網絡帶寬都是頂尖的)每秒能夠接受并處理100攻擊數(shù)據(jù)包,那樣的話,你的攻擊就什么用處都沒有了,而且非常有死機的可能。要知道,你若是發(fā)送這種1Vs1的攻擊,你的機器的CPU占用率是90%以上的,你的機器要是配置不夠高的話,那你就死定了。
不過,科技在發(fā)展,黑客的技術也在發(fā)展。正所謂道高一尺,魔高一仗。經過無數(shù)次當機,黑客們終于又找到一種新的DoS攻擊方法,這就是DDoS攻擊。它的原理說白了就是群毆,用好多的機器對目標機器一起發(fā)動 DoS攻擊,但這不是很多黑客一起參與的,這種攻擊只是由一名黑客來操作的。這名黑客不是擁有很多機器,他是通過他的機器在網絡上占領很多的“肉雞”,并且控制這些“肉雞”來發(fā)動DDoS攻擊,要不然怎么叫做分布式呢。還是剛才的那個例子,你的機器每秒能發(fā)送10攻擊數(shù)據(jù)包,而被攻擊的機器每秒能夠接受100的數(shù)據(jù)包,這樣你的攻擊肯定不會起作用,而你再用10臺或更多的機器來對被攻擊目標的機器進行攻擊的話,嘿嘿!結果我就不說了。
DRDoS分布反射式拒絕服務攻擊這是DDoS攻擊的變形,它與DDoS的不同之處就是DrDoS不需要在攻擊之前占領大量的“肉雞”。它的攻擊原理和Smurf攻擊原理相近,不過DRDoS是可以在廣域網上進行的,而Smurf攻擊是在局域網進行的。它的作用原理是基于廣播地址與回應請求的。一臺計算機向另一臺計算機發(fā)送一些特殊的數(shù)據(jù)包如ping請求時,會接到它的回應;如果向本網絡的廣播地址發(fā)送請求包,實際上會到達網絡上所有的計算機,這時就會得到所有計算機的回應。這些回應是需要被接收的計算機處理的,每處理一個就要占用一份系統(tǒng)資源,如果同時接到網絡上所有計算機的回應,接收方的系統(tǒng)是有可能吃不消的,就象遭到了DDoS攻擊一樣。不過是沒有人笨到自己攻擊自己,不過這種方法被黑客加以改進就具有很大的威力了。黑客向廣播地址發(fā)送請求包,所有的計算機得到請求后,卻不會把回應發(fā)到黑客那里,而是發(fā)到被攻擊主機。這是因為黑客冒充了被攻擊主機。黑客發(fā)送請求包所用的軟件是可以偽造源地址的,接到偽造數(shù)據(jù)包的主機會根據(jù)源地址把回應發(fā)出去,這當然就是被攻擊主機的地址。黑客同時還會把發(fā)送請求包的時間間隔減小,這樣在短時間能發(fā)出大量的請求包,使被攻擊主機接到從被欺騙計算機那里傳來的洪水般的回應,就像遭到了DDoS攻擊導致系統(tǒng)崩潰。駭客借助了網絡中所有計算機來攻擊受害者,而不需要事先去占領這些被欺騙的主機,這就是Smurf攻擊。而DRDoS攻擊正是這個原理,黑客同樣利用特殊的發(fā)包工具,首先把偽造了源地址的SYN連接請求包發(fā)送到那些被欺騙的計算機上,根據(jù)TCP三次握手的規(guī)則,這些計算機會向源IP發(fā)出SYN+ACK或RST包來響應這個請求。同Smurf攻擊一樣,黑客所發(fā)送的請求包的源IP地址是被攻擊主機的地址,這樣受欺騙的主機就都會把回應發(fā)到被攻擊主機處,造成被攻擊主機忙于處理這些回應而癱瘓。
解釋:
SYN:(Synchronize sequence numbers)用來建立連接,在連接請求中,SYN=1,ACK=0,連接響應時,SYN=1,ACK=1。即,SYN和ACK來區(qū)分Connection Request和Connection Accepted。
RST:(Reset the connection)用于復位因某種原因引起出現(xiàn)的錯誤連接,也用來拒絕非法數(shù)據(jù)和請求。如果接收到RST位時候,通常發(fā)生了某些錯誤。
ACK:(Acknowledgment field significant)置1時表示確認號(Acknowledgment Number)為合法,為0的時候表示數(shù)據(jù)段不包含確認信息,確認號被忽略。
設我們要準備建立連接,服務器正處于正常的接聽狀態(tài)。
第一步:我們也就是客戶端發(fā)送一個帶SYN位的請求,向服務器表示需要連接,假設請求包的序列號為10,那么則為:SYN=10,ACK=0,然后等待服務器的回應。
第二步:服務器接收到這樣的請求包后,查看是否在接聽的是指定的端口,如果不是就發(fā)送RST=1回應,拒絕建立連接。如果接收請求包,那么服務器發(fā)送確認回應,SYN為服務器的一個內碼,假設為100,ACK位則是客戶端的請求序號加1,本例中發(fā)送的數(shù)據(jù)是:SYN=100,ACK=11,用這樣的數(shù)據(jù)回應給我們。向我們表示,服務器連接已經準備好了,等待我們的確認。這時我們接收到回應后,分析得到的信息,準備發(fā)送確認連接信號到服務器。
第三步:我們發(fā)送確認建立連接的信息給服務器。確認信息的SYN位是服務器發(fā)送的ACK位,ACK位是服務器發(fā)送的SYN位加1。即:SYN=11,ACK=101。
這樣我們的連接就建立起來了。
DDoS究竟如何攻擊?目前最流行也是最好用的攻擊方法就是使用SYN-Flood進行攻擊,SYN-Flood也就是SYN洪水攻擊。SYN-Flood不會完成TCP三次握手的第三步,也就是不發(fā)送確認連接的信息給服務器。這樣,服務器無法完成第三次握手,但服務器不會立即放棄,服務器會不停的重試并等待一定的時間后放棄這個未完成的連接,這段時間叫做SYN timeout,這段時間大約30秒-2分鐘左右。若是一個用戶在連接時出現(xiàn)問題導致服務器的一個線程等待1分鐘并不是什么大不了的問題,但是若有人用特殊的軟件大量模擬這種情況,那后果就可想而知了。一個服務器若是處理這些大量的半連接信息而消耗大量的系統(tǒng)資源和網絡帶寬,這樣服務器就不會再有空余去處理普通用戶的正常請求(因為客戶的正常請求比率很小)。這樣這個服務器就無法工作了,這種攻擊就叫做:SYN-Flood攻擊。
到目前為止,進行DDoS攻擊的防御還是比較困難的。首先,這種攻擊的特點是它利用了TCP/IP協(xié)議的漏洞,除非你不用TCP/IP,才有可能完全抵御住DDoS攻擊。不過這不等于我們就沒有辦法阻擋DDoS攻擊,我們可以盡力來減少DDoS的攻擊。下面就是一些防御方法:
1.確保服務器的系統(tǒng)文件是最新的版本,并及時更新系統(tǒng)補丁。
2.關閉不必要的服務。
3.限制同時打開的SYN半連接數(shù)目。
4.縮短SYN半連接的time out 時間。
5.正確設置防火墻
6.禁止對主機的非開放服務的訪問
7.限制特定IP地址的訪問
8.啟用防火墻的防DDoS的屬性
9.嚴格限制對外開放的服務器的向外訪問
10.運行端口映射程序禍端口掃描程序,要認真檢查特權端口和非特權端口。
11.認真檢查網絡設備和主機/服務器系統(tǒng)的日志。只要日志出現(xiàn)漏洞或是時間變更,那這臺機器就可能遭到了攻擊。
12.限制在防火墻外與網絡文件共享。這樣會給黑客截取系統(tǒng)文件的機會,主機的信息暴露給黑客,無疑是給了對方入侵的機會。
TCP連接的狀態(tài)圖
TCP建立連接的三次握手過程,以及關閉連接的四次握手過程
貼一個telnet建立連接,斷開連接的使用wireshark捕獲的packet截圖。
1、建立連接協(xié)議(三次握手)
(1)客戶 端發(fā)送一個帶SYN標志的TCP報文到服務器。這是三次握手過程中的報文1。
(2) 服務器端回應客戶端的,這是三次握手中的第2個報文,這個報文同時帶ACK標志和SYN標志。因此它表示對剛才客戶端SYN報文的回應;同時又標志SYN給客戶端,詢問客戶端是否準備好進行數(shù)據(jù)通 訊。
(3) 客戶必須再次回應服務段一個ACK報文,這是報文段3。
2、連接終止協(xié)議(四次握手)
由于TCP連 接是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數(shù)據(jù)發(fā)送任務后就能發(fā)送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數(shù)據(jù)流動,一個TCP連接在收到一個FIN后仍能發(fā)送數(shù)據(jù)。首先進行關閉的一方將執(zhí)行主動關閉,而另一方執(zhí)行被動關閉。
(1) TCP客 戶端發(fā)送一個FIN,用來關閉客戶到服務器的數(shù)據(jù)傳送(報文段4)。
(2) 服務器收到這個FIN,它發(fā)回一個ACK,確認序號為收到的序號加1(報文段5)。和SYN一樣,一個FIN將占用一個序號。
(3) 服務器關閉客戶端的連接,發(fā)送一個FIN給客戶端(報文段6)。
(4) 客戶段發(fā)回ACK報文確認,并將確認序號設置為收到序號加1(報文段7)。
CLOSED: 這個沒什么好說的了,表示初始狀態(tài)。
LISTEN: 這個也是非常容易理解的一個狀態(tài),表示服務器端的某個SOCKET處 于監(jiān)聽狀態(tài),可以接受連接了。
SYN_RCVD: 這個狀態(tài)表示接受到了SYN報文,在正常情況下,這個狀態(tài)是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一個中間狀態(tài),很短暫,基本上用netstat你是很難看到這種狀態(tài)的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最后一個ACK報文不予發(fā)送。因此這種狀態(tài)時,當收到客戶端的ACK報文 后,它會進入到ESTABLISHED狀態(tài)。
SYN_SENT: 這個狀態(tài)與SYN_RCVD遙想呼應,當客戶端SOCKET執(zhí)行CONNECT連接時,它首先發(fā)送SYN報文,因此也隨即它會進入到了SYN_SENT狀態(tài),并等待服務端的發(fā)送三次握手中的第2個報文。SYN_SENT狀態(tài)表示客戶端已發(fā)送SYN報文。
ESTABLISHED:這個容易理解了,表示連接已經建立了。
FIN_WAIT_1: 這個狀態(tài)要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態(tài)的真正含義都是表示等待對方的FIN報文。而這兩種狀態(tài)的區(qū)別是:FIN_WAIT_1狀態(tài)實際上是當SOCKET在ESTABLISHED狀態(tài)時,它想主動關閉連接,向對方發(fā)送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態(tài)。而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態(tài),當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態(tài)一般是比較難見到的,而FIN_WAIT_2狀態(tài)還有時常常可以用netstat看到。
FIN_WAIT_2:上面已經詳細解釋了這種狀態(tài),實際上FIN_WAIT_2狀態(tài)下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數(shù)據(jù)需要傳送給你,稍后再關閉連接。
TIME_WAIT: 表示收到了對方的FIN報文,并發(fā)送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態(tài)了。如果FIN_WAIT_1狀態(tài)下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態(tài),而無須經過FIN_WAIT_2狀態(tài)。
CLOSING: 這種狀態(tài)比較特殊,實際情況中應該是很少見,屬于一種比較罕見的例外狀態(tài)。正常情況下,當你發(fā)送FIN報文后,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態(tài)表示你發(fā)送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什么情況下會出現(xiàn)此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close一個SOCKET的話,那么就出現(xiàn)了雙方同時發(fā)送FIN報文的情況,也即會出現(xiàn)CLOSING狀態(tài),表示雙方都正在關閉SOCKET連接。
CLOSE_WAIT: 這種狀態(tài)的含義其實是表示在等待關閉。怎么理解呢?當對方close一個SOCKET后發(fā)送FIN報文給自己,你系統(tǒng)毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態(tài)。接下來呢,實際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對方,如果沒有的話,那么你也就可以close這個SOCKET,發(fā)送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態(tài)下,需要完成的事情是等待你去關閉連接。
LAST_ACK: 這個狀態(tài)還是比較容易好理解的,它是被動關閉一方在發(fā)送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態(tài)了。
補充:
a. 默認情況下(不改變socket選項),當你調用close( or closesocket,以下說close不再重復)時,如果發(fā)送緩沖中還有數(shù)據(jù),TCP會繼續(xù)把數(shù)據(jù)發(fā)送完。
b. 發(fā)送了FIN只是表示這端不能繼續(xù)發(fā)送數(shù)據(jù)(應用層不能再調用send發(fā)送),但是還可以接收數(shù)據(jù)。
c. 應用層如何知道對端關閉?通常,在最簡單的阻塞模型中,當你調用recv時,如果返回0,則表示對端關閉。在這個時候通常的做法就是也調用close,那么TCP層就發(fā)送FIN,繼續(xù)完成四次握手。如果你不調用close,那么對端就會處于FIN_WAIT_2狀態(tài),而本端則會處于CLOSE_WAIT狀態(tài)。這個可以寫代碼試試。
d. 在很多時候,TCP連接的斷開都會由TCP層自動進行,例如你CTRL+C終止你的程序,TCP連接依然會正常關閉,你可以寫代碼試試。
1、 為什么建立連接協(xié)議是三次握手,而關閉連接卻是四次握手呢?
這是因為服務端的LISTEN狀態(tài)下的SOCKET當收到SYN報文的建連請求后,它可以把ACK和SYN(ACK起應答作用,而SYN起同步作用)放在一個報文里來發(fā)送。但關閉連接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數(shù)據(jù)發(fā)送給你了;但未必你所有的數(shù)據(jù)都全部發(fā)送給對方了,所以你可以未必會馬上會關閉SOCKET,也即你可能還需要發(fā)送一些數(shù)據(jù)給對方之后,再發(fā)送FIN報文給對方來表示你同意現(xiàn)在可以關閉連接了,所以它這里的ACK報文和FIN報文多數(shù)情況下都是分開發(fā)送的。
2、 為什么TIME_WAIT狀態(tài)還需要等2MSL后才能返回到CLOSED狀態(tài)?
什么是2MSL?MSL即Maximum Segment Lifetime,也就是報文最大生存時間,引用《TCP/IP詳解》中的話:“它(MSL)是任何報文段被丟棄前在網絡內的最長時間。”那么,2MSL也就是這個時間的2倍,當TCP連接完成四個報文段的交換時,主動關閉的一方將繼續(xù)等待一定時間(2-4分鐘),即使兩端的應用程序結束。例如在上面的telnet程序客戶端關閉后,使用netstat查看的結果:
C:\>netstat -na | find "172.29.21.25"
TCP 172.29.132.60:2795 172.29.21.25:23 TIME_WAIT
為什么需要這個2MSL呢,
第一,雖然雙方都同意關閉連接了,而且握手的4個報文也都協(xié)調和發(fā)送完畢,按理可以直接回到CLOSED狀態(tài)(就好比從SYN_SEND狀態(tài)到ESTABLISH狀態(tài)那樣);但是因為我們必須要假想網絡是不可靠的,你無法保證你最后發(fā)送的ACK報文會一定被對方收到,因此對方處于LAST_ACK狀態(tài)下的SOCKET可能會因為超時未收到ACK報文,而重發(fā)FIN報文,所以這個TIME_WAIT狀態(tài)的作用就是用來重發(fā)可能丟失的ACK報文。
第二,報文可能會被混淆,意思是說,其他時候的連接可能會被當作本次的連接。直接引用《The TCP/IP Guide》的說法:The second is to provide a “buffering period” between the end of this connection and any subsequent ones. If not for this period, it is possible that packets from different connections could be mixed, creating confusion.
當某個連接的一端處于TIME_WAIT狀態(tài)時,該連接將不能再被使用。事實上,對于我們比較有現(xiàn)實意義的是,這個端口將不能再被使用。某個端口處于TIME_WAIT狀態(tài)(其實應該是這個連接)時,這意味著這個TCP連接并沒有斷開(完全斷開),那么,如果你bind這個端口,就會失敗。對于服務器而言,如果服務器突然crash掉了,那么它將無法在2MSL內重新啟動,因為bind會失敗。解決這個問題的一個方法就是設置socket的SO_REUSEADDR選項。這個選項意味著你可以重用一個地址。
當建立一個TCP連接時,服務器端會繼續(xù)用原有端口監(jiān)聽,同時用這個端口與客戶端通信。而客戶端默認情況下會使用一個隨機端口與服務器端的監(jiān)聽端口通信。有時候,為了服務器端的安全性,我們需要對客戶端進行驗證,即限定某個IP某個特定端口的客戶端。客戶端可以使用bind來使用特定的端口。對于服務器端,當設置了SO_REUSEADDR選項時,它可以在2MSL內啟動并listen成功。但是對于客戶端,當使用bind并設置SO_REUSEADDR時,如果在2MSL內啟動,雖然bind會成功,但是在windows平臺上connect會失敗。而在linux上則不存在這個問題。(我的實驗平臺:winxp, ubuntu7.10)
要解決windows平臺的這個問題,可以設置SO_LINGER選項。SO_LINGER選項決定調用close時TCP的行為。SO_LINGER涉及到linger結構體,如果設置結構體中l(wèi)_onoff為非0,l_linger為0,那么調用close時TCP連接會立刻斷開,TCP不會將發(fā)送緩沖中未發(fā)送的數(shù)據(jù)發(fā)送,而是立即發(fā)送一個RST報文給對方,這個時候TCP連接(關閉時)就不會進入TIME_WAIT狀態(tài)。如你所見,這樣做雖然解決了問題,但是并不安全。通過以上方式設置SO_LINGER狀態(tài),等同于設置SO_DONTLINGER狀態(tài)。
當TCP連接發(fā)生一些物理上的意外情況時,例如網線斷開,linux上的TCP實現(xiàn)會依然認為該連接有效,而windows則會在一定時間后返回錯誤信息。這似乎可以通過設置SO_KEEPALIVE選項來解決,不過不知道這個選項是否對于所有平臺都有效。
3. 為什么不能用兩次握手進行連接?
我們知道,3次握手完成兩個重要的功能,既要雙方做好發(fā)送數(shù)據(jù)的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協(xié)商,這個序列號在握手過程中被發(fā)送和確認。
現(xiàn)在把三次握手改成僅需要兩次握手,死鎖是可能發(fā)生的。作為例子,考慮計算機S和C之間的通信,假定C給S發(fā)送一個連接請求分組,S收到了這個分組,并發(fā)送了確認應答分組。按照兩次握手的協(xié)定,S認為連接已經成功地建立了,可以開始發(fā)送數(shù)據(jù)分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S是否已準備好,不知道S建立什么樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認為連接還未建立成功,將忽略S發(fā)來的任何數(shù)據(jù)分組,只等待連接確認應答分組。而S在發(fā)出的分組超時后,重復發(fā)送同樣的分組。這樣就形成了死鎖。
DoS攻擊
DoS攻擊、DDoS攻擊和DRDoS攻擊相信大家已經早有耳聞了吧!DoS是Denial of Service的簡寫就是拒絕服務,而DDoS就是Distributed Denial of Service的簡寫就是分布式拒絕服務,而DRDoS就是Distributed Reflection Denial of Service的簡寫,這是分布反射式拒絕服務的意思。
不過這3中攻擊方法最厲害的還是DDoS,那個DRDoS攻擊雖然是新近出的一種攻擊方法,但它只是DDoS攻擊的變形,它的唯一不同就是不用占領大量的“肉雞”。這三種方法都是利用TCP三次握手的漏洞進行攻擊的,所以對它們的防御辦法都是差不多的。
DoS攻擊是最早出現(xiàn)的,它的攻擊方法說白了就是單挑,是比誰的機器性能好、速度快。但是現(xiàn)在的科技飛速發(fā)展,一般的網站主機都有十幾臺主機,而且各個主機的處理能力、內存大小和網絡速度都有飛速的發(fā)展,有的網絡帶寬甚至超過了千兆級別。這樣我們的一對一單挑式攻擊就沒有什么作用了,搞不好自己的機子就會死掉。舉個這樣的攻擊例子,假如你的機器每秒能夠發(fā)送10個攻擊用的數(shù)據(jù)包,而被你攻擊的機器(性能、網絡帶寬都是頂尖的)每秒能夠接受并處理100攻擊數(shù)據(jù)包,那樣的話,你的攻擊就什么用處都沒有了,而且非常有死機的可能。要知道,你若是發(fā)送這種1Vs1的攻擊,你的機器的CPU占用率是90%以上的,你的機器要是配置不夠高的話,那你就死定了。
不過,科技在發(fā)展,黑客的技術也在發(fā)展。正所謂道高一尺,魔高一仗。經過無數(shù)次當機,黑客們終于又找到一種新的DoS攻擊方法,這就是DDoS攻擊。它的原理說白了就是群毆,用好多的機器對目標機器一起發(fā)動 DoS攻擊,但這不是很多黑客一起參與的,這種攻擊只是由一名黑客來操作的。這名黑客不是擁有很多機器,他是通過他的機器在網絡上占領很多的“肉雞”,并且控制這些“肉雞”來發(fā)動DDoS攻擊,要不然怎么叫做分布式呢。還是剛才的那個例子,你的機器每秒能發(fā)送10攻擊數(shù)據(jù)包,而被攻擊的機器每秒能夠接受100的數(shù)據(jù)包,這樣你的攻擊肯定不會起作用,而你再用10臺或更多的機器來對被攻擊目標的機器進行攻擊的話,嘿嘿!結果我就不說了。
DRDoS分布反射式拒絕服務攻擊這是DDoS攻擊的變形,它與DDoS的不同之處就是DrDoS不需要在攻擊之前占領大量的“肉雞”。它的攻擊原理和Smurf攻擊原理相近,不過DRDoS是可以在廣域網上進行的,而Smurf攻擊是在局域網進行的。它的作用原理是基于廣播地址與回應請求的。一臺計算機向另一臺計算機發(fā)送一些特殊的數(shù)據(jù)包如ping請求時,會接到它的回應;如果向本網絡的廣播地址發(fā)送請求包,實際上會到達網絡上所有的計算機,這時就會得到所有計算機的回應。這些回應是需要被接收的計算機處理的,每處理一個就要占用一份系統(tǒng)資源,如果同時接到網絡上所有計算機的回應,接收方的系統(tǒng)是有可能吃不消的,就象遭到了DDoS攻擊一樣。不過是沒有人笨到自己攻擊自己,不過這種方法被黑客加以改進就具有很大的威力了。黑客向廣播地址發(fā)送請求包,所有的計算機得到請求后,卻不會把回應發(fā)到黑客那里,而是發(fā)到被攻擊主機。這是因為黑客冒充了被攻擊主機。黑客發(fā)送請求包所用的軟件是可以偽造源地址的,接到偽造數(shù)據(jù)包的主機會根據(jù)源地址把回應發(fā)出去,這當然就是被攻擊主機的地址。黑客同時還會把發(fā)送請求包的時間間隔減小,這樣在短時間能發(fā)出大量的請求包,使被攻擊主機接到從被欺騙計算機那里傳來的洪水般的回應,就像遭到了DDoS攻擊導致系統(tǒng)崩潰。駭客借助了網絡中所有計算機來攻擊受害者,而不需要事先去占領這些被欺騙的主機,這就是Smurf攻擊。而DRDoS攻擊正是這個原理,黑客同樣利用特殊的發(fā)包工具,首先把偽造了源地址的SYN連接請求包發(fā)送到那些被欺騙的計算機上,根據(jù)TCP三次握手的規(guī)則,這些計算機會向源IP發(fā)出SYN+ACK或RST包來響應這個請求。同Smurf攻擊一樣,黑客所發(fā)送的請求包的源IP地址是被攻擊主機的地址,這樣受欺騙的主機就都會把回應發(fā)到被攻擊主機處,造成被攻擊主機忙于處理這些回應而癱瘓。
解釋:
SYN:(Synchronize sequence numbers)用來建立連接,在連接請求中,SYN=1,ACK=0,連接響應時,SYN=1,ACK=1。即,SYN和ACK來區(qū)分Connection Request和Connection Accepted。
RST:(Reset the connection)用于復位因某種原因引起出現(xiàn)的錯誤連接,也用來拒絕非法數(shù)據(jù)和請求。如果接收到RST位時候,通常發(fā)生了某些錯誤。
ACK:(Acknowledgment field significant)置1時表示確認號(Acknowledgment Number)為合法,為0的時候表示數(shù)據(jù)段不包含確認信息,確認號被忽略。
設我們要準備建立連接,服務器正處于正常的接聽狀態(tài)。
第一步:我們也就是客戶端發(fā)送一個帶SYN位的請求,向服務器表示需要連接,假設請求包的序列號為10,那么則為:SYN=10,ACK=0,然后等待服務器的回應。
第二步:服務器接收到這樣的請求包后,查看是否在接聽的是指定的端口,如果不是就發(fā)送RST=1回應,拒絕建立連接。如果接收請求包,那么服務器發(fā)送確認回應,SYN為服務器的一個內碼,假設為100,ACK位則是客戶端的請求序號加1,本例中發(fā)送的數(shù)據(jù)是:SYN=100,ACK=11,用這樣的數(shù)據(jù)回應給我們。向我們表示,服務器連接已經準備好了,等待我們的確認。這時我們接收到回應后,分析得到的信息,準備發(fā)送確認連接信號到服務器。
第三步:我們發(fā)送確認建立連接的信息給服務器。確認信息的SYN位是服務器發(fā)送的ACK位,ACK位是服務器發(fā)送的SYN位加1。即:SYN=11,ACK=101。
這樣我們的連接就建立起來了。
DDoS究竟如何攻擊?目前最流行也是最好用的攻擊方法就是使用SYN-Flood進行攻擊,SYN-Flood也就是SYN洪水攻擊。SYN-Flood不會完成TCP三次握手的第三步,也就是不發(fā)送確認連接的信息給服務器。這樣,服務器無法完成第三次握手,但服務器不會立即放棄,服務器會不停的重試并等待一定的時間后放棄這個未完成的連接,這段時間叫做SYN timeout,這段時間大約30秒-2分鐘左右。若是一個用戶在連接時出現(xiàn)問題導致服務器的一個線程等待1分鐘并不是什么大不了的問題,但是若有人用特殊的軟件大量模擬這種情況,那后果就可想而知了。一個服務器若是處理這些大量的半連接信息而消耗大量的系統(tǒng)資源和網絡帶寬,這樣服務器就不會再有空余去處理普通用戶的正常請求(因為客戶的正常請求比率很小)。這樣這個服務器就無法工作了,這種攻擊就叫做:SYN-Flood攻擊。
到目前為止,進行DDoS攻擊的防御還是比較困難的。首先,這種攻擊的特點是它利用了TCP/IP協(xié)議的漏洞,除非你不用TCP/IP,才有可能完全抵御住DDoS攻擊。不過這不等于我們就沒有辦法阻擋DDoS攻擊,我們可以盡力來減少DDoS的攻擊。下面就是一些防御方法:
1.確保服務器的系統(tǒng)文件是最新的版本,并及時更新系統(tǒng)補丁。
2.關閉不必要的服務。
3.限制同時打開的SYN半連接數(shù)目。
4.縮短SYN半連接的time out 時間。
5.正確設置防火墻
6.禁止對主機的非開放服務的訪問
7.限制特定IP地址的訪問
8.啟用防火墻的防DDoS的屬性
9.嚴格限制對外開放的服務器的向外訪問
10.運行端口映射程序禍端口掃描程序,要認真檢查特權端口和非特權端口。
11.認真檢查網絡設備和主機/服務器系統(tǒng)的日志。只要日志出現(xiàn)漏洞或是時間變更,那這臺機器就可能遭到了攻擊。
12.限制在防火墻外與網絡文件共享。這樣會給黑客截取系統(tǒng)文件的機會,主機的信息暴露給黑客,無疑是給了對方入侵的機會。
總結
以上是生活随笔為你收集整理的TCP协议三次握手连接四次握手断开和DOS攻击的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TCP十一种状态
- 下一篇: TCP 通信过程中各步骤的状态