TCP協議是運輸層協議的一種,它提供可靠的數據傳輸服務。TCP鏈接時全雙工通訊,這意味通訊的雙方均可以同時發送和接收數據,這有助於咱們理解下面的握手與揮手過程!html
TCP鏈接做爲HTTP鏈接的前置,是由TCP鏈接來保證上面應用層的HTTP協議的工做的。git
咱們不只要弄清楚流程,還要弄清楚客戶端和服務器的狀態變化狀況!github
0.服務器server運行以後,就會打開端口開啓socket通訊,這時候服務器會監聽外部的TCP鏈接創建的請求。因此其狀態由closed
變成listening
。算法
服務器一直等待着外部的鏈接請求。
1.客戶端client在沒有創建鏈接的狀況下,初始爲closed
狀態。當它主動發出TCP鏈接請求的時候,它發送的報文段首部字節中就包含了TCP鏈接的信息(圖中名詞都是首部字節中的字段K-V數據)。client發送SYN=1, seq=X
:SYN
是指SYNchronized
,即同步字段,當SYN=1
時,則表示這是一個鏈接請求報文段;seq
是指sequence
,即序列號,它用來告訴對方個人報文段的序列號。當客戶端發送出請求報文段後,自身的狀態就變爲了SYN_SENT
,這很好理解,表示已發送請求。瀏覽器
客戶端開始發送TCP鏈接的請求,首先它對服務器發送一個請求報文。客戶端須要知道服務器能不能發送消息和接收消息?
2.服務器server接收到請求報文段後,也會發送ACK=1, ACKnum=1, SYN=1, seq=Y
的報文段。SYN=1
代表了這是一個請求鏈接報文段(很公平對不對?客戶端先請求創建鏈接,服務器後也請求創建鏈接!)ACK=1
,即acknowledge
,這是確認號。當一方主動發送SYN=1的鏈接請求時,若己方贊成創建鏈接,則必須回覆SYN=1和ACK=1的報文段。ACKnum=X+1
表示我想接收的下一個報文段的開始序列號應該是X+1
,這就回復了對方(你下次發送的數據的序列號不要錯,接着上一次的就行了)。服務器發送後,狀態變成SYN_REVN
,即請求鏈接已回覆。緩存
服務器接收到客戶端的請求後,知道了客戶端能發送消息,可是不知道能不能接收個人消息;因此服務器也發送一個請求報文回去,同時告訴客戶端我收到了你的請求。
3.客戶端client接收到服務器的請求報文段後,回覆ACK=1, ACKnum=Y+1
的報文段。ACK=1
表示贊成創建鏈接。客戶端發送後,狀態變成ESTABLISHED
。服務器
客戶端接收到服務器的回覆報文後,知道服務器既能接收消息,也能發送消息。那麼客戶端能夠放心大膽地發送數據了,客戶端發送確認報文給服務器。
5.服務器server接收到回覆報文後,知道客戶端不只能發送消息,也能接收到個人消息。那麼我也能夠放心大膽地發送數據了。服務器接收後,狀態變成ESTABLISHED
。網絡
其實TCP鏈接創建的目的很簡單:客戶端和服務器都要確認對方的狀態,既能發送數據也能接收數據!咱們明白這個目的後就能明白3次握手的具體事宜了。socket
第一點: 是爲了保證上面咱們所講的3次握手的意義,確認雙方的發送和接收狀態。tcp
第二點: 實際狀況的例證說明。這主要是爲了防止已失效的請求報文段忽然又傳送到了服務端而產生鏈接的誤判!
好比:客戶端發送了一個鏈接請求報文段A到服務端,可是在某些網絡節點上長時間滯留了,然後客戶端又超時重發了一個鏈接請求報文段B該服務端,而後正常創建鏈接,數據傳輸完畢,並釋放了鏈接。可是請求報文段A延遲了一段時間後,又到了服務端,這本是一個早已失效的報文段,可是服務端收到後會誤覺得客戶端又發出了一次鏈接請求,因而向客戶端發出確認報文段,並贊成創建鏈接。
那麼問題來了,假如這裏沒有三次握手,這時服務端只要發送了確認,新的鏈接就創建了,但因爲客戶端沒有發出創建鏈接的請求,所以不會理會服務端的確認,也不會向服務端發送數據;而服務端卻認爲新的鏈接已經創建了,並在一直等待客戶端發送數據,這樣服務端就會一直等待下去,直到超出保活計數器的設定值,而將客戶端斷定爲出了問題,纔會關閉這個鏈接。這樣就浪費了不少服務器的資源!而若是採用三次握手,客戶端就不會向服務端發出確認,服務端因爲收不到確認,就知道客戶端沒有要求創建鏈接,從而不創建該鏈接。
引伸,TCP的3次握手缺陷而引發的SYN Flood攻擊!也就是最經典的分佈式拒絕服務攻擊!
SYN- Flood攻擊是當前網絡上最爲常見的Dos/DDoS攻擊,也是最爲經典的拒絕服務攻擊,它就是利用了TCP協議實現上的一個缺陷,經過向網絡服務所在端口發送大量的僞造源地址的攻擊報文,就可能形成目標服務器中的半開鏈接隊列被佔滿,從而阻止其餘合法用戶進行訪問。這種攻擊早在1996年就被發現,但至今仍然顯示出強大的生力。不少操做系統,甚至防火牆、路由器都沒法有效地防護這種攻擊,並且因爲它能夠方便地僞造源地址,追查起來很是困難。
它的數據包特徵一般是,源發送了大量的SYN包,而且缺乏三次握手的最後一步握手ACK回覆。
原理:攻擊者首先僞造地址對服務器發起SYN請求,服務器迴應(SYN+ACK)包,而真實的IP會認爲,我沒有發送請求,不做迴應。服務器沒有收到迴應,這樣的話,服務器不知道(SYN+ACK)是否發送成功,默認狀況下會重試5次(tcp_syn_retries)。這樣的話,對於服務器的內存,帶寬都有很大的消耗。攻擊者若是處於公網,能夠僞造IP的話,對於服務器就很難根據IP來判斷攻擊者,給防禦帶來很大的困難。
Dos/DDos攻擊:
一、Dos是利用本身的計算機攻擊目標,也是一對一的關係,而DDOS是DoS攻擊基礎之上產生的一種新的攻擊方式,利用控制成百上千臺肉雞,組成一個 DDOS攻擊羣,同一時刻對目標發起攻擊。Dos是拒絕服務攻擊,而DDOS是分佈式拒絕服務攻擊;DOS與DDOS都是攻擊目標服務器、網絡服務的一種方式。二、從理論上來講,不管目標服務器、網絡服務的資源多大,也是帶寬、內存、CPU多大,都沒法避免Dos與DDOS攻擊,所以任何資源再大也有一個極限值,好比說,一臺服務器每秒能夠處理1000個數據包,而經過DOS攻擊給這臺服務器發送1001個數據包,這時服務器沒法正常運行,須要給服務器擴容。
三、從技術上來講,DOS和DDOS都是攻擊目標服務器的帶寬和連通性,使得目標服務器的帶寬資源耗盡,沒法正常運行。
一、無效鏈接監視釋放
這種方法不停的監視系統中半開鏈接和不活動鏈接,當達到必定閾值時拆除這些鏈接,釋放系統資源。這種絕對公平的方法每每也會將正常的鏈接的請求也會被釋放掉,「傷敵一千,自損八百」。
二、延緩TCB分配
SYN Flood關鍵是利用了,SYN數據報文一到,系統當即分配TCB資源,從而佔用了系統資源,所以有倆種技術來解決這一問題:
2.一、Syn Cache技術
這種技術在收到SYN時不急着去分配TCB,而是先回應一個ACK報文,並在一個專用的HASH表中(Cache)中保存這種半開鏈接,直到收到正確的ACK報文再去分配TCB。
2.二、Syn Cookie技術
Syn Cookie技術則徹底不使用任何存儲資源,它使用一種特殊的算法生成Sequence Number,這種算法考慮到了對方的IP、端口、己方IP、端口的固定信息,以及對方沒法知道而己方比較固定的一些信息,如MSS、時間等,在收到對方的ACK報文後,從新計算一遍,看其是否與對方迴應報文中的(Sequence Number-1)相同,從而決定是否分配TCB資源。
2.三、使用SYN Proxy防火牆
原理:對試圖穿越的SYN請求進行驗證以後才放行
仍是記住這是全雙工通訊!通常來講都是客戶端發起的鏈接斷開請求,這要結合實際來理解!客戶端在發送完本身的TCP請求後,本身就沒有東西再發送了,因此會請求斷開TCP鏈接,這一步的意義是什麼?客戶端想說:我已經沒有數據要發給你了,我先斷開我到你的發送數據的通道了,可是我仍是能夠接受你的數據的!服務器收到客戶端的斷開請求後,就贊成了,可是服務器的內容可能還沒發送完呢?服務器繼續發送響應內容給客戶端,發送完了以後,服務器也沒東西再發了,因此也發送鏈接斷開請求,這告訴客戶端,我也沒東西發送了,我要關閉鏈接了。客戶端收到後,回覆服務器,我知道了,那我也關了!當服務器接收到客戶端的回覆了,就關閉了TCP鏈接。客戶端若是在2個最大段生命週期沒有收到服務器第3次揮手的確認報文,說明服務器收到了剛纔我發的第4次揮手的報文,也關閉了TCP鏈接。
目前大部分瀏覽器都是使用HTTP1.1協議。
HTTP 1.0規定瀏覽器與服務器只保持短暫的鏈接,瀏覽器的每次請求都須要與服務器創建一個TCP鏈接,服務器完成請求處理後當即斷開TCP鏈接,服務器不跟蹤每一個客戶也不記錄過去的請求。
HTTP 1.1則支持持久鏈接Persistent Connection, 而且默認使用persistent connection。在同一個tcp的鏈接中能夠傳送多個HTTP請求和響應。多個請求和響應能夠重疊,多個請求和響應能夠同時進行。並且加入了更多的請求頭和響應頭(好比HTTP1.0沒有host的字段)。
在1.0時的會話方式:
HTTP 1.1的持續鏈接,也須要增長新的請求頭來幫助實現,例如,Connection請求頭的值爲Keep-Alive時,客戶端通知服務器返回本次請求結果後保持鏈接;Connection請求頭的值爲close時,客戶端通知服務器返回本次請求結果後關閉鏈接。HTTP 1.1還提供了與身份認證、狀態管理和Cache緩存等機制相關的請求頭和響應頭。
請求的流水線(Pipelining)處理,在一個TCP鏈接上能夠傳送多個HTTP請求和響應,減小了創建和關閉鏈接的消耗和延遲。例如:一個包含有許多圖像的網頁文件的多個請求和應答能夠在一個鏈接中傳輸,但每一個單獨的網頁文件的請求和應答仍然須要使用各自的鏈接。 HTTP 1.1還容許客戶端不用等待上一次請求結果返回,就能夠發出下一次請求,但服務器端必須按照接收到客戶端請求的前後順序依次回送響應結果,以保證客戶端可以區分出每次請求的響應內容。
在HTTP1.0中認爲每臺服務器都綁定一個惟一的IP地址,所以,請求消息中的URL並無傳遞主機名(hostname)。但隨着虛擬主機技術的發展,在一臺物理服務器上能夠存在多個虛擬主機(Multi-homed Web Servers),而且它們共享一個IP地址。
HTTP1.1的請求消息和響應消息都應支持Host頭域,且請求消息中若是沒有Host頭域會報告一個錯誤(400 Bad Request)。此外,服務器應該接受以絕對路徑標記的資源請求。
參考連接: 參考文章