在調(diào)試網(wǎng)絡(luò)通信程序是tcpdump是必備工具。tcpdump很強(qiáng)大,可以看到網(wǎng)絡(luò)通信的每個細(xì)節(jié)。如TCP,可以看到3次握手,PUSH/ACK數(shù)據(jù)推送,close4次揮手,全部細(xì)節(jié)。包括每一次網(wǎng)絡(luò)收包的字節(jié)數(shù),時間等。
tcpdump的選項
- -a —— 將網(wǎng)絡(luò)地址和廣播地址轉(zhuǎn)變成名字
- -d —— 將匹配信息包的代碼以人們能夠理解的匯編格式給出
- -dd —— 將匹配信息包的代碼以C語言程序段的格式給出
- -ddd —— 將匹配信息包的代碼以十進(jìn)制的形式給出
- -e —— 在輸出行打印出數(shù)據(jù)鏈路層的頭部信息
- -f —— 將外部的Internet地址以數(shù)字的形式打印出來
- -l —— 使標(biāo)準(zhǔn)輸出變?yōu)榫彌_行形式
- -n —— 不把網(wǎng)絡(luò)地址轉(zhuǎn)換成名字
- -nn: 指定將每個監(jiān)聽到的數(shù)據(jù)包中的域名轉(zhuǎn)換成IP、端口從應(yīng)用名稱轉(zhuǎn)換成端口號后顯示
- -s 從每個分組中讀取最開始的snaplen個字節(jié),而不是默認(rèn)的68個字節(jié)。 -s0 防止包截斷
- -t —— 在輸出的每一行不打印時間戳
- -v —— 輸出一個稍微詳細(xì)的信息,例如在ip包中可以包括ttl和服務(wù)類型的信息
- -vv —— 輸出詳細(xì)的報文信息
- -c —— 在收到指定的包的數(shù)目后,tcpdump就會停止
- -F —— 從指定的文件中讀取表達(dá)式,忽略其它的表達(dá)式
- -i —— 指定監(jiān)聽的網(wǎng)絡(luò)接口,如果不指定網(wǎng)卡,默認(rèn)tcpdump只會監(jiān)視第一個網(wǎng)絡(luò)接口,一般是eth0
- -r —— 從指定的文件中讀取包(這些包一般通過-w選項產(chǎn)生)
- -w —— 直接將包寫入cap文件中,并不分析和打印出來,一般配合wireshark分析
- -T —— 將監(jiān)聽到的包直接解釋為指定的類型的報文,常見的類型有rpc (遠(yuǎn)程過程調(diào)用)和snmp(簡單網(wǎng)絡(luò)管理協(xié)議)
- -X 告訴tcpdump命令,需要把協(xié)議頭和包內(nèi)容都原原本本的顯示出來(tcpdump會以16進(jìn)制和ASCII的形式顯示),這在進(jìn)行協(xié)議分析時是絕對的利器。
就是:dump the traffic on a network
tcpdump的表達(dá)式
類型的關(guān)鍵字要包括host,net,port
例如 host 210.27.48.2,指明 210.27.48.2是一臺主機(jī),net 202.0.0.0 指明 202.0.0.0是一個網(wǎng)絡(luò)地址,port 23 指明端口號是23。如果沒有指定類型,缺省的類型是host.
傳輸方向的關(guān)鍵字,主要包括src , dst ,dst or src, dst and src ,這些關(guān)鍵字指明了傳輸?shù)姆较?/p>
例如 src 210.27.48.2 ,指明ip包中源地址是210.27.48.2 , dst net 202.0.0.0 指明目的網(wǎng)絡(luò)地址是202.0.0.0 。如果沒有指明方向關(guān)鍵字,則缺省是src or dst關(guān)鍵字。
協(xié)議的關(guān)鍵字,主要包括fddi,ip,arp,rarp,tcp,udp等類型。Fddi指明是在FDDI(分布式光 纖數(shù)據(jù)接口網(wǎng)絡(luò))上的特定的網(wǎng)絡(luò)協(xié)議,實際上它是”ether”的別名,fddi和ether具有類似的源地址和目的地址,所以可以將fddi協(xié)議包當(dāng)作 ether的包進(jìn)行處理和分析。其他的幾個關(guān)鍵字就是指明了監(jiān)聽的包的協(xié)議內(nèi)容。如果沒有指定任何協(xié)議,則tcpdump將會監(jiān)聽所有協(xié)議的信息包。
其他重要的關(guān)鍵字:gateway, broadcast,less,greater,還有三種邏輯運算,取非運算是 ‘not ‘ ‘! ‘, 與運算是’and’,'&&’;或運算 是’or’ ,’││’;這些關(guān)鍵字可以組合起來構(gòu)成強(qiáng)大的組合條件來滿足人們的需要,下面舉幾個例子來說明。
A)跟10.66.151.82:6379(redis服務(wù)器)交互的所有tcp數(shù)據(jù)包(雙向):
tcpdump tcp port 6379 and host 10.66.151.82 -X
16:53:01.883032 phpmianshi.com.36822 > 10.66.151.82.6379: Flags
[S], seq 1943657014, win 29200, options [mss 1460,sackOK,TS val 814732894 ecr 0
,nop,wscale 7], length 0
16:53:01.883220 IP 10.66.151.82.6379 > phpmianshi.com.36822: Flags
[S.], seq 453036003, ack 1943657015, win 14480, options [mss 1424,sackOK,TS val
4119054316 ecr 814732894,nop,wscale 7], length 0
16:53:01.883234 IP phpmianshi.com.36822 > 10.66.151.82.6379: Flags
[.], ack 1, win 229, options [nop,nop,TS val 814732894 ecr 4119054316], length
0
16:53:01.883358 IP phpmianshi.com.36822 > 10.66.151.82.6379: Flags
[P.], seq 1:47, ack 1, win 229, options [nop,nop,TS val 814732894 ecr 411905431
6], length 29: RESP "AUTH" "password"
tcpdump的輸出結(jié)果 總的的輸出格式為:系統(tǒng)時間 來源主機(jī).端口 > 目標(biāo)主機(jī).端口 數(shù)據(jù)包參數(shù)
16:53:01.883358 時間帶有精確到微妙
IP 表示這個包在網(wǎng)路層,是IP包
phpmianshi.com.36822 > 10.66.151.82.6379 表示通信的流向,36822 是客戶端,6379是服務(wù)器端
flags 標(biāo)志由S(SYN), F(FIN), P(PUSH, R(RST),W(ECN CWT(nt | rep:未知, 需補(bǔ)充))或者 E(ECN-Echo(nt | rep:未知, 需補(bǔ)充))組成
[S] 表示這是一個SYN請求
[S.] 表示這是一個SYN+ACK確認(rèn)包
[.] 表示這是一個ACK確認(rèn)包
[P] 表示這個是一個數(shù)據(jù)推送,可以是從服務(wù)器端向客戶端推送,也可以從客戶端向服務(wù)器端推
[F] 表示這是一個FIN包,是關(guān)閉連接操作,client/server都有可能發(fā)起
[R] 表示這是一個RST包,與F包作用相同,但RST表示連接關(guān)閉時,仍然有數(shù)據(jù)未被處理。可以理解為是強(qiáng)制切斷連接
win 29200是指滑動窗口大小
length 29指數(shù)據(jù)包的大小, 因為 SYN 包不帶 TCP payload,所有信息都在 TCP header,所以length 為 0
截獲主機(jī)hostname發(fā)送的所有數(shù)據(jù)
tcpdump src host hostname
監(jiān)視所有送到主機(jī)hostname的數(shù)據(jù)包
tcpdump dst host hostname
監(jiān)視指定協(xié)議的數(shù)據(jù)包
打印TCP會話中的的開始和結(jié)束數(shù)據(jù)包,
tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin)!=0'
想獲取115.159.122.65.3306之間建立TCP三次握手中帶有SYN標(biāo)記位的網(wǎng)絡(luò)包.
tcpdump -n -nn 'host 115.159.122.65 and port 3306 and tcp[tcpflags] & tcp-syn!=0'
語法: proto [ expr : size]
Proto即protocol的縮寫,它表示這里要指定的是某種協(xié)議名稱,如ip,tcp,udp等,鏈路層協(xié)議 ether,fddi,tr,wlan,ppp,slip,link,網(wǎng)絡(luò)層協(xié)議ip,ip6,arp,rarp,icmp,傳輸層協(xié)議tcp,udp等。
expr用來指定數(shù)據(jù)報字節(jié)單位的偏移量,該偏移量相對于指定的協(xié)議層,默認(rèn)的起始位置是0;而size表示從偏移量的位置開始提取多少個字節(jié),可以設(shè)置為
1、2、4,默認(rèn)為1字節(jié)。如果只設(shè)置了expr,而沒有設(shè)置size,則默認(rèn)提取1個字節(jié)。比如ip[2:2],就表示提取出第3、4個字節(jié);而ip[0]則表示提取ip協(xié)議頭的
第一個字節(jié)。在我們提取了特定內(nèi)容之后,我們就需要設(shè)置我們的過濾條件了,我們可用的“比較操作符”包括:>,<,>=,<=,=,!=,總共有6個。
舉例:想截取每個TCP會話的起始和結(jié)束報文(SYN 和 FIN 報文), 而且會話中有一個遠(yuǎn)程主機(jī).
tcpdump 'tcp[13] & 3 != 0 and not(src and dst net 172.16.0.0)' -nn
如果熟悉tcp首部報文格式可以比較容易理解這句話,因為tcp偏移13字節(jié)的位置為2位保留位和6位標(biāo)志位(URG,ACK,PSH,RST,SYN,FIN), 所以與3相與就可以得出
SYN,FIN其中是否一個置位1.
從上面可以看到在寫過濾表達(dá)式時,需要我們對協(xié)議格式比較理解才能把表達(dá)式寫對。為了讓tcpdump工具更人性化一些,有一些常用的偏移量,
可以通過一些名稱來代替,比如icmptype表示ICMP協(xié)議的類型域、icmpcode表示ICMP的code域,tcpflags 則表示TCP協(xié)議的標(biāo)志字段域。
更進(jìn)一步的,對于ICMP的類型域,可以用這些名稱具體指代:
icmp-echoreply,icmp-unreach, icmp-sourcequench, icmp-redirect,icmp-echo, icmp-routeradvert, icmp-routersolicit, icmp-timxceed, icmp-paramprob,icmp-tstamp, icmp-tstampreply, icmp-ireq, icmp-ireqreply, icmp-maskreq,icmp-maskreply。
而對于TCP協(xié)議的標(biāo)志字段域,則可以細(xì)分為tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg。
對于tcpdump 只能通過經(jīng)常操作來熟練這些語句了。
tcpdump 與wireshark
Wireshark(以前是ethereal)是windows下非常簡單易用的抓包工具。但在linux下很難找到一個好用的圖形化抓包工具。還好有Tcpdump。我們可以用Tcpdump + Wireshark 的完美組合實現(xiàn):在 Linux 里抓包,然后在Windows 里分析包。
tcpdump tcp -i eth1 -t -s 0 -c 100 and dst port ! 22 and src net 192.168.1.0/24 -w ./target.cap
(1)tcp: ip icmp arp rarp 和 tcp、udp、icmp這些選項等都要放到第一個參數(shù)的位置,用來過濾數(shù)據(jù)報的類型(2)-i eth1 : 只抓經(jīng)過接口eth1的包(3)-t : 不顯示時間戳(4)-s 0 : 抓取數(shù)據(jù)包時默認(rèn)抓取長度為68字節(jié)。加上-S 0 后可以抓到完整的數(shù)據(jù)包(5)-c 100 : 只抓取100個數(shù)據(jù)包(6)dst port ! 22 : 不抓取目標(biāo)端口是22的數(shù)據(jù)包(7)src net 192.168.1.0/24 : 數(shù)據(jù)包的源網(wǎng)絡(luò)地址為192.168.1.0/24(8)-w ./target.cap : 保存成cap文件,方便用ethereal(即wireshark)分析
tcpdump 對截獲的數(shù)據(jù)并沒有進(jìn)行徹底解碼,數(shù)據(jù)包內(nèi)的大部分內(nèi)容是使用十六進(jìn)制的形式直接打印輸出的。顯然這不利于分析網(wǎng)絡(luò)故障,通常的解決辦法是先使用帶-w參數(shù)的tcpdump截獲數(shù)據(jù)并保存到文件中,然后再使用其他程序(如Wireshark)進(jìn)行解碼分析。當(dāng)然也應(yīng)該定義過濾規(guī)則,以避免捕獲的數(shù)據(jù)包填滿整個硬盤。
對于復(fù)雜的 pcap,例如,其中包含了上百個 IP 地址、上千個端口、上萬個連接的 pcap, 通過 tcpdump 看輸出可能就比較低效了。
這時,wireshark 這樣帶圖形用戶界面,且功能強(qiáng)大的網(wǎng) 絡(luò)流分析工具就派上了用場。
wireshark 支持強(qiáng)大的過濾功能,支持按 IP、端口、協(xié)議、連接、TCP flag 以及它們的各 種組合進(jìn)行過濾,然后進(jìn)行分析,大大節(jié)省網(wǎng)絡(luò)排障的時間。
wireshark 官方維護(hù)了一個 sample pcap列表
使用技巧:
wireshark導(dǎo)入pcap文件,我們可以看到有TCP Retransmission的情況,右鍵=>跟蹤流=>TCP流 就可以只看跟這個鏈接相關(guān)的流
從結(jié)果我們看到,由于沒有ack包回復(fù),觸發(fā)客戶端 TCP 超時重傳
TCP 重傳的機(jī)制:指數(shù)后退,比如第一次等待 1s,第二次等 待 2s,第三次等待 4s,第四次 8s,5次重傳后鏈接超時
從這個抓包文件看,這次連接沒有建立起來,client 沒有收到 server 的應(yīng)答包。要跟進(jìn)這個問題,就需要在 server 端一起抓包,看應(yīng)答包是否有發(fā)出來 。
TCPDUMP技巧
[技巧一]使用-A選項,則tcpdump只會顯示ASCII形式的數(shù)據(jù)包內(nèi)容,不會再以十六進(jìn)制形式顯示;[技巧二]使用-XX選項,則tcpdump會從以太網(wǎng)部分就開始顯示網(wǎng)絡(luò)包內(nèi)容,而不是僅從網(wǎng)絡(luò)層協(xié)議開始顯示。[技巧三]使用tcpdump -D 則tcpdump會列出所有可以選擇的抓包對象。 [技巧四]如果想查看哪些ICMP包中“目標(biāo)不可達(dá)、主機(jī)不可達(dá)”的包,請使用這樣的過濾表達(dá)式:icmp[0:2]==0x0301[技巧五]要提取TCP協(xié)議的SYN、ACK、FIN標(biāo)識字段,語法是:tcp[tcpflags] & tcp-syntcp[tcpflags] & tcp-acktcp[tcpflags] & tcp-fin[技巧六]要提取TCP協(xié)議里的SYN-ACK數(shù)據(jù)包,不但可以使用上面的方法,也可以直接使用最本質(zhì)的方法:tcp[13]==18[技巧七]如果要抓取一個區(qū)間內(nèi)的端口,可以使用portrange語法:tcpdump -i eth0 -nn 'portrange 52-55' -c 1 -XX