轉(zhuǎn)載揩环,文章出處:http://mrpeak.cn/blog/tutorial-tcpdump/
開啟tcpdump
Mac上的rvictl可以通過iOS設(shè)備的UDID創(chuàng)建一個虛擬網(wǎng)卡鸠珠,然后通過網(wǎng)瞳監(jiān)聽設(shè)備上的所有流量授艰。
rvictl -s udid //創(chuàng)建虛擬網(wǎng)卡命令 sudo tcpdump -i rvi0 -AAl //啟動tcpdump監(jiān)控
分析tcpdump
經(jīng)過上面的步驟成功運行tcpdump之后兜看,接下來就可以分析輸出的網(wǎng)絡(luò)包內(nèi)容了,iOS設(shè)備和Android設(shè)備的輸出是一致的。我們先來解析下幾個基本的格式:
圖中紅色方框內(nèi)的部分是一個ip包的詳細記錄眯杏,類似的紀(jì)錄還有好幾條。這里我們著重分析第一條的各部分字段含義典尾。
14:37:41.615018 很簡單役拴,是該包接收到的時間。
17.143.164.37.5223 是發(fā)送方的ip地址及端口號(5223是端口號)钾埂。
10.29.44.140.58036 是我iphone的ip地址及端口號河闰。
Flags [P.] 是tcp包header部分的第14個字節(jié)的P位。這個字節(jié)所包含的幾個flag很重要褥紫,后面我會單獨詳細講解姜性。這里P位表示接受方需要馬上將包push到應(yīng)用層。
seq 1:54 tcp包的seq號髓考,1是起始值部念,54結(jié)束值。tcp之所以被認為是流氨菇,是因為tcp包所攜帶的每一個字節(jié)都有標(biāo)號(seq號)儡炼。1:54表明總共有54個字節(jié)被接受,其中一個字節(jié)是三次握手階段所使用查蓉,所以一共發(fā)送的長度是53字節(jié)乌询。
ack 101 tcp包的ack號,ack 101表明seq號為100的字節(jié)已被確認收到豌研,下一個期望接收的seq號從101開始妹田。
win 255 win表示的是tcp包發(fā)送方,作為接受方還可以接受的字節(jié)數(shù)鹃共。這里win 255表明ip為17.143.164.37的主機還可以接受255個字節(jié)鬼佣。
options [nop,nop,…] options[…]表示的是該tcp包的options區(qū)域,nop是no opertion的縮寫霜浴,沒什么實際用途晶衷,主要是用做padding,因為options區(qū)域按協(xié)議規(guī)定必須是4字節(jié)的倍數(shù)阴孟。
options[… TS val 2381386761] ts val這個值是tcp包的時間戳房铭,不過這個時間戳和設(shè)備的系統(tǒng)時間沒啥關(guān)系,剛開始是隨機值温眉,后面隨著系統(tǒng)時鐘自增長缸匪。這個時間戳主要用處是seq序列號越界從0重新開始后,可以確認包的順序类溢。
options[… ecr 427050796] ts ecr這個值主要用來計算RTT凌蔬。比如A發(fā)送一個tcp包給B露懒,A會在包里帶上TS val,B收到之后在ack包里再把這個值原樣返回砂心,A收到B的ack包之后再根據(jù)本地時鐘就可以計算出RTT了懈词。這個值只在ack包里有效,非ack包ecr的值就為0.
length 53 這個length是應(yīng)用層傳過來的數(shù)據(jù)大小辩诞,不包括tcp的header坎弯。這個值和我們上面分析的seq 1:54是一致的谷徙。
以上就是一個基本的tcp包結(jié)構(gòu)宪肖,大家可以按照上面的分析再把其他幾個包理解下。我們在做應(yīng)用的時候面對的更多是http協(xié)議结耀,但對一個http請求是怎么通過tcp/ip分解成一個個的packet外永,然后怎么在網(wǎng)絡(luò)上穩(wěn)定可靠的傳輸崎脉,要有個基本的印象。下面我們再看下tcpdump更多的功能伯顶,這些功能都是基于對tcp/ip協(xié)議的理解囚灼,遇到不理解的建議多google下相關(guān)的技術(shù)概念。
tcpdump知識拓展
再繼續(xù)深入tcpdump之前祭衩,先貼上一張tcp header格式圖灶体,常看常新掐暮。
3.1 TCP Flags(tcp header第十四個字節(jié))
我們再仔細看下上面提到的flags概念赃春,flags位于tcp header的第十四個字節(jié),包含8個比特位劫乱,也就是上圖的CWR到FIN。這8個比特位都有特定的功能用途锥涕,分別是:CWR衷戈,ECE,URG层坠,ACK殖妇,PSH,RST破花,SYN谦趣,F(xiàn)IN。
CWR 座每,ECE 兩個flag是用來配合做congestion control的前鹅,一般情況下和應(yīng)用層關(guān)系不大。發(fā)送方的包ECE(ECN-Echo)為0的時候表示出現(xiàn)了congestion峭梳,接收方回的包里CWR(Congestion Window Reduced)為1表明收到congestion信息并做了處理舰绘。我們重點看其他六個flag蹂喻。
URG URG代表Urgent,表明包的優(yōu)先級高捂寿,需要優(yōu)先傳送對方并處理口四。像我們平時使用terminal的時候經(jīng)常ctrl+c來結(jié)束某個任務(wù),這種命令產(chǎn)生的網(wǎng)絡(luò)數(shù)據(jù)包就需要urgent秦陋。
ACK 也就是我們所熟悉的ack包蔓彩,用來告訴對方上一個數(shù)據(jù)包已經(jīng)成功收到。不過一般不會為了ack單獨發(fā)送一個包驳概,都是在下一個要發(fā)送的packet里設(shè)置ack位赤嚼,這屬于tcp的優(yōu)化機制,參見delayed ack抡句。
PSH Push我們上面解釋過探膊,接收方接收到P位的flag包需要馬上將包交給應(yīng)用層處理,一般我們在http request的最后一個包里都能看到P位被設(shè)置待榔。
RST Reset位逞壁,表明packet的發(fā)送方馬上就要斷開當(dāng)前連接了。在http請求結(jié)束的時候一般可以看到一個數(shù)據(jù)包設(shè)置了RST位锐锣。
SYN SYN位在發(fā)送建立連接請求的時候會設(shè)置腌闯,我們所熟悉的tcp三次握手就是syn和ack位的配合:syn->syn+ack->ack。
FIN Finish位設(shè)置了就表示發(fā)送方?jīng)]有更多的數(shù)據(jù)要發(fā)送了雕憔,之后就要單向關(guān)閉連接了姿骏,接收方一般會回一個ack包。接收方再同理發(fā)送一個FIN就可以雙向關(guān)閉連接了斤彼。
這8個flag首字母分別是:C E U A P R S F分瘦。初看難以記憶,我腦洞了下琉苇,把它們組合成 supr cafe嘲玫,當(dāng)然少了super少了個e,我可以將就下并扇。我們在使用tcpdump的時候會經(jīng)橙ネ牛看到這幾個flag,[S],[P],[R],[F],[.]穷蛹。其他幾個都好理解土陪,[.]特殊點,是個占位符肴熏,沒有其他flag被設(shè)置的時候就顯示這個占位符鬼雀,一般表示ack。
tcpdump 更多使用參數(shù)
這部分我們來看下tcpdump常用的一些命令參數(shù)蛙吏。文章最開始部分的tcpdump命令是這樣的:sudo tcpdump -i rvi0 -AAl取刃。 -i rvi0 -AAl都是屬于參數(shù)部分蹋肮。常見的有這些:
-i, 要監(jiān)聽的網(wǎng)卡名稱,-i rvi0監(jiān)聽虛擬網(wǎng)卡璧疗。不設(shè)置的時候默認監(jiān)聽所有網(wǎng)卡流量坯辩。
-A, 用ASCII碼展示所截取的流量,一般用于網(wǎng)頁或者app里http請求崩侠。-AA可以獲取更多的信息漆魔。
-X,用ASCII碼和hex來展示包的內(nèi)容却音,和上面的-A比較像改抡。-XX可以展示更多的信息(比如link layer的header)。
-n系瓢,不解析hostname,tcpdump會優(yōu)先暫時主機的名字阿纤。-nn則不展示主機名和端口名(比如443端口會被展示成https)。
-s夷陋,截取的包字節(jié)長度欠拾,默認情況下tcpdump會展示96字節(jié)的長度,要獲取完整的長度可以用-s0或者-s1600骗绕。
-c藐窄,只截取指定數(shù)目的包,然后退出酬土。
-v荆忍,展示更多的有用信息,還可以用-vv -vvv增加信息的展示量撤缴。
src刹枉,指明ip包的發(fā)送方地址。
dst屈呕,指明ip包的接收方地址微宝。
port,指明tcp包發(fā)送方或者接收方的端口號凉袱。
and,or,not,操作法,字面意思侦铜。
上面幾個是我個人比較常用的专甩,更多的參數(shù)可以參考這個詳細文檔。有興趣的可以分析下面幾個例子練習(xí)下:
tcpdump ‘tcp[13] & 16!=0’
tcpdump src port 80 and tcp
tcpdump -vv src baidu and not dst port 23
tcpdump -nnvvS src 192.0.1.100 and dst port 443
用tcpdump分析http完整請求
說了這么多钉稍,我們再來實戰(zhàn)下涤躲,看一個完整的http請求流程。 下面截圖里的流量是我監(jiān)聽的 知乎App點贊之后發(fā)送的一個https請求贡未。我之前先分析過server的ip地址了种樱,tcpdump命令是:
sudo tcpdump -i rvi0 -AAl src 60.28.215.123 or dst 60.28.215.123
圖中列出了6個前面的packet蒙袍,10.29.44.240是我iphone的ip地址,60.28.215.123是知乎server的ip地址嫩挤,紅色方框內(nèi)是iphone發(fā)出的packet害幅,白色方框內(nèi)是server發(fā)出的packet。packet1是iphone三次握手的第一個syn包岂昭,packet2是server ack+syn的包以现,packet3是iphone ack的包。這3個packet之后tcp的三次握手就完成了约啊。
packet4是iphone發(fā)出的http request邑遏。長度只有240個字節(jié),所以一個packet就發(fā)過去了恰矩,當(dāng)然還設(shè)置了flags的P位记盒,request需要馬上被應(yīng)用層處理。包里面出現(xiàn)了spdy外傅,點贊纪吮。
packet5是server ack剛收到的包,長度位0栏豺,所以這僅僅是一個ack包彬碱。
packet6是server返回http的response了,1388個字節(jié)奥洼。packet5和packet6都ack了seq為241的包巷疼,當(dāng)然是為了增加ack的成功率。
中間還有好幾個packet就不仔細分析了灵奖,最后再看下請求完成的最后幾個包:
最后兩個packet比較簡單嚼沿,iphone發(fā)送個FIN+ACK的包就斷開連接了,server直接發(fā)送了一個RST包后也斷開連接了瓷患。
這篇教程到這里就結(jié)束了骡尽,建議大家自己多練習(xí)下,遇到不懂的參數(shù)或關(guān)鍵字多google擅编。最好能系統(tǒng)的學(xué)習(xí)下tcp/ip協(xié)議??攀细。