1、TCP標誌位
在講TCP三次握手和四次揮手以前,先說一下TCP標誌位,方便後續的理解。前端
簡單來講,TCP標誌位的值表明了當前請求的目的。面試
標誌位一共有6種,分別是:安全
- SYN(synchronous): 發送/同步標誌,用來創建鏈接,和下面的第二個標誌位ACK搭配使用。鏈接開始時,SYN=1,ACK=0,表明鏈接開始可是未得到響應。當鏈接被響應的時候,標誌位會發生變化,其中ACK會置爲1,表明確認收到鏈接請求,此時的標誌位變成了 SYN=1,ACK=1。
- ACK(acknowledgement):確認標誌,表示確認收到請求。
- PSH(push) :表示推送操做,就是指數據包到達接收端之後,不對其進行隊列處理,而是儘量的將數據交給應用程序處理;
- FIN(finish):結束標誌,用於結束一個TCP會話;
- RST(reset):重置復位標誌,用於復位對應的TCP鏈接。
- URG(urgent):緊急標誌,用於保證TCP鏈接不被中斷,而且督促中間層設備儘快處理。
此外,還有兩個序號:服務器
- Sequence number :順序號,發送數據包中的第一個字節的序列號,通常爲小寫的seq。
- Acknowledge number:確認號,響應前面的seq,值爲seq+1,能夠理解爲指望下次發出的序列號爲seq+1;
2、TCP三次握手
1.TCP三次握手概述
所謂三次握手(Three-way Handshake),是指創建一個TCP鏈接時,須要客戶端和服務器總共發送3個包。 三次握手的目的是鏈接服務器指定端口,創建TCP鏈接,並同步鏈接雙方的順序號和確認號並交換 TCP信息cookie
2.圖解TCP三次握手
- 第一次握手:客戶端Client發送位碼爲SYN=1,隨機產生seq=x的數據包到服務器,服務器Server由SYN=1知道,客戶端Client要求創建聯機;
- 第二次握手:服務器Server收到請求後要確認聯機信息,向客戶端Client發送ack=(客戶端Client請求鏈接時的seq)+1,SYN=1,ACK=1,產生seq=y的包,表明接收到鏈接請求而且向客戶端再次確認;
- 第三次握手:客戶端Client收到後檢查ack是否正確,即第一次發送的seq+1,以及位碼ACK是否爲1,表明收到了服務器端發過來的確認信息。以後客戶端Client會再向服務器發送ack=(服務器Server的seq+1),ACK=1,服務器Server收到後確認ack 值與ACK=1,鏈接創建成功。
3.針對TCP鏈接的安全問題:SYN攻擊
- 危害:SYN攻擊屬於DOS攻擊的一種,它利用TCP協議缺陷,經過發送大量的半鏈接請求,耗費CPU和內存資源。SYN攻擊除了能影響主機外,還能夠危害路由器、防火牆等網絡系統,事實上SYN攻擊並無論目標是什麼系統,只要這些系統打開TCP服務就能夠實施。
- 原理:在三次握手過程當中,服務器發送SYN-ACK(確認收到客戶端請求的鏈接)以後,收到客戶端的ACK(第三個包)以前的TCP鏈接稱爲半鏈接(half-open connect).此時服務器處於SYN_RECV(等待客戶端相應)狀態,若是接收到客戶端的ACK,則TCP鏈接成功,若是未接受到,則會重發請求直至成功。SYN攻擊就是 攻擊客戶端 在短期內僞造大量不存在的IP地址,向服務器不斷地發送SYN包,服務器回覆確認包,並等待客戶的確認,因爲源地址是不存在的,服務器須要不斷的重發直 至超時,這些僞造的SYN包將長時間佔用未鏈接隊列,影響了正常的SYN,目標系統運行緩慢,嚴重者引發網絡堵塞甚至系統癱瘓。
- 檢測:檢測SYN攻擊很是的方便,當在服務器上看到大量的半鏈接狀態時,特別是源IP地址是隨機的,基本上能夠判定這是一次SYN攻擊。
- 防範:主要有兩大類,一類是經過防火牆、路由器等過濾網關防禦,另外一類是經過加固TCP/IP協議棧防範.但必須清楚的是,SYN攻擊不能徹底被阻止,咱們所作的是儘量的減輕SYN攻擊的危害,除非將TCP協議從新設計。
過濾網關防禦:網絡
- 網關超時設置
- SYN網關
- SYN代理
加固TCP/IP協議棧:前端工程師
- SynAttackProtect機制
- SYN cookies技術
- 增長最大半鏈接數
- 縮短超時時間
3、圖解TCP四次揮手
- 客戶端Client進程發出鏈接釋放報文,而且中止發送數據。其中FIN=1,順序號爲seq=m(等於前面已經傳送過來的數據的最後一個字節的序號加1),此時,客戶端Client進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即便不攜帶數據,也要消耗一個序號。
- 服務器Server收到鏈接釋放報文,發出確認報文,ACK=1,ack=m+1,而且帶上本身的順序號seq=n,此時,服務器Server就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器通知高層的應用進程,客戶端Client向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端Client已經沒有數據要發送了,可是服務器Server若發送數據,客戶端Client依然要接受。這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
- 客戶端Client收到服務器Server的確認信息後,此時,客戶端Client就進入FIN-WAIT-2(終止等待2)狀態,等待服務器Server發送鏈接釋放報文(在這以前還須要接受服務器Server發送的最後的數據)。
- 服務器Server將最後的數據發送完畢後,就向客戶端發送鏈接釋放報文,FIN=1,ack=m+1,因爲在半關閉狀態,服務器Server極可能又發送了一些數據,假定此時的順序號爲seq=p,此時,服務器Server就進入了LAST-ACK(最後確認)狀態,等待客戶端Client的確認。
- 客戶端Client收到服務器Server的鏈接釋放報文後,必須發出確認,ACK=1,ack=p+1,而本身的順序號是seq=m+1,此時,客戶端Client就進入了TIME-WAIT(時間等待)狀態。注意此時TCP鏈接尚未釋放,必須通過2*MSL(最長報文段壽命)的時間後,當客戶端Client撤銷相應的TCB(保護程序)後,才進入CLOSED狀態。
- 服務器Server只要收到了客戶端Client發出的確認,當即進入CLOSED狀態。一樣,撤銷TCB後,就結束了此次的TCP鏈接。能夠看到,服務器Server結束TCP鏈接的時間要比客戶端Client早一些。
4、常見面試題
1.爲何鏈接的時候是三次握手,關閉的時候倒是四次握手?
答:由於當客戶端發起關閉鏈接的請求時,發出的FIN,僅表明客戶端沒有須要發送給服務器端的數據了。而若是服務器端若是仍有數據須要發送給客戶端的話,響應報文ACK和結束報文FIN則就不能同時發送給客戶端了。此時,服務器端會先返回一個響應報文,表明接收到了客戶端發出的FIN請求,然後在數據傳輸完了以後,再發出FIN請求,表示服務器端已經準備好斷開鏈接了。因此關閉鏈接的時候是四次握手。職業規劃
2.爲何TIME_WAIT狀態須要通過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
答:按照前面所說,當四個報文所有發送完畢後,理論上就算是結束了。可是實際狀況每每不會那麼可靠,好比最後一條報文發出後丟失了,那麼服務器端就不會接收到這一報文,每隔一段時間,服務器端會再次發出FIN報文,此時若是客戶端已經斷開了,那麼就沒法響應服務器的二次請求,這樣服務器會繼續發出FIN報文,從而變成了死循環。因此須要設置一個時間段,若是在這個時間段內接收到了服務器端的再次請求,則表明客戶端發出的ACK報文沒有接收成功。反之,則表明服務器端成功接收響應報文,客戶端進入CLOSED狀態,這次鏈接成功關閉。而這個時間,就規定爲了2MSL,即客戶端發出ACK報文到服務器端的最大時間 + 服務器沒有接收到ACK報文再次發出FIN的最大時間 = 2MSLspa
3.爲何不能用兩次握手進行鏈接?
答:三次握手有兩個重要的功能,一是要雙方作好發送數據的準備工做且雙方都知道彼此已準備好,二要容許雙方就初始順序號進行協商,這個順序號在握手過程當中被髮送和確認。若是改成了兩次握手,是有可能發生死鎖的。在兩次握手的設定下,服務器端在成功接受客戶端的鏈接請求SYN後,向客戶端發出ACK肯定報文時,若是由於網絡緣由客戶端沒有接收到,則會一直等待服務器端的ACK報文,而服務器端則認爲鏈接成功創建了,便開始向客戶端發送數據。可是客戶端由於沒有收到服務器端的ACK報文,且不知道服務器的順序號seq,則會認爲鏈接未成功創建,忽略服務器發出的任何數據。如此客戶端一直等待服務器端的ACK報文,而服務器端由於客戶端一直沒有接收數據,而不斷地重複發送數據,從而形成死鎖。設計
4.若是已經創建了鏈接,可是客戶端忽然出現故障了怎麼辦?
答:TCP還設有一個保活計時器,顯然,客戶端若是出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會從新復位這個計時器,時間一般是設置爲2小時,若兩小時尚未收到客戶端的任何數據,服務器就會發送一個探測報文段,之後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉鏈接。
你好!我是 JHCan333,公衆號:愛生活的前端狗的做者。公衆號專一前端工程師方向,包括但不限於技術提升、職業規劃、生活品質、我的理財等方面,會持續發佈優質文章,從各個方面提高前端開發的幸福感。關注公衆號,咱們一塊兒向前走!