墊顯示器的大學教材,全是知識點啊!!!

墊顯示器的大學教材,全是知識點啊!!!

今天無意間注意到墊顯示器的《TCP/IP協議族》,書皮最上面一行字:世界著名計算機教材精選。這是我大學的教材,我的專業是網絡工程,大學沒能好好學習,慚愧,慚愧。打開隨便翻了一下, 發現很多折角,應該是學期末老師劃重點的時候折的,唉,回憶襲來。
看到這本書,想到的就是之前幾次面試的一個高頻問題:tcp三次握手和四次揮手。趕緊翻到運輸層TCP那一節。映入眼簾的是我沒交的作業。。。


墊顯示器的大學教材,全是知識點啊!!!

萬千思緒啊,懷念啊。。


TCP

TCP使用端口號提供進程到進程的通信。tcp和udp都是屬於運輸層。tcp使用的我們常見的端口號有FTP(20/21)TELNET(23)SMTP(25)DNS(53)HTTP(80)
和UDP不同,TCP是一種面向流的協議。所謂面向流,我理解的就是:UDP報文之間沒有沒有任何關聯,而TCP則允許發送進程以字節流的形式來傳送數據,並且也允許接受進程把數據作為字節流來接收,也就是是說建立了一條連接,這條連接就像一個管道,以此進行全雙工的通信。


墊顯示器的大學教材,全是知識點啊!!!

由於發送進程和接收進程寫入和讀取數據的速度可能不同,TCP會用緩存來存儲數據。所以TCP有兩個緩存,即發送緩存和接收緩存。這些緩存還被TCP用來進行流量控制和差錯控制。

TCP是一個可靠的運輸協議,它使用確認機制來檢查數據是否安全完好地到達。

TCP報文的首部有很多字段,包括源端口地址、目的端口地址、序號、確認號、首部長度、保留、控制、窗口大小、檢驗和、緊急指針、選項
其中控制字段定義了6中不同的控制位或標誌:

  • URG:緊急指針有效
  • ACK:確認是有效的
  • PSH:請求推送
  • RST:連接復位
  • SYN:同步序號
  • FIN:終止連接


TCP連接

TCP是面向連接的,需要經歷三個階段:建立連接、數據傳輸、連接終止


建立連接

TCP建立連接的過程成為三向握手(three-way handshaking)


墊顯示器的大學教材,全是知識點啊!!!

過程:

準備條件:服務器程序告訴服務器的TCP自己已經準備好接收連接。這個請求被稱為被動打開請求。這個打開是針對連接的,而不是端口。這一步就是我們的服務啟動了,開放了端口,等待連接。

  1. 客戶端程序發出請求,稱為主動打開。客戶端發送第一個報文段(SYN報文段),這個報文中只有SYN標誌被置為1,並且客戶端選擇了一個隨機數作為序號,並把這個序號發送給服務端。這裡同時是客戶端在同步它的初始序號。
  2. 服務器發送第二個報文,即SYN+ACK報文段,其中兩個標誌(SYN和ACK)置為1。這個報文有兩個目的。首先,他是另一個方向上的SYN報文段,服務器使用這個報文來同步自己的初始序號。其次,服務器還通過ACK標誌來確認已收到來自客戶端的SYN報文段,同時給出期望從客戶端收到的下一個序號。
  3. 客戶端發送第三個報文。這僅僅是一個ACK報文段。它使用ACK標誌和確認號字段來確認收到了第二個報文。
    這個報文的序號和SYN報文段使用的序號是一樣的,這樣可以節省一個序號。當然在某些實現中,這個報文可以攜帶客戶端的第一個數據塊,這種情況下,第三個報文必須有一個新的序號來表示數據中的第一個字節編號。但是通常第三個報文段是不包含數據的,因而不消耗序號。

SYN洪泛攻擊:
瞭解了上面的連接過程,很多人會想到,如果我向一個服務端發送大量的SYN報文段,是不是可以把連接佔滿,導致服務不可用?
當然,之前我們公司的一些服務使用socket長連接,這些連接通過心跳保持連接,但是由於存在bug,客戶端在關閉連接的時候不會發送確認,導致服務端的連接狀態一直是close wait,無法真正關閉連接。而客戶端卻認為這些連接已經斷開了,再次申請新的連接,導致長時間不重啟服務的話,連接就會被佔滿。這個問題有一段時間一直困擾著我們,不得不定期重啟服務端才能保證業務。
這樣的機制也讓一些不懷好意的人所利用,偽造大量假源IP地址的SYN報文段發送給服務端。服務端認為這是客戶端發來的主動打開請求,於是分配必要的資源,併發送SYN+ACK報文段給對應的源IP,奈何這些IP都是假的,這些報文終將超時,服務端卻已經分配了資源。大量的資源被佔用卻未被利用,服務器最終會因為資源耗盡而不能接收合法客戶的連接請求。這就是

SYN洪泛攻擊
當然也有一些解決的辦法,常見的是使用Cookie,做到推遲資源的分配,直到服務器能夠正式連接請求來自合法的IP地址。


數據傳輸

按照建立連接時雙方已經確定的序號發送數據。

舉例子得有背景!
背景:

  • 建立連接第一個報文,客戶端在SYN時使用的序號(seq)是8000,
  • 建立連接第二個報文,服務器初始seq是15000,ack是8001
  • 建立連接第三個報文,客戶端沒有發送數據塊,即當時seq也是8000,ack是15001。那麼正式開始傳輸數據,客戶端推送數據開始。
墊顯示器的大學教材,全是知識點啊!!!


  1. 客戶端推送數據,seq為8001(序號排著來,建立連接用的是8000),ack:15001,攜帶1000字節數據。控制方面,PSH(推送)標誌為1,代表推送數據。
  2. 服務端收到seq為8001的報文,它瞭解到PSH標誌為1,就會盡快把這些數據交給服務端對應端口上的程序。如果由於資源佔用等原因不能及時把數據交給程序,TCP有緩存機制,可以先緩存下來,回頭再給程序。這裡服務器可以直接發送確認報文,也可能因為忙碌沒能及時發送確認,但是服務端會在超時時間內發送確認。我們這裡假定服務端沒立即返回確認,而是收到了客戶端發來的第二個數據塊。
  3. 客戶端發送第二個報文塊,seq為8001+1000=9001,序號就是數據的offset嘛,很好理解。ack還是15001,因為服務端沒來新的報文嘛。PSH標誌還是1,因為還是推送數據。
  4. 服務端這時候收到兩個報文,客戶端的數據也都傳輸完了。服務端終於有時間給客戶端確認了。這時候它直接發了一個報文,seq為15001,各自按各自的序號來,必定這是告訴對方自己數據的offset
    ,ack為8001+1000+1000=10001,要發確認就一起確認了,沒必要每個來自客戶端的都得單獨確認,記住,序號就是數據的offset。服務端在確認的同時可能還會返回一些數據,就像上面我說的那個socket接口的例子,這時候就會攜帶接口的響應數據。比如攜帶了2000字節的數據。這個報文PSH是不是1,不同的TCP實現不一樣。
  5. 服務端收到報文,已經傳輸完所有的數據,就不需要攜帶數據了,但是得確認收到服務端的報文,seq為10000,不攜帶數據,offset還是之前的10000,ack為15001+2000=17001。


連接終止

參與連接的任何一方都可以關閉連接,一般都是客戶端發起。

墊顯示器的大學教材,全是知識點啊!!!


  1. 客戶進程告訴自己的TCP關閉連接,TCP發送第一個報文,這個報文把FIN位置1,成為FIN報文段。這個FIN報文段,可以是最後一個數據塊,也可以只是一個控制報文段。不攜帶數據的話,只消耗一個序號。seq:x,ack:y
  2. 服務器TCP在收到合格FIN報文段後,把這種情況告訴它的進程,併發送第二個報文--FIN+ACK報文段,確定客戶端的FIN報文,同時也宣佈另一個方向正在關閉連接。當然這個報文也可能帶著來自服務端的最後一個數據塊。如果不攜帶數據,只消耗一個序號。seq:y,ack:x+1
  3. 客戶端TCP發送最後一個報文段,這是一個ACK報文段,確認服務端的FIN報文段。seq:x,ack:y+1


分享到:


相關文章: