絡(luò)故障模擬與抓包分析:TCP/UDP協(xié)議行為復(fù)現(xiàn)實(shí)戰(zhàn))
1. 網(wǎng)絡(luò)故障模擬到底在模擬什么第一次接觸“網(wǎng)絡(luò)故障模擬”這個(gè)說(shuō)法的人腦子里冒出來(lái)的畫(huà)面往往是機(jī)房著火、交換機(jī)冒煙、網(wǎng)線被老鼠咬斷。但真正做過(guò)抓包分析的人都知道日常工作中遇到的絕大多數(shù)“網(wǎng)絡(luò)故障”其實(shí)根本不是硬件壞了而是協(xié)議行為不符合預(yù)期——TCP 該重傳的時(shí)候沒(méi)重傳UDP 該丟包的時(shí)候丟得莫名其妙握手該三次的時(shí)候偏偏只走了兩次。這些東西你在應(yīng)用層是看不出來(lái)的日志里只會(huì)寫(xiě)一句“連接超時(shí)”然后就沒(méi)有然后了。所以網(wǎng)絡(luò)故障模擬的核心不是去制造物理?yè)p壞而是在可控環(huán)境下復(fù)現(xiàn)那些“看起來(lái)像故障”的協(xié)議行為再用抓包工具把整個(gè)過(guò)程錄下來(lái)逐幀分析。TCP 和 UDP 是繞不開(kāi)的兩個(gè)主角TCP 面向連接、有狀態(tài)、有重傳機(jī)制它的故障往往表現(xiàn)為握手失敗、窗口凍結(jié)、RST 異常、重傳風(fēng)暴UDP 無(wú)連接、無(wú)狀態(tài)、不保證送達(dá)它的故障更多體現(xiàn)在丟包、亂序、重復(fù)、MTU 分片問(wèn)題上。兩者的排查思路完全不同抓包時(shí)的過(guò)濾策略也不一樣。這套東西適合誰(shuí)我個(gè)人的判斷是三類人最需要一是剛?cè)胄械倪\(yùn)維或后端開(kāi)發(fā)線上出了問(wèn)題只會(huì)重啟服務(wù)想往深了走必須懂抓包二是做物聯(lián)網(wǎng)、音視頻、游戲這類對(duì) UDP 依賴很重的開(kāi)發(fā)者UDP 的問(wèn)題不抓包基本靠猜三是準(zhǔn)備面試網(wǎng)絡(luò)相關(guān)崗位的人TCP 三次握手四次揮手背得再熟不如自己抓一次包看一遍來(lái)得扎實(shí)。接下來(lái)我會(huì)按照“先搭環(huán)境、再制造故障、然后抓包、最后逐幀分析”的順序把整個(gè)流程拆開(kāi)講。中間會(huì)穿插大量我實(shí)際踩過(guò)的坑比如為什么你抓到的包總是缺幀、為什么 Wireshark 顯示的“重傳”有時(shí)候是誤報(bào)、為什么 UDP 抓包過(guò)濾規(guī)則寫(xiě)錯(cuò)了會(huì)漏掉關(guān)鍵數(shù)據(jù)。這些細(xì)節(jié)文檔里通常不會(huì)寫(xiě)但恰恰是決定你能不能定位到問(wèn)題的關(guān)鍵。2. 動(dòng)手之前環(huán)境搭建與工具選型2.1 抓包工具的取舍邏輯抓包工具市面上主流的就是 Wireshark、tcpdump再加上一些命令行小工具。我的建議是兩個(gè)都要會(huì)但分工明確。Wireshark 是圖形化分析的主力優(yōu)勢(shì)在于協(xié)議解碼極其完整TCP 的每一個(gè)標(biāo)志位、每一個(gè)選項(xiàng)字段都能展開(kāi)看還能自動(dòng)標(biāo)記重傳、亂序、重復(fù) ACK。但它的劣勢(shì)也很明顯在服務(wù)器上跑圖形界面不現(xiàn)實(shí)而且抓大流量的時(shí)候內(nèi)存吃得厲害。tcpdump 則是服務(wù)器端的標(biāo)配幾乎任何 Linux 發(fā)行版都自帶或者一條命令就能裝它負(fù)責(zé)“抓”把包存成 pcap 文件然后拉到本地用 Wireshark 分析。這個(gè)“服務(wù)器抓、本地析”的組合是我用得最多的。至于故障模擬工具Linux 下最順手的是tctraffic control配合netem模塊可以模擬延遲、丟包、亂序、重復(fù)、損壞。Windows 下可以用 Clumsy 這類工具但功能沒(méi) tc 細(xì)。如果你只是想模擬應(yīng)用層的連接異常用iptables直接 DROP 或 REJECT 某些包也能達(dá)到目的而且更簡(jiǎn)單粗暴。提示不要一上來(lái)就上復(fù)雜工具。很多“故障”用 iptables 一條規(guī)則就能造出來(lái)比如直接丟棄 SYN 包模擬服務(wù)不可達(dá)比配置 tc 快得多。2.2 實(shí)驗(yàn)環(huán)境的搭建步驟我習(xí)慣用兩臺(tái) Linux 虛擬機(jī)加一臺(tái)宿主機(jī)來(lái)做這套實(shí)驗(yàn)。一臺(tái)當(dāng)客戶端一臺(tái)當(dāng)服務(wù)端宿主機(jī)用來(lái)跑 Wireshark 分析。網(wǎng)絡(luò)模式用 NAT 或者僅主機(jī)模式都行關(guān)鍵是兩臺(tái)機(jī)器能互通且你能控制它們之間的流量。具體步驟兩臺(tái)虛擬機(jī)都裝好基礎(chǔ)系統(tǒng)確認(rèn)ping能通。服務(wù)端裝一個(gè)簡(jiǎn)單的 TCP 服務(wù)和 UDP 服務(wù)。TCP 用nc -l或者 Python 的 socket 都行UDP 同理。我一般用 Python 寫(xiě)個(gè)十幾行的小腳本方便控制收發(fā)邏輯。客戶端裝tcpdump服務(wù)端也裝因?yàn)橛袝r(shí)候需要兩端同時(shí)抓包對(duì)比。宿主機(jī)裝 Wireshark用來(lái)打開(kāi) pcap 文件。確認(rèn)tc可用tc qdisc show能輸出內(nèi)容就說(shuō)明沒(méi)問(wèn)題。這里有個(gè)容易被忽略的點(diǎn)虛擬機(jī)的網(wǎng)卡類型會(huì)影響抓包結(jié)果。如果你用的是 virtio 網(wǎng)卡某些情況下 TCP 校驗(yàn)和卸載checksum offload會(huì)導(dǎo)致 Wireshark 顯示校驗(yàn)和錯(cuò)誤但那其實(shí)是網(wǎng)卡卸載造成的假象不是真的錯(cuò)誤。解決辦法是在 Wireshark 里關(guān)掉校驗(yàn)和驗(yàn)證或者用ethtool -K eth0 tx off rx off關(guān)掉卸載。這個(gè)坑我踩過(guò)不止一次一開(kāi)始以為是數(shù)據(jù)包損壞查了半天才發(fā)現(xiàn)是卸載的鍋。2.3 抓包過(guò)濾規(guī)則的正確寫(xiě)法抓包時(shí)最忌諱的就是“全抓”。全抓的后果是文件巨大、噪音極多分析的時(shí)候光過(guò)濾就浪費(fèi)半小時(shí)。正確的做法是在抓的時(shí)候就過(guò)濾而不是抓完再過(guò)濾。tcpdump 的過(guò)濾表達(dá)式基于 BPF 語(yǔ)法幾個(gè)我常用的# 只抓某臺(tái)主機(jī)的 TCP 流量 tcpdump -i eth0 -w tcp.pcap host 192.168.1.100 and tcp # 只抓某個(gè)端口且排除 SSH 自身流量 tcpdump -i eth0 -w udp.pcap udp port 9999 # 抓 TCP 握手和揮手相關(guān)的包 tcpdump -i eth0 -w handshake.pcap tcp[tcpflags] (tcp-syn|tcp-fin|tcp-rst) ! 0Wireshark 的顯示過(guò)濾器則是另一套語(yǔ)法常用的有tcp.analysis.retransmission看重傳、tcp.flags.reset 1看 RST、udp.length 100按長(zhǎng)度過(guò)濾。注意區(qū)分捕獲過(guò)濾器和顯示過(guò)濾器前者在抓的時(shí)候就生效后者只是隱藏不匹配的包文件里其實(shí)還在。注意抓包時(shí)加-s 0表示抓完整包不加的話默認(rèn)只抓前 96 字節(jié)TCP 選項(xiàng)字段可能被截?cái)喾治鑫帐謪?shù)時(shí)會(huì)缺信息。這個(gè)細(xì)節(jié)很多人不知道導(dǎo)致抓到的包“看起來(lái)正?!钡治霾涣恕?. TCP 故障模擬與抓包實(shí)戰(zhàn)3.1 三次握手失敗的三種典型場(chǎng)景TCP 故障里最基礎(chǔ)也最??嫉木褪俏帐质?。我把它分成三種SYN 丟失、SYN-ACK 丟失、ACK 丟失。三種情況在抓包結(jié)果上表現(xiàn)完全不同排查方向也不一樣。場(chǎng)景一SYN 丟失??蛻舳税l(fā)出 SYN 后服務(wù)端根本沒(méi)收到所以不會(huì)有任何回應(yīng)。抓包看到的是客戶端反復(fù)重發(fā) SYN間隔按 1s、2s、4s、8s 指數(shù)退避重試幾次后放棄報(bào)“連接超時(shí)”。這種故障通常意味著網(wǎng)絡(luò)路徑不通、防火墻攔截或者服務(wù)端根本沒(méi)在監(jiān)聽(tīng)。模擬方法很簡(jiǎn)單在服務(wù)端用 iptables 丟棄入站 SYNiptables -A INPUT -p tcp --dport 8080 --syn -j DROP抓包分析時(shí)重點(diǎn)看客戶端 SYN 的序列號(hào)是否每次相同相同說(shuō)明是重傳不是新連接、重傳間隔是否符合指數(shù)退避、有沒(méi)有收到任何回應(yīng)。場(chǎng)景二SYN-ACK 丟失。服務(wù)端收到了 SYN回了 SYN-ACK但這個(gè)回應(yīng)在回程路上丟了。客戶端視角和場(chǎng)景一一樣也是反復(fù)重發(fā) SYN。但如果你在服務(wù)端抓包會(huì)看到服務(wù)端其實(shí)回了 SYN-ACK而且可能回了多次因?yàn)榉?wù)端也在重傳。這種故障的迷惑性在于客戶端和服務(wù)端的抓包結(jié)果對(duì)不上一個(gè)說(shuō)“我發(fā)了你沒(méi)回”一個(gè)說(shuō)“我回了你沒(méi)收到”。這時(shí)候兩端同時(shí)抓包對(duì)比就非常關(guān)鍵。場(chǎng)景三ACK 丟失。這個(gè)最隱蔽。服務(wù)端收到 SYN回 SYN-ACK客戶端收到后回 ACK但 ACK 丟了。服務(wù)端會(huì)認(rèn)為握手沒(méi)完成重傳 SYN-ACK客戶端認(rèn)為自己已經(jīng) ESTABLISHED 了收到重復(fù)的 SYN-ACK 會(huì)覺(jué)得奇怪。抓包時(shí)能看到服務(wù)端反復(fù)重傳 SYN-ACK而客戶端可能已經(jīng)開(kāi)始發(fā)數(shù)據(jù)了。這種“半開(kāi)連接”狀態(tài)是很多詭異問(wèn)題的根源。3.2 用 tc netem 制造可控的丟包和延遲iptables 只能做“丟”或“不丟”的二元選擇想要更精細(xì)的控制比如“丟 30% 的包”“延遲 200ms 且抖動(dòng) 50ms”就得上 tc netem。# 在 eth0 上添加 30% 丟包 tc qdisc add dev eth0 root netem loss 30% # 添加 200ms 延遲抖動(dòng) 50ms tc qdisc add dev eth0 root netem delay 200ms 50ms # 模擬亂序25% 的包延遲 10ms 發(fā)送 tc qdisc add dev eth0 root netem delay 10ms reorder 25% # 用完記得刪除否則一直生效 tc qdisc del dev eth0 root這里有個(gè)實(shí)操心得netem 的丟包是隨機(jī)的不可復(fù)現(xiàn)。同樣的配置跑兩次丟的包不一樣。如果你需要精確復(fù)現(xiàn)某個(gè)故障場(chǎng)景netem 不太合適得用更底層的手段比如自己寫(xiě)個(gè)代理程序按規(guī)則丟包。但對(duì)于學(xué)習(xí)抓包分析來(lái)說(shuō)隨機(jī)丟包已經(jīng)足夠制造出重傳、重復(fù) ACK、快速重傳這些現(xiàn)象了。我一般會(huì)這樣設(shè)計(jì)實(shí)驗(yàn)先建立正常連接抓一份“健康”的包作為基線然后加上 netem 丟包再抓一份“故障”的包兩份對(duì)比著看差異一目了然。沒(méi)有基線對(duì)比你很難判斷某個(gè)現(xiàn)象是正常的還是異常的。3.3 重傳與快速重傳的抓包識(shí)別TCP 重傳分兩種超時(shí)重傳和快速重傳。超時(shí)重傳是發(fā)送方等不到 ACK超過(guò) RTO 時(shí)間后重發(fā)快速重傳是發(fā)送方收到三個(gè)重復(fù) ACK 后立即重發(fā)不等超時(shí)。在 Wireshark 里超時(shí)重傳會(huì)被標(biāo)記為T(mén)CP Retransmission快速重傳標(biāo)記為T(mén)CP Fast Retransmission。但要注意Wireshark 的標(biāo)記有時(shí)候是誤報(bào)。比如它可能把正常的重傳當(dāng)成異常或者因?yàn)樽グc(diǎn)位置不對(duì)而誤判。判斷重傳是否真的發(fā)生了最可靠的方法是看序列號(hào)如果兩個(gè)包的序列號(hào)相同、載荷相同那就是重傳。重復(fù) ACK 的識(shí)別也有講究。接收方收到亂序的包時(shí)會(huì)重復(fù)發(fā)送最后一個(gè)按序到達(dá)的 ACK告訴發(fā)送方“我還在等某個(gè)序列號(hào)的包”。收到三個(gè)重復(fù) ACK發(fā)送方就觸發(fā)快速重傳。抓包時(shí)看到連續(xù)的、ACK 號(hào)相同的包基本就是重復(fù) ACK 了。提示分析重傳時(shí)把 Wireshark 的“相對(duì)序列號(hào)”打開(kāi)默認(rèn)就是開(kāi)的比看絕對(duì)序列號(hào)直觀得多。絕對(duì)序列號(hào)是一串大數(shù)字相對(duì)序列號(hào)從 0 開(kāi)始一眼就能看出哪個(gè)包重傳了。3.4 RST 異常的排查思路RST 包是 TCP 里的“急剎車”收到 RST 意味著連接被強(qiáng)制終止。RST 出現(xiàn)的原因很多連接到一個(gè)沒(méi)監(jiān)聽(tīng)的端口、防火墻主動(dòng)拒絕、應(yīng)用層主動(dòng)關(guān)閉、半開(kāi)連接收到數(shù)據(jù)等。排查 RST 的第一步是看 RST 是誰(shuí)發(fā)的、在什么階段發(fā)的。如果是握手階段服務(wù)端回 RST說(shuō)明端口沒(méi)監(jiān)聽(tīng)或者被防火墻 REJECT 了。如果是數(shù)據(jù)傳輸階段某一方發(fā) RST可能是應(yīng)用崩潰或者主動(dòng)關(guān)閉。如果是連接空閑很久后突然 RST可能是中間設(shè)備清理了會(huì)話表。我遇到過(guò)一個(gè)很典型的案例客戶端連接服務(wù)端握手正常發(fā)第一個(gè)請(qǐng)求也正常但發(fā)第二個(gè)請(qǐng)求時(shí)收到 RST。抓包發(fā)現(xiàn)服務(wù)端在收到第二個(gè)請(qǐng)求后立即回了 RST。查下來(lái)是服務(wù)端的連接池配置有問(wèn)題第一個(gè)請(qǐng)求處理完后連接被錯(cuò)誤地關(guān)閉了但客戶端不知道繼續(xù)復(fù)用這個(gè)連接服務(wù)端收到數(shù)據(jù)后發(fā)現(xiàn)連接已經(jīng)不存在只能回 RST。這種問(wèn)題不看抓包根本定位不到。4. UDP 故障模擬與抓包實(shí)戰(zhàn)4.1 UDP 抓包的特殊性UDP 和 TCP 在抓包分析上的最大區(qū)別是UDP 沒(méi)有連接狀態(tài)沒(méi)有握手揮手沒(méi)有重傳機(jī)制。這意味著你抓到的每一個(gè) UDP 包都是獨(dú)立的不存在“這個(gè)包屬于哪個(gè)連接”的概念除非應(yīng)用層自己定義了會(huì)話 ID。這給分析帶來(lái)了兩個(gè)困難一是無(wú)法通過(guò)握手判斷通信是否正常建立二是丟包后沒(méi)有任何協(xié)議層的補(bǔ)償只能靠應(yīng)用層自己處理。抓 UDP 包時(shí)過(guò)濾規(guī)則要更精確。因?yàn)?UDP 沒(méi)有標(biāo)志位你只能按端口、按 IP、按長(zhǎng)度來(lái)過(guò)濾。我常用的# 按端口抓 tcpdump -i eth0 -w udp.pcap udp port 9999 # 按源或目的 IP 抓 tcpdump -i eth0 -w udp.pcap udp and host 192.168.1.100 # 排除某個(gè)端口避免抓到噪音 tcpdump -i eth0 -w udp.pcap udp and not port 53Wireshark 里分析 UDP 時(shí)我建議打開(kāi)“協(xié)議層次統(tǒng)計(jì)”和“會(huì)話統(tǒng)計(jì)”能快速看出哪些 IP 對(duì)之間流量最大、包數(shù)量是否對(duì)稱。UDP 的故障往往表現(xiàn)為“一方發(fā)了很多另一方收得很少”這種不對(duì)稱在統(tǒng)計(jì)圖里一眼就能看出來(lái)。4.2 丟包、亂序、重復(fù)的模擬與識(shí)別UDP 的故障模擬和 TCP 類似也是用 tc netem但因?yàn)?UDP 沒(méi)有重傳丟包的影響更直接。# 模擬 20% 丟包 tc qdisc add dev eth0 root netem loss 20% # 模擬亂序 tc qdisc add dev eth0 root netem delay 5ms reorder 50% 50% # 模擬重復(fù) tc qdisc add dev eth0 root netem duplicate 10%識(shí)別丟包的方法在發(fā)送端和接收端同時(shí)抓包對(duì)比兩邊的包序列號(hào)如果應(yīng)用層有序列號(hào)的話。發(fā)送端發(fā)了 100 個(gè)包接收端只收到 80 個(gè)那 20 個(gè)就是丟了。如果應(yīng)用層沒(méi)有序列號(hào)那就只能靠包的數(shù)量和內(nèi)容來(lái)推斷難度大很多。這也是為什么我強(qiáng)烈建議自研的 UDP 協(xié)議一定要在應(yīng)用層加序列號(hào)不然出了問(wèn)題根本沒(méi)法排查。亂序的識(shí)別接收端收到的包序列號(hào)不是遞增的比如收到 1、2、4、3、5。Wireshark 本身不會(huì)標(biāo)記 UDP 亂序因?yàn)樗恢滥愕男蛄刑?hào)規(guī)則你得自己看載荷里的序列號(hào)字段。重復(fù)的識(shí)別同一個(gè)序列號(hào)的包出現(xiàn)了兩次。netem 的 duplicate 是隨機(jī)復(fù)制所以你會(huì)看到某些包莫名其妙出現(xiàn)兩遍。4.3 MTU 與分片問(wèn)題的抓包分析UDP 還有一個(gè) TCP 不太會(huì)遇到的問(wèn)題分片。UDP 包如果超過(guò) MTUIP 層會(huì)把它分片。分片本身不是故障但分片會(huì)帶來(lái)兩個(gè)隱患一是任何一片丟失整個(gè) UDP 包就廢了而 UDP 不會(huì)重傳二是某些防火墻或 NAT 設(shè)備對(duì)分片的處理不一致可能導(dǎo)致分片被丟棄或重組失敗。抓包時(shí)識(shí)別分片看 IP 頭的Flags字段MFMore Fragments為 1 表示后面還有分片F(xiàn)ragment Offset不為 0 表示這是后續(xù)分片。Wireshark 會(huì)把同一個(gè) UDP 包的分片標(biāo)記出來(lái)但需要你手動(dòng)開(kāi)啟“重組”功能才能看到完整的載荷。我遇到過(guò)一個(gè)經(jīng)典問(wèn)題客戶端發(fā)一個(gè) 2000 字節(jié)的 UDP 包服務(wù)端收不到。抓包發(fā)現(xiàn)包被分成了兩片第一片到了第二片丟了。因?yàn)?UDP 不重傳服務(wù)端重組失敗整個(gè)包被丟棄。解決辦法要么是減小包大小避免分片要么是在應(yīng)用層做分片和重傳。這個(gè)問(wèn)題的隱蔽性在于小包測(cè)試一切正常一大包就出問(wèn)題很容易誤判為“服務(wù)端處理能力不足”。注意路徑 MTU 發(fā)現(xiàn)PMTUD在 UDP 場(chǎng)景下經(jīng)常失效因?yàn)楹芏喾阑饓?huì)丟棄 ICMP 的“需要分片”消息。所以 UDP 應(yīng)用最好自己控制包大小不要依賴 PMTUD。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 抓包抓不到包的幾個(gè)原因這是新手最常遇到的問(wèn)題明明配置了抓包但一個(gè)包都沒(méi)有。我總結(jié)了幾種可能現(xiàn)象可能原因排查方法完全沒(méi)包網(wǎng)卡選錯(cuò)了ip a確認(rèn)流量走哪塊網(wǎng)卡只有單向包抓包點(diǎn)位置不對(duì)在兩端同時(shí)抓對(duì)比包不完整沒(méi)加-s 0重新抓指定 snaplen過(guò)濾太嚴(yán)表達(dá)式寫(xiě)錯(cuò)先不加過(guò)濾抓確認(rèn)有流量再逐步加權(quán)限不足沒(méi)用 rootsudo tcpdump還有一個(gè)隱蔽的原因流量走了 loopback。如果客戶端和服務(wù)端在同一臺(tái)機(jī)器上流量走的是lo網(wǎng)卡你在eth0上抓是抓不到的。這個(gè)坑我踩過(guò)當(dāng)時(shí)以為是防火墻問(wèn)題查了半天才發(fā)現(xiàn)是網(wǎng)卡選錯(cuò)了。5.2 Wireshark 分析中的誤報(bào)與陷阱Wireshark 很強(qiáng)大但它的自動(dòng)分析功能有時(shí)候會(huì)誤導(dǎo)人。幾個(gè)常見(jiàn)的誤報(bào)校驗(yàn)和錯(cuò)誤誤報(bào)。前面提過(guò)網(wǎng)卡卸載會(huì)導(dǎo)致 Wireshark 顯示校驗(yàn)和錯(cuò)誤但實(shí)際包是好的。解決辦法是關(guān)掉校驗(yàn)和驗(yàn)證或者關(guān)掉網(wǎng)卡卸載。重傳誤報(bào)。Wireshark 判斷重傳是基于序列號(hào)和時(shí)間的如果抓包點(diǎn)位置特殊比如在發(fā)送方和接收方之間的中間設(shè)備上抓可能會(huì)把正常的包誤判為重傳。亂序誤報(bào)。多路徑或者抓包點(diǎn)不對(duì)稱時(shí)Wireshark 可能把正常到達(dá)的包標(biāo)記為亂序。我的經(jīng)驗(yàn)是永遠(yuǎn)不要只信 Wireshark 的標(biāo)記要自己看序列號(hào)、看時(shí)間戳、看載荷。標(biāo)記只是提示最終判斷得靠數(shù)據(jù)本身。5.3 從抓包到定位問(wèn)題的完整思路抓包只是手段定位問(wèn)題才是目的。我一般的分析流程是先看整體用 Wireshark 的“統(tǒng)計(jì)”功能看包數(shù)量、會(huì)話分布、協(xié)議分布快速定位異常點(diǎn)。再看異常過(guò)濾出重傳、RST、重復(fù) ACK、ICMP 錯(cuò)誤等異常包看它們集中在哪個(gè)時(shí)間段、哪對(duì) IP 之間。然后看細(xì)節(jié)針對(duì)異常包展開(kāi)協(xié)議樹(shù)看序列號(hào)、標(biāo)志位、選項(xiàng)字段、載荷內(nèi)容。最后做對(duì)比和正常情況的抓包對(duì)比找出差異。沒(méi)有對(duì)比就沒(méi)有判斷。這個(gè)流程說(shuō)起來(lái)簡(jiǎn)單但實(shí)際操作中最難的是第 4 步。很多人抓了包看到一堆重傳就慌了但其實(shí)如果基線抓包里也有重傳那說(shuō)明重傳在這個(gè)網(wǎng)絡(luò)環(huán)境下是正常的不是故障原因。建立基線這個(gè)習(xí)慣是我做抓包分析這些年最重要的經(jīng)驗(yàn)。5.4 幾個(gè)提升效率的小技巧Wireshark 的“追蹤 TCP 流”功能Follow TCP Stream能把一個(gè)連接的所有載荷拼起來(lái)看分析應(yīng)用層協(xié)議時(shí)特別有用。UDP 沒(méi)有流的概念但可以用“追蹤 UDP 流”看一段時(shí)間內(nèi)的所有包。給 pcap 文件命名時(shí)帶上時(shí)間、場(chǎng)景、過(guò)濾條件比如20240115_tcp_retrans_loss30.pcap過(guò)幾天回頭看還能想起來(lái)是什么實(shí)驗(yàn)。分析大文件時(shí)先用editcap按時(shí)間或包數(shù)量切分再逐段分析比一次性打開(kāi)幾百兆的文件流暢得多。如果需要在多臺(tái)機(jī)器上同時(shí)抓包用tcpdump的-w寫(xiě)到文件然后統(tǒng)一拉到一臺(tái)機(jī)器上用 Wireshark 的“合并”功能合并注意時(shí)間同步問(wèn)題機(jī)器之間時(shí)間差太大會(huì)導(dǎo)致合并后的時(shí)間線錯(cuò)亂。最后分享一個(gè)我個(gè)人的習(xí)慣每次做完故障模擬實(shí)驗(yàn)我都會(huì)把抓包文件、分析筆記、結(jié)論整理成一個(gè)文檔存檔。下次遇到類似問(wèn)題直接翻文檔比重新抓包分析快得多。網(wǎng)絡(luò)故障這東西太陽(yáng)底下沒(méi)有新鮮事你遇到過(guò)的大概率別人也遇到過(guò)只是你當(dāng)時(shí)沒(méi)記下來(lái)而已。