TCP/IP 系列文章
網(wǎng)絡(luò)基礎(chǔ)知識(一)
TCP/IP基礎(chǔ)知識(二)
物理層(三)
數(shù)據(jù)鏈路層(四)
IP 協(xié)議(五)
IP 協(xié)議相關(guān)技術(shù)(六)
TCP與UDP(七)
一、傳輸協(xié)議層
1.1 兩種傳輸層協(xié)議 UDP 和 TCP
在 TCP/IP 中能夠?qū)崿F(xiàn)傳輸功能的,并具有代表性的協(xié)議是 TCP 和 UDP 這兩個協(xié)議猎荠。兩者都是流協(xié)議膘掰,你可以把它想象成排水管中的水流尺锚。
TCP 協(xié)議能夠正確處理丟包問題席楚,保證接收方能夠收到數(shù)據(jù)趣惠,與此同時還能夠有效利用網(wǎng)絡(luò)帶寬。然而 TCP 協(xié)議中定義了很多復(fù)雜的規(guī)范鉴扫,因此效率不如 UDP 協(xié)議,不適合實時的視頻和音頻傳輸澈缺。
UDP 協(xié)議是面向無連接的協(xié)議坪创,它只會把數(shù)據(jù)傳遞給接收端,但是不會關(guān)注接收端是否真的收到了數(shù)據(jù)姐赡。但是這種特性反而適合多播莱预,實時的視頻和音頻傳輸。因為個別數(shù)據(jù)包的丟失并不會影響視頻和音頻的整體效果项滑。
1.2.1 UDP 首部
UDP 的首部結(jié)構(gòu)比較簡單依沮,如下圖所示。
UDP 首部包含源端口號枪狂、目標(biāo)端口號危喉、包長度和校驗和。其中包長度表示 UDP 首部的長度和 UDP 數(shù)據(jù)長度之和州疾。另外辜限,校驗和用來判斷數(shù)據(jù)在傳輸過程中是否損壞。計算這個校驗和的時候严蓖,不僅考慮源端口號和目標(biāo)端口號薄嫡,還要考慮 IP 首部中的源 IP 地址氧急,目標(biāo) IP 地址和協(xié)議號(這些又稱為 UDP 偽首部)。這是因為以上五個要素用于識別通信時缺一不可毫深,如果校驗和只考慮端口號吩坝,那么另外三個要素收到破壞時,應(yīng)用就無法得知哑蔫。這有可能導(dǎo)致不該收到包的應(yīng)用收到了包钉寝,該收到包的應(yīng)用反而沒有收到。這個概念同樣適用于即將介紹的 TCP 首部鸳址。
1.2.2 TCP 首部
毫無疑問瘩蚪,TCP 首部的結(jié)構(gòu)要比 UDP 復(fù)雜的多。這也是 TCP 傳輸速度低于 UDP 的重要原因之一稿黍。
序列號:它表示發(fā)送數(shù)據(jù)的位置疹瘦,假設(shè)當(dāng)前的序列號為 s,發(fā)送數(shù)據(jù)長度為 l巡球,則下次發(fā)送數(shù)據(jù)時的序列號為 s + l言沐。在建立連接時通常由計算機生成一個隨機數(shù)作為序列號的初始值。
確認應(yīng)答號:它等于下一次應(yīng)該接收到的數(shù)據(jù)的序列號酣栈。假設(shè)發(fā)送端的序列號為 s险胰,發(fā)送數(shù)據(jù)的長度為 l,那么接收端返回的確認應(yīng)答號也是 s + l矿筝。發(fā)送端接收到這個確認應(yīng)答后起便,可以認為這個位置以前所有的數(shù)據(jù)都已被正常接收。
數(shù)據(jù)偏移:TCP 首部的長度窖维,單位為 4 字節(jié)榆综。如果沒有可選字段,那么這里的值就是 5铸史。表示 TCP 首部的長度為 20 字節(jié)鼻疮。
控制位:改字段長度為 8 比特,分別有 8 個控制標(biāo)志琳轿。依次是 CWR判沟,ECE,URG崭篡,ACK挪哄,PSH,RST媚送,SYN 和 FIN中燥。在后續(xù)的文章中你會陸續(xù)接觸到其中的某些控制位。
窗口大刑临恕:用于表示從應(yīng)答號開始能夠接受多少個 8 位字節(jié)疗涉。如果窗口大小為 0拿霉,可以發(fā)送窗口探測。
緊急指針:盡在 URG 控制位為 1 時有效咱扣。表示緊急數(shù)據(jù)的末尾在 TCP 數(shù)據(jù)部分中的位置绽淘。通常在暫時中斷通信時使用(比如輸入 Ctrl + C)。
1.2 關(guān)于端口號(擴充)
首先要知道闹伪,只有在目標(biāo)地址沪铭、原地址、目標(biāo)端口號偏瓤、源端口號以及協(xié)議類型(TCP 還是 UDP)這五項內(nèi)容都一致的時候才被認為是同一個通信連接杀怠。
服務(wù)端程序在 UNIX 系統(tǒng)中叫做守護進程。如 HTTP 的服務(wù)端程序是 httpd(HTTP 守護進程)厅克,而 sshd (SSH 守護進程)赔退。在 UNIX 中并不需要將這些守護進程逐個啟動,而是啟動一個可以代表他們接收到客服端請求的 inetd(互聯(lián)網(wǎng)進程)服務(wù)程序即可证舟。傳輸協(xié)議 TCP 硕旗、UDP 通過接受數(shù)據(jù)中的目標(biāo)端口號識別處理程序。
二女责、TCP 連接和斷開(三次連接,四次揮手斷開連接)
關(guān)于 TCP 連接和斷開連接的過程漆枚,可以參考下圖。
2.1 關(guān)于三次握手連接
三次握手建立連接流程:
- 1抵知、(客戶端):我要建立連接了墙基。
- 2、(服務(wù)端):我知道你要建立連接了刷喜,我這邊沒有問題碘橘。
- 3、(客戶端):我知道你知道我要建立連接了吱肌,接下來我們就正式開始通信。
為什么要三次握手仰禽,尤其是為何執(zhí)行第三步氮墨?
一般的思路可能會覺得只要兩次握手就可以了,第三步確認似乎是多余的吐葵。其實不然规揪,網(wǎng)絡(luò)是不可靠的,數(shù)據(jù)包是可能丟失的温峭。假設(shè)沒有第三次確認猛铅,客戶端向服務(wù)端發(fā)送了 SYN 請求建立連接。由于延遲凤藏,服務(wù)端沒有及時收到這個包奸忽。于是客戶端重新發(fā)送一個 SYN 包堕伪。假設(shè)服務(wù)端接收到了第二個 SYN 包,建立了通信栗菜,一段時間后通信結(jié)束欠雌,連接被關(guān)閉。這時候最初被發(fā)送的 SYN 包剛剛抵達服務(wù)端疙筹,服務(wù)端又會發(fā)送一次 ACK 確認富俄。由于兩次握手就建立了連接,此時的服務(wù)端就會建立一個新的連接而咆,然而客戶端覺得自己并沒有請求建立連接霍比,所以就不會向服務(wù)端發(fā)送數(shù)據(jù)。從而導(dǎo)致服務(wù)端建立了一個空的連接暴备,白白浪費資源悠瞬。但是在有了第三步確認時情況就不一樣了,服務(wù)端直到收到客戶端的應(yīng)答后才會建立連接馍驯。如果客戶端接受到一個相同的 ACK 包阁危,這時候它會拋棄這個數(shù)據(jù)包,不會和服務(wù)端再次進行汰瘫,因此避免了服務(wù)端建立空的連接狂打。
建立連接過程中, ACK 確認丟失后混弥,TCP 協(xié)議是如何處理趴乡?
按照 TCP 協(xié)議處理丟包的一般方法,服務(wù)端會重新向客戶端發(fā)送數(shù)據(jù)包蝗拿,直至收到 ACK 確認為止晾捏。但實際上這種做法有可能遭到 SYN 泛洪攻擊。所謂的泛洪攻擊哀托,是指發(fā)送方偽造多個 IP 地址惦辛,模擬三次握手的過程。當(dāng)服務(wù)器返回 ACK 后仓手,攻擊方故意不確認胖齐,從而使得服務(wù)器不斷重發(fā) ACK。由于服務(wù)器長時間處于半連接狀態(tài)嗽冒,最后消耗過多的 CPU 和內(nèi)存資源導(dǎo)致死機呀伙。
正確處理方法是服務(wù)端發(fā)送 RST 報文,進入 CLOSE 狀態(tài)添坊。這個 RST 數(shù)據(jù)包的 TCP 首部中剿另,控制位中的 RST 位被設(shè)置為 1。這表示連接信息全部被初始化,原有的 TCP 通信不能繼續(xù)進行雨女⊙柙埽客戶端如果還想重新建立 TCP 連接,就必須重新開始一次握手戚篙。
2.2 關(guān)于四次揮手斷開連接
四次揮手斷開連接過程:
- 1五鲫、(客戶端):我要關(guān)閉連接了。
- 2岔擂、(服務(wù)端):你那邊的連接可以關(guān)閉了位喂。
- 3、(服務(wù)端):我這邊也要關(guān)閉連接了乱灵。
- 4塑崖、(客戶端):你那邊的連接可以關(guān)閉了。
為什么都要執(zhí)行關(guān)閉操作痛倚?
因為連接是雙向的规婆,所以雙方都要主動關(guān)閉自己這一側(cè)的連接。
ACK 丟失怎么辦蝉稳?
在第三步中抒蚜,客戶端收到 FIN 包時,會設(shè)置一個計時器耘戚,等待相當(dāng)長的一段時間嗡髓。如果客戶端返回的 ACK 丟失,那么服務(wù)端還會重發(fā) FIN 并重置計時器收津。假設(shè)在計時器失效前服務(wù)器重發(fā)的 FIN 包沒有到達客戶端饿这,客戶端就會進入 CLOSE 狀態(tài),從而導(dǎo)致服務(wù)端永遠無法收到 ACK 確認撞秋,也就無法關(guān)閉連接长捧。
三、TCP 數(shù)據(jù)包重發(fā)
丟失數(shù)據(jù)包再次重發(fā)的前提是發(fā)送方能夠知道接收方是否成功的接收了消息吻贿。
通過序列號和確認應(yīng)答提高可靠性
TCP 中串结,當(dāng)發(fā)送端的數(shù)據(jù)到達接收端時,接收端會返回一個已收到消息的回執(zhí)通知舅列,該回執(zhí)通知叫做確認應(yīng)答 ACK 奉芦。根據(jù) 上面對 TCP 首都的分析可知,該 ACK 的值和發(fā)送端下次發(fā)送數(shù)據(jù)包在整個發(fā)送數(shù)據(jù)中的序列號相等剧蹂。更明確的說,ACK 除了告訴發(fā)送端已經(jīng)接收到了當(dāng)前數(shù)據(jù)包烦却,還告訴發(fā)送端下次發(fā)送數(shù)據(jù)要從那個位置開始發(fā)宠叼。如下示意圖。
然而,實際情況并不總是那么盡如人意冒冬。比如下面這兩個問題:
1伸蚯、因為網(wǎng)絡(luò)問題,如果數(shù)據(jù)包和 ACK 應(yīng)答都丟失简烤,怎么辦剂邮?
此時,發(fā)送方如果在一段時間內(nèi)沒有收到 ACK横侦,就會重發(fā)數(shù)據(jù)挥萌。
2、由于網(wǎng)絡(luò)延遲的存在枉侧,接收方收到重復(fù)的數(shù)據(jù)包怎么辦引瀑?
通過 TCP 首部中的 SYN 判斷這個數(shù)據(jù)包是否曾經(jīng)接收過。如果已經(jīng)接收過榨馁,就會丟棄這個包憨栽。
TCP 窗口
發(fā)送端在數(shù)據(jù)包發(fā)出后,直至 ACK 確認返回以前翼虫,發(fā)送端都無法發(fā)送數(shù)據(jù)屑柔,顯然是一種浪費,網(wǎng)絡(luò)利用效率和通信性能就越低珍剑。這一問題在 TCP 中通過引入”窗口“的概念得以被解決掸宛。
利用窗口控制提高速度
”窗口大小“表示無需等待確認應(yīng)答ACK返回之前,可以繼續(xù)發(fā)送數(shù)據(jù)包的最大數(shù)量次慢。
窗口的控制和重發(fā)控制
以下示意圖是窗口控制的概念旁涤。
-
在使用窗口控制的過程中,如果是數(shù)據(jù)包已經(jīng)到達對端迫像,但是確認應(yīng)答卻沒有返回該怎么辦劈愚?這就是窗口最擅長處理的問題了。假設(shè)發(fā)送發(fā)收到的確認包中的 ACK 第一次是 1001闻妓,第二次是 4001菌羽。那么我們完全可以相信中間的兩個包是成功被接收的。因為如果有沒接收到的包由缆,接收方是不會增加 ACK 的注祖。而在沒有窗口控制的條件下,發(fā)送方就會重發(fā)第二個和第三個數(shù)據(jù)包均唉。如下圖所示是晨。
ACK丟失的情況 在使用窗口控制的過程中,如果是數(shù)據(jù)包丟失該怎么辦舔箭?接收端主機如果接收到一個自己應(yīng)該接受序號以外的數(shù)據(jù)罩缴,此時只會針對在此之前收到數(shù)據(jù)返回確認應(yīng)答ACK蚊逢。如下圖,當(dāng)1001 - 2000 的數(shù)據(jù)包丟失時箫章,發(fā)送端會一直收到系列號為 1001 的確認應(yīng)發(fā)烙荷,這個確認應(yīng)答就好像接收端一直在提醒發(fā)送端:“我想接收的是從 1001 開始的數(shù)據(jù)”。當(dāng)發(fā)送端如果連續(xù) 3 次收到同樣的確認應(yīng)答檬寂,此時就會針對確認應(yīng)答序列號發(fā)送對應(yīng)的數(shù)據(jù)终抽,這種機制被稱作高速重發(fā)控制。相對于超時重發(fā)機制管理更加有效桶至。如下圖所示昼伴。
補充
TCP 和 UDP 的區(qū)別
- TCP 借助滑動窗口協(xié)議或早期的停止等待協(xié)議,可靠傳輸塞茅。UDP 屬于不可靠傳輸亩码,但是在 UDP 的基礎(chǔ)之上,自己處理可以變?yōu)榭煽總鬏斠笆荩?QQ 的底層通信是借助 UDP描沟。
- TCP 具有流量控制功能。流量控制就是讓發(fā)送方的放松速率不要太快鞭光,要讓接收方來得及接收吏廉。接收方除了告訴發(fā)送方下一個數(shù)據(jù)序號之外,還會讓發(fā)送方調(diào)整發(fā)送窗口大小惰许。
- TCP 具有網(wǎng)絡(luò)擁塞控制功能席覆。 擁塞控制主要是為了防止過多數(shù)據(jù)注入網(wǎng)絡(luò)中,當(dāng)發(fā)送方遲遲不能收到對方的消息時汹买,猜想當(dāng)前網(wǎng)絡(luò)某處發(fā)生了擁塞佩伤。發(fā)送方就會通過慢開始和擁塞避免機制去控制窗口大小。當(dāng)發(fā)生網(wǎng)絡(luò)擁塞時晦毙,從1指數(shù)型增長窗口大小生巡,當(dāng)增到特定的時候,再線性增加滑動窗口见妒;當(dāng)再次發(fā)生擁塞時孤荣,繼續(xù)重復(fù)之前步驟。
HTTP 如何實現(xiàn)可靠傳輸须揣?
參考 TCP 可靠傳輸
HTTPS 中間人怎么攻擊的盐股?
針對SSL的中間人攻擊方式主要有兩類,分別是SSL劫持攻擊和SSL剝離攻擊:
SSL劫持攻擊
SSL劫持攻擊即SSL證書欺騙攻擊耻卡,攻擊者為了獲得HTTPS傳輸?shù)拿魑臄?shù)據(jù)疯汁,需要先將自己接入到客戶端和目標(biāo)網(wǎng)站之間;在傳輸過程中偽造服務(wù)器的證書卵酪,將服務(wù)器的公鑰替換成自己的公鑰涛目,這樣秸谢,中間人就可以得到明文傳輸帶Key1、Key2和Pre-Master-Key霹肝,從而竊取客戶端和服務(wù)端的通信數(shù)據(jù);
但是對于客戶端來說塑煎,如果中間人偽造了證書沫换,在校驗證書過程中會提示證書錯誤,由用戶選擇繼續(xù)操作還是返回最铁,由于大多數(shù)用戶的安全意識不強讯赏,會選擇繼續(xù)操作,此時冷尉,中間人就可以獲取瀏覽器和服務(wù)器之間的通信數(shù)據(jù)
SSL剝離攻擊
這種攻擊方式也需要將攻擊者設(shè)置為中間人漱挎,之后見HTTPS范文替換為HTTP返回給瀏覽器,而中間人和服務(wù)器之間仍然保持HTTPS服務(wù)器雀哨。由于HTTP是明文傳輸?shù)目牧拢灾虚g人可以獲取客戶端和服務(wù)器傳輸數(shù)據(jù)