久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

一文搞定 Wireshark 網(wǎng)絡(luò)數(shù)據(jù)包分析

 wxt208 2021-08-29

為了讓大家更容易「看得見」 TCP,我搭建不少測試環(huán)境,,并且數(shù)據(jù)包抓很多次,,花費(fèi)了不少時間,才抓到比較容易分析的數(shù)據(jù)包,。

接下來丟包,、亂序、超時重傳,、快速重傳、選擇性確認(rèn),、流量控制等等 TCP 的特性,,都能「一覽無云」。

沒錯,,我把 TCP 的'衣服扒光'了,,就為了給大家看的清楚,嘻嘻,。

圖片
提綱

顯形“不可見”的網(wǎng)絡(luò)包

網(wǎng)絡(luò)世界中的數(shù)據(jù)包交互我們?nèi)庋凼强床灰姷?,它們就好像隱形了一樣,我們對著課本學(xué)習(xí)計算機(jī)網(wǎng)絡(luò)的時候就會覺得非常的抽象,,加大了學(xué)習(xí)的難度。

還別說,我自己在大學(xué)的時候,,也是如此。

直到工作后,,認(rèn)識了兩大分析網(wǎng)絡(luò)的利器:tcpdump 和 Wireshark,這兩大利器把我們“看不見”的數(shù)據(jù)包,,呈現(xiàn)在我們眼前,,一目了然。

唉,,當(dāng)初大學(xué)學(xué)習(xí)計網(wǎng)的時候,,要是能知道這兩個工具,就不會學(xué)的一臉懵逼,。

tcpdump 和 Wireshark 有什么區(qū)別,?

tcpdump 和 Wireshark 就是最常用的網(wǎng)絡(luò)抓包和分析工具,更是分析網(wǎng)絡(luò)性能必不可少的利器,。

  • tcpdump 僅支持命令行格式使用,,常用在 Linux 服務(wù)器中抓取和分析網(wǎng)絡(luò)包。

  • Wireshark 除了可以抓包外,,還提供了可視化分析網(wǎng)絡(luò)包的圖形頁面,。

所以,這兩者實(shí)際上是搭配使用的,,先用 tcpdump 命令在 Linux 服務(wù)器上抓包,,接著把抓包的文件拖出到 Windows 電腦后,用 Wireshark 可視化分析,。

當(dāng)然,,如果你是在 Windows 上抓包,只需要用 Wireshark 工具就可以,。

tcpdump 在 Linux 下如何抓包,?

tcpdump 提供了大量的選項(xiàng)以及各式各樣的過濾表達(dá)式,來幫助你抓取指定的數(shù)據(jù)包,,不過不要擔(dān)心,,只需要掌握一些常用選項(xiàng)和過濾表達(dá)式,就可以滿足大部分場景的需要了,。

假設(shè)我們要抓取下面的 ping 的數(shù)據(jù)包:

圖片

要抓取上面的 ping 命令數(shù)據(jù)包,,首先我們要知道 ping 的數(shù)據(jù)包是 icmp 協(xié)議,接著在使用 tcpdump 抓包的時候,,就可以指定只抓 icmp 協(xié)議的數(shù)據(jù)包:

圖片

那么當(dāng) tcpdump 抓取到 icmp 數(shù)據(jù)包后,, 輸出格式如下:

圖片
圖片

從 tcpdump 抓取的 icmp 數(shù)據(jù)包,我們很清楚的看到 icmp echo 的交互過程了,,首先發(fā)送方發(fā)起了 ICMP echo request 請求報文,,接收方收到后回了一個 ICMP echo reply 響應(yīng)報文,之后 seq 是遞增的。

我在這里也幫你整理了一些最常見的用法,,并且繪制成了表格,,你可以參考使用。

首先,,先來看看常用的選項(xiàng)類,,在上面的 ping 例子中,我們用過 -i 選項(xiàng)指定網(wǎng)口,,用過 -nn 選項(xiàng)不對 IP 地址和端口名稱解析,。其他常用的選項(xiàng),如下表格:

圖片
tcpdump 常用選項(xiàng)類

接下來,,我們再來看看常用的過濾表用法,,在上面的 ping 例子中,我們用過的是 icmp and host 183.232.231.174,,表示抓取 icmp 協(xié)議的數(shù)據(jù)包,,以及源地址或目標(biāo)地址為 183.232.231.174 的包。其他常用的過濾選項(xiàng),,我也整理成了下面這個表格,。

圖片
tcpdump 常用過濾表達(dá)式類

說了這么多,你應(yīng)該也發(fā)現(xiàn)了,,tcpdump 雖然功能強(qiáng)大,,但是輸出的格式并不直觀。

所以,,在工作中 tcpdump 只是用來抓取數(shù)據(jù)包,,不用來分析數(shù)據(jù)包,而是把 tcpdump 抓取的數(shù)據(jù)包保存成 pcap 后綴的文件,,接著用 Wireshark 工具進(jìn)行數(shù)據(jù)包分析,。

Wireshark 工具如何分析數(shù)據(jù)包?

Wireshark 除了可以抓包外,,還提供了可視化分析網(wǎng)絡(luò)包的圖形頁面,,同時,還內(nèi)置了一系列的匯總分析工具,。

比如,,拿上面的 ping 例子來說,,我們可以使用下面的命令,,把抓取的數(shù)據(jù)包保存到 ping.pcap 文件

圖片

接著把 ping.pcap 文件拖到電腦,再用 Wireshark 打開它,。打開后,,你就可以看到下面這個界面:

圖片

是吧?在 Wireshark 的頁面里,可以更加直觀的分析數(shù)據(jù)包,,不僅展示各個網(wǎng)絡(luò)包的頭部信息,,還會用不同的顏色來區(qū)分不同的協(xié)議,由于這次抓包只有 ICMP 協(xié)議,,所以只有紫色的條目,。

接著,在網(wǎng)絡(luò)包列表中選擇某一個網(wǎng)絡(luò)包后,,在其下面的網(wǎng)絡(luò)包詳情中,,可以更清楚的看到,這個網(wǎng)絡(luò)包在協(xié)議棧各層的詳細(xì)信息,。比如,,以編號 1 的網(wǎng)絡(luò)包為例子:

圖片
ping 網(wǎng)絡(luò)包

  • 可以在數(shù)據(jù)鏈路層,看到 MAC 包頭信息,,如源 MAC 地址和目標(biāo) MAC 地址等字段,;

  • 可以在 IP 層,看到 IP 包頭信息,,如源 IP 地址和目標(biāo) IP 地址,、TTL、IP 包長度,、協(xié)議等 IP 協(xié)議各個字段的數(shù)值和含義,;

  • 可以在 ICMP 層,看到 ICMP 包頭信息,,比如 Type,、Code 等 ICMP 協(xié)議各個字段的數(shù)值和含義;

Wireshark 用了分層的方式,,展示了各個層的包頭信息,,把“不可見”的數(shù)據(jù)包,清清楚楚的展示了給我們,,還有理由學(xué)不好計算機(jī)網(wǎng)絡(luò)嗎,?是不是相見恨晚

從 ping 的例子中,,我們可以看到網(wǎng)絡(luò)分層就像有序的分工,,每一層都有自己的責(zé)任范圍和信息,上層協(xié)議完成工作后就交給下一層,,最終形成一個完整的網(wǎng)絡(luò)包,。

圖片

解密 TCP 三次握手和四次揮手

既然學(xué)會了 tcpdump 和 Wireshark 兩大網(wǎng)絡(luò)分析利器,那我們快馬加鞭,,接下用它倆抓取和分析 HTTP 協(xié)議網(wǎng)絡(luò)包,,并理解 TCP 三次握手和四次揮手的工作原理,。

本次例子,我們將要訪問的 http://192.168.3.200 服務(wù)端,。在終端用 tcpdump 命令抓取數(shù)據(jù)包:

圖片

接著,,在終端二執(zhí)行下面的 curl 命令:

圖片

最后,回到終端一,,按下 Ctrl+C 停止 tcpdump,,并把得到的 http.pcap 取出到電腦。

使用 Wireshark 打開 http.pcap 后,,你就可以在 Wireshark 中,,看到如下的界面:

圖片
HTTP 網(wǎng)絡(luò)包

我們都知道 HTTP 是基于 TCP 協(xié)議進(jìn)行傳輸?shù)模敲矗?/p>

  • 最開始的 3 個包就是 TCP 三次握手建立連接的包

  • 中間是 HTTP 請求和響應(yīng)的包

  • 而最后的 3 個包則是 TCP 斷開連接的揮手包

Wireshark 可以用時序圖的方式顯示數(shù)據(jù)包交互的過程,,從菜單欄中,,點(diǎn)擊 統(tǒng)計 (Statistics) -> 流量圖 (Flow Graph),然后,,在彈出的界面中的「流量類型」選擇 「TCP Flows」,,你可以更清晰的看到,整個過程中 TCP 流的執(zhí)行過程:

圖片
TCP 流量圖

你可能會好奇,,為什么三次握手連接過程的 Seq 是 0 ,?

實(shí)際上是因?yàn)?Wireshark 工具幫我們做了優(yōu)化,它默認(rèn)顯示的是序列號 seq 是相對值,,而不是真實(shí)值,。

如果你想看到實(shí)際的序列號的值,可以右鍵菜單,, 然后找到「協(xié)議首選項(xiàng)」,,接著找到「Relative Seq」后,把它給取消,,操作如下:

圖片
取消序列號相對值顯示

取消后,,Seq 顯示的就是真實(shí)值了:

圖片
TCP 流量圖

可見,客戶端和服務(wù)端的序列號實(shí)際上是不同的,,序列號是一個隨機(jī)值,。

這其實(shí)跟我們書上看到的 TCP 三次握手和四次揮手很類似,作為對比,,你通??吹降?TCP 三次握手和四次揮手的流程,基本是這樣的:

圖片
TCP 三次握手和四次揮手的流程

為什么抓到的 TCP 揮手是三次,,而不是書上說的四次,?

因?yàn)榉?wù)器端收到客戶端的 FIN 后,服務(wù)器端同時也要關(guān)閉連接,,這樣就可以把 ACKFIN 合并到一起發(fā)送,,節(jié)省了一個包,變成了“三次揮手”,。

而通常情況下,,服務(wù)器端收到客戶端的 FIN 后,很可能還沒發(fā)送完數(shù)據(jù),,所以就會先回復(fù)客戶端一個 ACK 包,,稍等一會兒,完成所有數(shù)據(jù)包的發(fā)送后,,才會發(fā)送 FIN 包,,這也就是四次揮手了。

如下圖,,就是四次揮手的過程:

圖片
四次揮手

TCP 三次握手異常情況實(shí)戰(zhàn)分析

TCP 三次握手的過程相信大家都背的滾瓜爛熟,,那么你有沒有想過這三個異常情況:

  • TCP 第一次握手的 SYN 丟包了,會發(fā)生了什么,?

  • TCP 第二次握手的 SYN,、ACK 丟包了,會發(fā)生什么,?

  • TCP 第三次握手的 ACK 包丟了,,會發(fā)生什么?

有的小伙伴可能說:“很簡單呀,,包丟了就會重傳嘛,。”

那我再繼續(xù)問你:

  • 那會重傳幾次,?

  • 超時重傳的時間 RTO 會如何變化,?

  • 在 Linux 下如何設(shè)置重傳次數(shù)?

  • ….

是不是啞口無言,,無法回答,?

不知道沒關(guān)系,接下里我用三個實(shí)驗(yàn)案例,,帶大家一起探究探究這三種異常,。

實(shí)驗(yàn)場景

本次實(shí)驗(yàn)用了兩臺虛擬機(jī),一臺作為服務(wù)端,,一臺作為客戶端,,它們的關(guān)系如下:

圖片
實(shí)驗(yàn)環(huán)境

  • 客戶端和服務(wù)端都是 CentOs 6.5 Linux,Linux 內(nèi)核版本 2.6.32

  • 服務(wù)端 192.168.12.36,,apache web 服務(wù)

  • 客戶端 192.168.12.37

實(shí)驗(yàn)一:TCP 第一次握手 SYN 丟包

為了模擬 TCP 第一次握手 SYN 丟包的情況,,我是在拔掉服務(wù)器的網(wǎng)線后,立刻在客戶端執(zhí)行 curl 命令:

圖片

其間 tcpdump 抓包的命令如下:

圖片

過了一會,, curl 返回了超時連接的錯誤:

圖片

date 返回的時間,,可以發(fā)現(xiàn)在超時接近 1 分鐘的時間后,,curl 返回了錯誤。

接著,,把 tcp_sys_timeout.pcap 文件用 Wireshark 打開分析,,顯示如下圖:

圖片
SYN 超時重傳五次

從上圖可以發(fā)現(xiàn), 客戶端發(fā)起了 SYN 包后,,一直沒有收到服務(wù)端的 ACK ,,所以一直超時重傳了 5 次,并且每次 RTO 超時時間是不同的:

  • 第一次是在 1 秒超時重傳

  • 第二次是在 3 秒超時重傳

  • 第三次是在 7 秒超時重傳

  • 第四次是在 15 秒超時重傳

  • 第五次是在 31 秒超時重傳

可以發(fā)現(xiàn),,每次超時時間 RTO 是指數(shù)(翻倍)上漲的,,當(dāng)超過最大重傳次數(shù)后,客戶端不再發(fā)送 SYN 包,。

在 Linux 中,,第一次握手的 SYN 超時重傳次數(shù),是如下內(nèi)核參數(shù)指定的:

$ cat /proc/sys/net/ipv4/tcp_syn_retries
5

tcp_syn_retries 默認(rèn)值為 5,,也就是 SYN 最大重傳次數(shù)是 5 次,。

接下來,我們繼續(xù)做實(shí)驗(yàn),,把 tcp_syn_retries 設(shè)置為 2 次:

echo 2 > /proc/sys/net/ipv4/tcp_syn_retries

重傳抓包后,,用 Wireshark 打開分析,顯示如下圖:

圖片
SYN 超時重傳兩次

實(shí)驗(yàn)一的實(shí)驗(yàn)小結(jié)

通過實(shí)驗(yàn)一的實(shí)驗(yàn)結(jié)果,,我們可以得知,,當(dāng)客戶端發(fā)起的 TCP 第一次握手 SYN 包,在超時時間內(nèi)沒收到服務(wù)端的 ACK,,就會在超時重傳 SYN 數(shù)據(jù)包,,每次超時重傳的 RTO 是翻倍上漲的,直到 SYN 包的重傳次數(shù)到達(dá) tcp_syn_retries 值后,,客戶端不再發(fā)送 SYN 包,。

圖片
SYN 超時重傳

實(shí)驗(yàn)二:TCP 第二次握手 SYN、ACK 丟包

為了模擬客戶端收不到服務(wù)端第二次握手 SYN,、ACK 包,,我的做法是在客戶端加上防火墻限制,直接粗暴的把來自服務(wù)端的數(shù)據(jù)都丟棄,,防火墻的配置如下:

圖片

接著,,在客戶端執(zhí)行 curl 命令:

圖片

date 返回的時間前后,可以算出大概 1 分鐘后,,curl 報錯退出了,。

客戶端在這其間抓取的數(shù)據(jù)包,用 Wireshark 打開分析,,顯示的時序圖如下:

圖片

從圖中可以發(fā)現(xiàn):

  • 客戶端發(fā)起 SYN 后,,由于防火墻屏蔽了服務(wù)端的所有數(shù)據(jù)包,,所以 curl 是無法收到服務(wù)端的 SYN、ACK 包,,當(dāng)發(fā)生超時后,,就會重傳 SYN 包

  • 服務(wù)端收到客戶的 SYN 包后,就會回 SYN,、ACK 包,但是客戶端一直沒有回 ACK,,服務(wù)端在超時后,,重傳了 SYN、ACK 包,,接著一會,,客戶端超時重傳的 SYN 包又抵達(dá)了服務(wù)端,服務(wù)端收到后,,超時定時器就重新計時,,然后回了 SYN、ACK 包,,所以相當(dāng)于服務(wù)端的超時定時器只觸發(fā)了一次,,又被重置了。

  • 最后,,客戶端 SYN 超時重傳次數(shù)達(dá)到了 5 次(tcp_syn_retries 默認(rèn)值 5 次),,就不再繼續(xù)發(fā)送 SYN 包了。

所以,,我們可以發(fā)現(xiàn),,當(dāng)?shù)诙挝帐值?SYN、ACK 丟包時,,客戶端會超時重發(fā) SYN 包,,服務(wù)端也會超時重傳 SYN、ACK 包,。

咦,?客戶端設(shè)置了防火墻,屏蔽了服務(wù)端的網(wǎng)絡(luò)包,,為什么 tcpdump 還能抓到服務(wù)端的網(wǎng)絡(luò)包,?

添加 iptables 限制后, tcpdump 是否能抓到包 ,,這要看添加的 iptables 限制條件:

  • 如果添加的是 INPUT 規(guī)則,,則可以抓得到包

  • 如果添加的是 OUTPUT 規(guī)則,則抓不到包

網(wǎng)絡(luò)包進(jìn)入主機(jī)后的順序如下:

  • 進(jìn)來的順序 Wire -> NIC -> tcpdump -> netfilter/iptables

  • 出去的順序 iptables -> tcpdump -> NIC -> Wire

tcp_syn_retries 是限制 SYN 重傳次數(shù),,那第二次握手 SYN,、ACK 限制最大重傳次數(shù)是多少,?

TCP 第二次握手 SYN、ACK 包的最大重傳次數(shù)是通過 tcp_synack_retries 內(nèi)核參數(shù)限制的,,其默認(rèn)值如下:

$ cat /proc/sys/net/ipv4/tcp_synack_retries
5

是的,,TCP 第二次握手 SYN、ACK 包的最大重傳次數(shù)默認(rèn)值是 5 次,。

為了驗(yàn)證 SYN,、ACK 包最大重傳次數(shù)是 5 次,我們繼續(xù)做下實(shí)驗(yàn),,我們先把客戶端的 tcp_syn_retries 設(shè)置為 1,,表示客戶端 SYN 最大超時次數(shù)是 1 次,目的是為了防止多次重傳 SYN,,把服務(wù)端 SYN,、ACK 超時定時器重置。

接著,,還是如上面的步驟:

  1. 客戶端配置防火墻屏蔽服務(wù)端的數(shù)據(jù)包

  2. 客戶端 tcpdump 抓取 curl 執(zhí)行時的數(shù)據(jù)包

把抓取的數(shù)據(jù)包,,用 Wireshark 打開分析,顯示的時序圖如下:

圖片

從上圖,,我們可以分析出:

  • 客戶端的 SYN 只超時重傳了 1 次,,因?yàn)?tcp_syn_retries 值為 1

  • 服務(wù)端應(yīng)答了客戶端超時重傳的 SYN 包后,由于一直收不到客戶端的 ACK 包,,所以服務(wù)端一直在超時重傳 SYN,、ACK 包,每次的 RTO 也是指數(shù)上漲的,,一共超時重傳了 5 次,,因?yàn)?tcp_synack_retries 值為 5

接著,我把 tcp_synack_retries 設(shè)置為 2,,tcp_syn_retries 依然設(shè)置為 1:

echo 2 > /proc/sys/net/ipv4/tcp_synack_retries
echo 1 > /proc/sys/net/ipv4/tcp_syn_retries

依然保持一樣的實(shí)驗(yàn)步驟進(jìn)行操作,,接著把抓取的數(shù)據(jù)包,用 Wireshark 打開分析,,顯示的時序圖如下:

圖片

可見:

  • 客戶端的 SYN 包只超時重傳了 1 次,,符合 tcp_syn_retries 設(shè)置的值;

  • 服務(wù)端的 SYN,、ACK 超時重傳了 2 次,,符合 tcp_synack_retries 設(shè)置的值

實(shí)驗(yàn)二的實(shí)驗(yàn)小結(jié)

通過實(shí)驗(yàn)二的實(shí)驗(yàn)結(jié)果,我們可以得知,,當(dāng) TCP 第二次握手 SYN,、ACK 包丟了后,客戶端 SYN 包會發(fā)生超時重傳,服務(wù)端 SYN,、ACK 也會發(fā)生超時重傳,。

客戶端 SYN 包超時重傳的最大次數(shù),是由 tcp_syn_retries 決定的,,默認(rèn)值是 5 次,;服務(wù)端 SYN、ACK 包時重傳的最大次數(shù),,是由 tcp_synack_retries 決定的,,默認(rèn)值是 5 次。

實(shí)驗(yàn)三:TCP 第三次握手 ACK 丟包

為了模擬 TCP 第三次握手 ACK 包丟,,我的實(shí)驗(yàn)方法是在服務(wù)端配置防火墻,,屏蔽客戶端 TCP 報文中標(biāo)志位是 ACK 的包,也就是當(dāng)服務(wù)端收到客戶端的 TCP ACK 的報文時就會丟棄,,iptables 配置命令如下:

圖片

接著,,在客戶端執(zhí)行如下 tcpdump 命令:

圖片

然后,,客戶端向服務(wù)端發(fā)起 telnet,,因?yàn)?telnet 命令是會發(fā)起 TCP 連接,所以用此命令做測試:

圖片

此時,,由于服務(wù)端收不到第三次握手的 ACK 包,,所以一直處于 SYN_RECV 狀態(tài):

圖片

而客戶端是已完成 TCP 連接建立,處于 ESTABLISHED 狀態(tài):

圖片

過了 1 分鐘后,,觀察發(fā)現(xiàn)服務(wù)端的 TCP 連接不見了:

圖片

過了 30 分別,,客戶端依然還是處于 ESTABLISHED 狀態(tài):

圖片

接著,在剛才客戶端建立的 telnet 會話,,輸入 123456 字符,,進(jìn)行發(fā)送:

圖片

持續(xù)「好長」一段時間,客戶端的 telnet 才斷開連接:

圖片

以上就是本次實(shí)驗(yàn)三的現(xiàn)象,,這里存在兩個疑點(diǎn):

  • 為什么服務(wù)端原本處于 SYN_RECV 狀態(tài)的連接,,過 1 分鐘后就消失了?

  • 為什么客戶端 telnet 輸入 123456 字符后,,過了好長一段時間,,telnet 才斷開連接?

不著急,,我們把剛抓的數(shù)據(jù)包,,用 Wireshark 打開分析,顯示的時序圖如下:

圖片

上圖的流程:

  • 客戶端發(fā)送 SYN 包給服務(wù)端,,服務(wù)端收到后,,回了個 SYN、ACK 包給客戶端,,此時服務(wù)端的 TCP 連接處于 SYN_RECV 狀態(tài),;

  • 客戶端收到服務(wù)端的  SYN,、ACK 包后,給服務(wù)端回了個 ACK 包,,此時客戶端的 TCP 連接處于 ESTABLISHED 狀態(tài),;

  • 由于服務(wù)端配置了防火墻,屏蔽了客戶端的 ACK 包,,所以服務(wù)端一直處于 SYN_RECV 狀態(tài),,沒有進(jìn)入  ESTABLISHED 狀態(tài),tcpdump 之所以能抓到客戶端的 ACK 包,,是因?yàn)閿?shù)據(jù)包進(jìn)入系統(tǒng)的順序是先進(jìn)入 tcpudmp,,后經(jīng)過 iptables;

  • 接著,,服務(wù)端超時重傳了 SYN,、ACK 包,重傳了 5 次后,,也就是超過 tcp_synack_retries 的值(默認(rèn)值是 5),,然后就沒有繼續(xù)重傳了,此時服務(wù)端的 TCP 連接主動中止了,,所以剛才處于 SYN_RECV 狀態(tài)的 TCP 連接斷開了,,而客戶端依然處于ESTABLISHED 狀態(tài);

  • 雖然服務(wù)端 TCP 斷開了,,但過了一段時間,,發(fā)現(xiàn)客戶端依然處于ESTABLISHED 狀態(tài),于是就在客戶端的 telnet 會話輸入了 123456 字符,;

  • 此時由于服務(wù)端已經(jīng)斷開連接,,客戶端發(fā)送的數(shù)據(jù)報文,一直在超時重傳,,每一次重傳,,RTO 的值是指數(shù)增長的,所以持續(xù)了好長一段時間,,客戶端的 telnet 才報錯退出了,,此時共重傳了 15 次。

通過這一波分析,,剛才的兩個疑點(diǎn)已經(jīng)解除了:

  • 服務(wù)端在重傳 SYN,、ACK 包時,超過了最大重傳次數(shù) tcp_synack_retries,,于是服務(wù)端的 TCP 連接主動斷開了,。

  • 客戶端向服務(wù)端發(fā)送數(shù)據(jù)包時,由于服務(wù)端的 TCP 連接已經(jīng)退出了,所以數(shù)據(jù)包一直在超時重傳,,共重傳了 15 次,, telnet 就 斷開了連接。

TCP 第一次握手的 SYN 包超時重傳最大次數(shù)是由 tcp_syn_retries 指定,,TCP 第二次握手的 SYN,、ACK 包超時重傳最大次數(shù)是由 tcp_synack_retries 指定,那 TCP 建立連接后的數(shù)據(jù)包最大超時重傳次數(shù)是由什么參數(shù)指定呢,?

TCP 建立連接后的數(shù)據(jù)包傳輸,,最大超時重傳次數(shù)是由 tcp_retries2 指定,默認(rèn)值是 15 次,,如下:

$ cat /proc/sys/net/ipv4/tcp_retries2
15

如果 15 次重傳都做完了,,TCP 就會告訴應(yīng)用層說:“搞不定了,包怎么都傳不過去,!”

那如果客戶端不發(fā)送數(shù)據(jù),,什么時候才會斷開處于 ESTABLISHED 狀態(tài)的連接?

這里就需要提到 TCP 的 ?;顧C(jī)制,。這個機(jī)制的原理是這樣的:

定義一個時間段,在這個時間段內(nèi),,如果沒有任何連接相關(guān)的活動,,TCP ?;顧C(jī)制會開始作用,,每隔一個時間間隔,發(fā)送一個「探測報文」,,該探測報文包含的數(shù)據(jù)非常少,,如果連續(xù)幾個探測報文都沒有得到響應(yīng),則認(rèn)為當(dāng)前的 TCP 連接已經(jīng)死亡,,系統(tǒng)內(nèi)核將錯誤信息通知給上層應(yīng)用程序,。

在 Linux 內(nèi)核可以有對應(yīng)的參數(shù)可以設(shè)置保活時間,、?;钐綔y的次數(shù)、?;钐綔y的時間間隔,,以下都為默認(rèn)值:

net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75  
net.ipv4.tcp_keepalive_probes=9
  • tcp_keepalive_time=7200:表示保活時間是 7200 秒(2小時),,也就 2 小時內(nèi)如果沒有任何連接相關(guān)的活動,,則會啟動保活機(jī)制

  • tcp_keepalive_intvl=75:表示每次檢測間隔 75 秒;

  • tcp_keepalive_probes=9:表示檢測 9 次無響應(yīng),,認(rèn)為對方是不可達(dá)的,,從而中斷本次的連接。

也就是說在 Linux 系統(tǒng)中,,最少需要經(jīng)過 2 小時 11 分 15 秒才可以發(fā)現(xiàn)一個「死亡」連接,。

圖片

這個時間是有點(diǎn)長的,所以如果我抓包足夠久,,或許能抓到探測報文,。

實(shí)驗(yàn)三的實(shí)驗(yàn)小結(jié)

在建立 TCP 連接時,如果第三次握手的 ACK,,服務(wù)端無法收到,,則服務(wù)端就會短暫處于 SYN_RECV 狀態(tài),而客戶端會處于 ESTABLISHED 狀態(tài),。

由于服務(wù)端一直收不到 TCP 第三次握手的 ACK,,則會一直重傳 SYN、ACK 包,,直到重傳次數(shù)超過 tcp_synack_retries 值(默認(rèn)值 5 次)后,,服務(wù)端就會斷開 TCP 連接。

而客戶端則會有兩種情況:

  • 如果客戶端沒發(fā)送數(shù)據(jù)包,,一直處于 ESTABLISHED 狀態(tài),,然后經(jīng)過 2 小時 11 分 15 秒才可以發(fā)現(xiàn)一個「死亡」連接,于是客戶端連接就會斷開連接,。

  • 如果客戶端發(fā)送了數(shù)據(jù)包,,一直沒有收到服務(wù)端對該數(shù)據(jù)包的確認(rèn)報文,則會一直重傳該數(shù)據(jù)包,,直到重傳次數(shù)超過 tcp_retries2 值(默認(rèn)值 15 次)后,,客戶端就會斷開 TCP 連接。


TCP 快速建立連接

客戶端在向服務(wù)端發(fā)起 HTTP GET 請求時,,一個完整的交互過程,,需要 2.5 個 RTT 的時延。

由于第三次握手是可以攜帶數(shù)據(jù)的,,這時如果在第三次握手發(fā)起 HTTP GET 請求,,需要 2 個 RTT 的時延。

但是在下一次(不是同個 TCP 連接的下一次)發(fā)起 HTTP GET 請求時,,經(jīng)歷的 RTT 也是一樣,,如下圖:

圖片
常規(guī) HTTP 請求

在 Linux 3.7 內(nèi)核版本中,提供了 TCP Fast Open 功能,,這個功能可以減少 TCP 連接建立的時延,。

圖片
常規(guī) HTTP 請求 與 Fast  Open HTTP 請求

  • 在第一次建立連接的時候,,服務(wù)端在第二次握手產(chǎn)生一個 Cookie (已加密)并通過 SYN、ACK 包一起發(fā)給客戶端,,于是客戶端就會緩存這個 Cookie,,所以第一次發(fā)起 HTTP Get 請求的時候,還是需要 2 個 RTT 的時延,;

  • 在下次請求的時候,,客戶端在 SYN 包帶上 Cookie 發(fā)給服務(wù)端,就提前可以跳過三次握手的過程,,因?yàn)?Cookie 中維護(hù)了一些信息,,服務(wù)端可以從 Cookie 獲取 TCP 相關(guān)的信息,這時發(fā)起的 HTTP GET 請求就只需要 1 個 RTT 的時延,;

注:客戶端在請求并存儲了 Fast Open Cookie 之后,,可以不斷重復(fù) TCP Fast Open 直至服務(wù)器認(rèn)為 Cookie 無效(通常為過期)

在 Linux 上如何打開 Fast Open 功能?

可以通過設(shè)置 net.ipv4.tcp_fastopn 內(nèi)核參數(shù),,來打開 Fast Open 功能,。

net.ipv4.tcp_fastopn 各個值的意義:

  • 0 關(guān)閉

  • 1 作為客戶端使用 Fast Open 功能

  • 2 作為服務(wù)端使用 Fast Open 功能

  • 3 無論作為客戶端還是服務(wù)器,都可以使用 Fast Open 功能

TCP Fast Open 抓包分析

在下圖,,數(shù)據(jù)包 7 號,,客戶端發(fā)起了第二次 TCP 連接時,SYN 包會攜帶 Cooike,,并且有長度為 5 的數(shù)據(jù),。

服務(wù)端收到后,校驗(yàn) Cooike 合法,,于是就回了 SYN,、ACK 包,并且確認(rèn)應(yīng)答收到了客戶端的數(shù)據(jù)包,,ACK = 5 + 1 = 6

圖片
TCP Fast Open 抓包分析

TCP 重復(fù)確認(rèn)和快速重傳

當(dāng)接收方收到亂序數(shù)據(jù)包時,,會發(fā)送重復(fù)的 ACK,,以使告知發(fā)送方要重發(fā)該數(shù)據(jù)包,,當(dāng)發(fā)送方收到 3 個重復(fù) ACK 時,就會觸發(fā)快速重傳,,立刻重發(fā)丟失數(shù)據(jù)包,。

圖片
快速重傳機(jī)制

TCP 重復(fù)確認(rèn)和快速重傳的一個案例,用 Wireshark 分析,,顯示如下:

圖片

  • 數(shù)據(jù)包 1 期望的下一個數(shù)據(jù)包 Seq 是 1,,但是數(shù)據(jù)包 2 發(fā)送的 Seq 卻是 10945,說明收到的是亂序數(shù)據(jù)包,,于是回了數(shù)據(jù)包 3 ,,還是同樣的 Seq = 1,,Ack = 1,這表明是重復(fù)的 ACK,;

  • 數(shù)據(jù)包 4 和 6 依然是亂序的數(shù)據(jù)包,,于是依然回了重復(fù)的 ACK;

  • 當(dāng)對方收到三次重復(fù)的 ACK 后,,于是就快速重傳了 Seq = 1 ,、Len = 1368 的數(shù)據(jù)包 8;

  • 當(dāng)收到重傳的數(shù)據(jù)包后,,發(fā)現(xiàn) Seq = 1 是期望的數(shù)據(jù)包,,于是就發(fā)送了確認(rèn)報文 ACK;

注意:快速重傳和重復(fù) ACK 標(biāo)記信息是 Wireshark 的功能,,非數(shù)據(jù)包本身的信息,。

以上案例在 TCP 三次握手時協(xié)商開啟了選擇性確認(rèn) SACK,因此一旦數(shù)據(jù)包丟失并收到重復(fù) ACK ,,即使在丟失數(shù)據(jù)包之后還成功接收了其他數(shù)據(jù)包,,也只需要重傳丟失的數(shù)據(jù)包。如果不啟用 SACK,,就必須重傳丟失包之后的每個數(shù)據(jù)包,。

如果要支持 SACK,必須雙方都要支持,。在 Linux 下,,可以通過 net.ipv4.tcp_sack 參數(shù)打開這個功能(Linux 2.4 后默認(rèn)打開)。


TCP 流量控制

TCP 為了防止發(fā)送方無腦的發(fā)送數(shù)據(jù),,導(dǎo)致接收方緩沖區(qū)被填滿,,所以就有了滑動窗口的機(jī)制,它可利用接收方的接收窗口來控制發(fā)送方要發(fā)送的數(shù)據(jù)量,,也就是流量控制,。

接收窗口是由接收方指定的值,存儲在 TCP 頭部中,,它可以告訴發(fā)送方自己的 TCP 緩沖空間區(qū)大小,,這個緩沖區(qū)是給應(yīng)用程序讀取數(shù)據(jù)的空間:

  • 如果應(yīng)用程序讀取了緩沖區(qū)的數(shù)據(jù),那么緩沖空間區(qū)的就會把被讀取的數(shù)據(jù)移除

  • 如果應(yīng)用程序沒有讀取數(shù)據(jù),,則數(shù)據(jù)會一直滯留在緩沖區(qū),。

接收窗口的大小,是在 TCP 三次握手中協(xié)商好的,,后續(xù)數(shù)據(jù)傳輸時,,接收方發(fā)送確認(rèn)應(yīng)答 ACK 報文時,會攜帶當(dāng)前的接收窗口的大小,,以此來告知發(fā)送方,。

假設(shè)接收方接收到數(shù)據(jù)后,,應(yīng)用層能很快的從緩沖區(qū)里讀取數(shù)據(jù),那么窗口大小會一直保持不變,,過程如下:

圖片
理想狀態(tài)下的窗口變化

但是現(xiàn)實(shí)中服務(wù)器會出現(xiàn)繁忙的情況,,當(dāng)應(yīng)用程序讀取速度慢,那么緩存空間會慢慢被占滿,,于是為了保證發(fā)送方發(fā)送的數(shù)據(jù)不會超過緩沖區(qū)大小,,則服務(wù)器會調(diào)整窗口大小的值,接著通過 ACK 報文通知給對方,,告知現(xiàn)在的接收窗口大小,,從而控制發(fā)送方發(fā)送的數(shù)據(jù)大小。

圖片
服務(wù)端繁忙狀態(tài)下的窗口變化

零窗口通知與窗口探測

假設(shè)接收方處理數(shù)據(jù)的速度跟不上接收數(shù)據(jù)的速度,,緩存就會被占滿,,從而導(dǎo)致接收窗口為 0,當(dāng)發(fā)送方接收到零窗口通知時,,就會停止發(fā)送數(shù)據(jù),。

如下圖,可以接收方的窗口大小在不斷的收縮至 0:

圖片
窗口大小在收縮

接著,,發(fā)送方會定時發(fā)送窗口大小探測報文,,以便及時知道接收方窗口大小的變化。

以下圖 Wireshark 分析圖作為例子說明:

圖片
零窗口 與 窗口探測

  • 發(fā)送方發(fā)送了數(shù)據(jù)包 1 給接收方,,接收方收到后,,由于緩沖區(qū)被占滿,回了個零窗口通知,;

  • 發(fā)送方收到零窗口通知后,,就不再發(fā)送數(shù)據(jù)了,直到過了 3.4 秒后,,發(fā)送了一個 TCP Keep-Alive 報文,,也就是窗口大小探測報文;

  • 當(dāng)接收方收到窗口探測報文后,,就立馬回一個窗口通知,,但是窗口大小還是 0;

  • 發(fā)送方發(fā)現(xiàn)窗口還是 0,,于是繼續(xù)等待了 6.8(翻倍) 秒后,,又發(fā)送了窗口探測報文,接收方依然還是回了窗口為 0 的通知,;

  • 發(fā)送方發(fā)現(xiàn)窗口還是 0,于是繼續(xù)等待了 13.5(翻倍) 秒后,,又發(fā)送了窗口探測報文,,接收方依然還是回了窗口為 0 的通知,;

可以發(fā)現(xiàn),這些窗口探測報文以 3.4s,、6.5s,、13.5s 的間隔出現(xiàn),說明超時時間會翻倍遞增,。

這連接暫停了 25s,,想象一下你在打王者的時候,25s 的延遲你還能上王者嗎,?

發(fā)送窗口的分析

在 Wireshark 看到的 Windows size 也就是 ' win = ',,這個值表示發(fā)送窗口嗎?

這不是發(fā)送窗口,,而是在向?qū)Ψ铰暶髯约旱慕邮沾翱凇?/p>

你可能會好奇,,抓包文件里有「Window size scaling factor」,它其實(shí)是算出實(shí)際窗口大小的乘法因子,,「Windos size value」實(shí)際上并不是真實(shí)的窗口大小,,真實(shí)窗口大小的計算公式如下:

「Windos size value」 * 「Window size scaling factor」 = 「Caculated window size 」

對應(yīng)的下圖案例,也就是 32 * 2048 = 65536,。

圖片

實(shí)際上是 Caculated window size 的值是 Wireshark 工具幫我們算好的,,Window size scaling factor 和 Windos size value 的值是在 TCP 頭部中,其中 Window size scaling factor 是在三次握手過程中確定的,,如果你抓包的數(shù)據(jù)沒有 TCP 三次握手,,那可能就無法算出真實(shí)的窗口大小的值,如下圖:

圖片

如何在包里看出發(fā)送窗口的大???

很遺憾,沒有簡單的辦法,,發(fā)送窗口雖然是由接收窗口決定,,但是它又可以被網(wǎng)絡(luò)因素影響,也就是擁塞窗口,,實(shí)際上發(fā)送窗口是值是 min(擁塞窗口,,接收窗口)。

發(fā)送窗口和 MSS 有什么關(guān)系,?

發(fā)送窗口決定了一口氣能發(fā)多少字節(jié),,而 MSS 決定了這些字節(jié)要分多少包才能發(fā)完。

舉個例子,,如果發(fā)送窗口為 16000 字節(jié)的情況下,,如果 MSS 是 1000 字節(jié),那就需要發(fā)送 1600/1000 = 16 個包,。

發(fā)送方在一個窗口發(fā)出 n 個包,,是不是需要 n 個 ACK 確認(rèn)報文,?

不一定,因?yàn)?TCP 有累計確認(rèn)機(jī)制,,所以當(dāng)收到多個數(shù)據(jù)包時,,只需要應(yīng)答最后一個數(shù)據(jù)包的 ACK 報文就可以了。


TCP 延遲確認(rèn)與 Nagle 算法

當(dāng)我們 TCP 報文的承載的數(shù)據(jù)非常小的時候,,例如幾個字節(jié),,那么整個網(wǎng)絡(luò)的效率是很低的,因?yàn)槊總€ TCP 報文中都有會 20 個字節(jié)的 TCP 頭部,,也會有 20 個字節(jié)的 IP 頭部,,而數(shù)據(jù)只有幾個字節(jié),所以在整個報文中有效數(shù)據(jù)占有的比重就會非常低,。

這就好像快遞員開著大貨車送一個小包裹一樣浪費(fèi),。

那么就出現(xiàn)了常見的兩種策略,來減少小報文的傳輸,,分別是:

  • Nagle 算法

  • 延遲確認(rèn)

Nagle 算法是如何避免大量 TCP 小數(shù)據(jù)報文的傳輸,?

Nagle 算法做了一些策略來避免過多的小數(shù)據(jù)報文發(fā)送,這可提高傳輸效率,。

Nagle 算法的策略:

  • 沒有已發(fā)送未確認(rèn)報文時,,立刻發(fā)送數(shù)據(jù)。

  • 存在未確認(rèn)報文時,,直到「沒有已發(fā)送未確認(rèn)報文」或「數(shù)據(jù)長度達(dá)到 MSS 大小」時,,再發(fā)送數(shù)據(jù)。

只要沒滿足上面條件中的一條,,發(fā)送方一直在囤積數(shù)據(jù),,直到滿足上面的發(fā)送條件。

圖片
禁用 Nagle 算法 與 啟用 Nagle 算法

上圖右側(cè)啟用了 Nagle 算法,,它的發(fā)送數(shù)據(jù)的過程:

  • 一開始由于沒有已發(fā)送未確認(rèn)的報文,,所以就立刻發(fā)了 H 字符;

  • 接著,,在還沒收到對 H 字符的確認(rèn)報文時,,發(fā)送方就一直在囤積數(shù)據(jù),直到收到了確認(rèn)報文后,,此時就沒有已發(fā)送未確認(rèn)的報文,,于是就把囤積后的 ELL 字符一起發(fā)給了接收方;

  • 待收到對 ELL 字符的確認(rèn)報文后,,于是把最后一個 O 字符發(fā)送出去

可以看出,,Nagle 算法一定會有一個小報文,也就是在最開始的時候。

另外,,Nagle 算法默認(rèn)是打開的,,如果對于一些需要小數(shù)據(jù)包交互的場景的程序,,比如,,telnet 或 ssh 這樣的交互性比較強(qiáng)的程序,則需要關(guān)閉 Nagle 算法,。

可以在 Socket 設(shè)置 TCP_NODELAY 選項(xiàng)來關(guān)閉這個算法(關(guān)閉 Nagle 算法沒有全局參數(shù),,需要根據(jù)每個應(yīng)用自己的特點(diǎn)來關(guān)閉)。

圖片
關(guān)閉 Nagle 算法

那延遲確認(rèn)又是什么,?

事實(shí)上當(dāng)沒有攜帶數(shù)據(jù)的 ACK,,他的網(wǎng)絡(luò)效率也是很低的,因?yàn)樗灿?40 個字節(jié)的 IP 頭 和 TCP 頭,,但沒有攜帶數(shù)據(jù),。

為了解決 ACK 傳輸效率低問題,所以就衍生出了 TCP 延遲確認(rèn),。

TCP 延遲確認(rèn)的策略:

  • 當(dāng)有響應(yīng)數(shù)據(jù)要發(fā)送時,,ACK 會隨著響應(yīng)數(shù)據(jù)一起立刻發(fā)送給對方

  • 當(dāng)沒有響應(yīng)數(shù)據(jù)要發(fā)送時,ACK 將會延遲一段時間,,以等待是否有響應(yīng)數(shù)據(jù)可以一起發(fā)送

  • 如果在延遲等待發(fā)送 ACK 期間,,對方的第二個數(shù)據(jù)報文又到達(dá)了,這時就會立刻發(fā)送 ACK

圖片
TCP 延遲確認(rèn)

延遲等待的時間是在 Linux 內(nèi)核中的定義的,,如下圖:

圖片

關(guān)鍵就需要 HZ 這個數(shù)值大小,,HZ 是跟系統(tǒng)的時鐘頻率有關(guān),每個操作系統(tǒng)都不一樣,,在我的 Linux 系統(tǒng)中 HZ 大小是 1000,,如下圖:

圖片

知道了 HZ 的大小,那么就可以算出:

  • 最大延遲確認(rèn)時間是 200 ms (1000/5)

  • 最短延遲確認(rèn)時間是 40 ms (1000/25)

TCP 延遲確認(rèn)可以在 Socket 設(shè)置 TCP_QUICKACK 選項(xiàng)來關(guān)閉這個算法,。

圖片
關(guān)閉 TCP 延遲確認(rèn)

延遲確認(rèn) 和 Nagle 算法混合使用時,,會產(chǎn)生新的問題

當(dāng) TCP 延遲確認(rèn) 和 Nagle 算法混合使用時,會導(dǎo)致時耗增長,,如下圖:

圖片
TCP 延遲確認(rèn) 和 Nagle 算法混合使用

發(fā)送方使用了 Nagle 算法,,接收方使用了 TCP 延遲確認(rèn)會發(fā)生如下的過程:

  • 發(fā)送方先發(fā)出一個小報文,接收方收到后,,由于延遲確認(rèn)機(jī)制,,自己又沒有要發(fā)送的數(shù)據(jù),只能干等著發(fā)送方的下一個報文到達(dá),;

  • 而發(fā)送方由于 Nagle 算法機(jī)制,,在未收到第一個報文的確認(rèn)前,是不會發(fā)送后續(xù)的數(shù)據(jù);

  • 所以接收方只能等待最大時間 200 ms 后,,才回 ACK 報文,,發(fā)送方收到第一個報文的確認(rèn)報文后,也才可以發(fā)送后續(xù)的數(shù)據(jù),。

很明顯,,這兩個同時使用會造成額外的時延,這就會使得網(wǎng)絡(luò)'很慢'的感覺,。

要解決這個問題,,只有兩個辦法:

  • 要么發(fā)送方關(guān)閉 Nagle 算法

  • 要么接收方關(guān)閉 TCP 延遲確認(rèn)


巨人的肩膀

[1] Wireshark網(wǎng)絡(luò)分析的藝術(shù).林沛滿.人民郵電出版社.

[2] Wireshark網(wǎng)絡(luò)分析就這么簡單.林沛滿.人民郵電出版社.

[3] Wireshark數(shù)據(jù)包分析實(shí)戰(zhàn).Chris Sanders .人民郵電出版社.


K8S進(jìn)階訓(xùn)練營,點(diǎn)擊下方圖片了解詳情

圖片

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多