tcpdump抓包命令
tcpdump是一個用于截取網絡分組,并輸出分組內容的工具。tcpdump憑借強大的功能和靈活的截取策略,使其成為類UNIX系統下用于網絡分析和問題排查的首選工具。
tcpdump提供了源代碼,公開了接口,因此具備很強的可擴展性,對于網絡維護和入侵者都是非常有用的工具。tcpdump存在于基本的Linux系統中,由于它需要將網絡界面設置為混雜模式,普通用戶不能正常執行,但具備root權限的用戶可以直接執行它來獲取網絡上的信息。因此系統中存在網絡分析工具主要不是對本機安全的威脅,而是對網絡上的其他計算機的安全存在威脅。
一、概述
顧名思義,tcpdump可以將網絡中傳送的數據包的“頭”完全截獲下來提供分析。它支持針對網絡層、協議、主機、網絡或端口的過濾,并提供and、or、not等邏輯語句來幫助你去掉無用的信息。
# tcpdump -vv # -vv表示顯示詳細的信息
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
11:53:21.444591 IP (tos 0x10, ttl 64, id 19324, offset 0, flags [DF], proto 6, length: 92)
asptest.localdomain.ssh > 192.168.228.244.1858: P 3962132600:3962132652(52) ack 2726525936 win 1266
asptest.localdomain.1077 > 192.168.228.153.domain: [bad udp cksum 166e!] 325+ PTR? 244.228.168.192.in-addr.arpa. (46)
11:53:21.446929 IP (tos 0x0, ttl 64, id 42911, offset 0, flags [DF], proto 17, length: 151) 192.168.228.153.domain > asptest.localdomain.1077: 325 NXDomain q: PTR? 244.228.168.192.in-addr.arpa. 0/1/0 ns: 168.192.in-addr.arpa. (123)
11:53:21.447408 IP (tos 0x10, ttl 64, id 19328, offset 0, flags [DF], proto 6, length: 172) asptest.localdomain.ssh > 192.168.228.244.1858: P 168:300(132) ack 1 win 1266
<==按下[ctrl]-c之后結束
347 packets captured
1474 packets received by filter
745 packets dropped by kernel
不帶參數的tcpdump會收集網絡中所有的信息包頭,數據量巨大,必須過濾。
二、選項介紹
tcpdump采用命令行方式,它的命令大致如下:
tcpdump [ -AbdDefhHIJKlLnNOpqStuUvxX# ] [ -B buffer_size ]
[ -c count ]
[ -C file_size ] [ -G rotate_seconds ] [ -F file ]
[ -i interface ] [ -j tstamp_type ] [ -m module ] [ -M secret ]
[ --number ] [ -Q in|out|inout ]
[ -r file ] [ -V file ] [ -s snaplen ] [ -T type ] [ -w file ]
[ -W filecount ]
[ -y datalinktype ] [ -z postrotate-command ] [ -Z user ]
[ --immediate-mode ]
[ expression ]
參數的含義如下:
參數 | 含義 |
---|---|
-A | 以ASCII格式打印出所有分組,通常用來抓取www的網頁數據包數據。 |
-c | 在收到指定的數量的分組后,tcpdump就會停止。 |
-C | 在將一個原始分組寫入文件之前,檢查文件當前的大小是否超過了參數file_size 中指定的大小。如果超過了指定大小,則關閉當前文件,然后在打開一個新的文件。參數 file_size 的單位是兆字節(是1,000,000字節,而不是1,048,576字節)。 |
-d | 將匹配信息包的代碼以人們能夠理解的匯編格式給出。 |
-dd | 將匹配信息包的代碼以c語言程序段的格式給出。 |
-ddd | 將匹配信息包的代碼以十進制的形式給出。 |
-D | 打印出系統中所有可以用tcpdump截包的網絡接口。 |
-e | 在輸出行打印出數據鏈路層的頭部信息,也就是使用數據鏈路層的MAC數據包數據來顯示. |
-f | 將外部的Internet地址以數字的形式打印出來。 |
-F | 從指定的文件中讀取表達式,忽略命令行中給出的表達式。 |
-i | 指定監聽的網絡接口。 |
-l | 使標準輸出變為緩沖行形式,可以把數據導出到文件。 |
-L | 列出網絡接口的已知數據鏈路。 |
-b | 在數據-鏈路層上選擇協議,包括ip、arp、rarp、ipx都是這一層的。 |
-n | 不把網絡地址轉換成名字。 |
-nn | 不進行端口名稱的轉換。 |
-N | 不輸出主機名中的域名部分。例如,‘nic.ddn.mil‘只輸出’nic‘。 |
-t | 在輸出的每一行不打印時間戳。 |
-O | 不運行分組分組匹配(packet-matching)代碼優化程序。 |
-P | 不將網絡接口設置成混雜模式。 |
-q | 快速輸出。只輸出較少的協議信息。 |
-r | 從指定的文件中讀取包(這些包一般通過-w選項產生)。 |
-S | 將tcp的序列號以絕對值形式輸出,而不是相對值。 |
-s | 從每個分組中讀取最開始的snaplen個字節,而不是默認的68個字節。 |
-T | 將監聽到的包直接解釋為指定的類型的報文,常見的類型有rpc遠程過程調用)和snmp(簡單網絡管理協議)。 |
-t | 不在每一行中輸出時間戳。 |
-tt | 在每一行中輸出非格式化的時間戳 |
-ttt | 輸出本行和前面一行之間的時間差。 |
-tttt | 在每一行中輸出由date處理的默認格式的時間戳。 |
-v | 輸出一個稍微詳細的信息,例如在ip包中可以包括ttl和服務類型的信息。 |
-vv | 輸出詳細的報文信息。 |
-w | 直接將分組寫入文件中,而不是不分析并打印出來。 |
-X | 可以列出16進制以及ASCII的數據包內容,對于監聽數據包內容很有用. |
推薦的一些寫法:
tcpdump -ntv -i xxx # -n表示不將網絡地址轉化為名稱,-t不輸出時間戳,-v輸出一些比較詳細的信息(這個很好用)
三、tcpdump的表達式介紹
表達式對應命令參數中最后的可省略的expression.tcpdump利用它作為過濾報文的條件,如果一個報文滿足表 達式的條件,則這個報文將會被捕獲。如果沒有給出任何條件,則網絡上所有的信息包 將會被截獲。
表達式(expression)實際遵循的是bpf的語法,有關于bpf的相關介紹,可以查看這個頁面:
https://biot.com/capstats/bpf.html,下面的部分,基本是此頁面的翻譯.
在表達式中一般如下幾種類型的關鍵字:
表達式由一個或多個表達元組成(nt: primitive
, 表達元, 可理解為組成表達式的基本元素). 一個表達元通常由一個或多個修飾符(qualifiers
)后跟一個名字或數字表示的id組成(nt: 即, qualifiers id
).
有三種不同類型的修飾符(或者說限定符):type, dir以及 proto.
type 修飾符指定id 所代表的對象類型, id可以是名字也可以是數字. 可選的對象類型有: host, net, port 以及portrange(nt: host 表明id表示主機, net表明id是網絡, port 表明id是端口, 而portrange表明id是一個端口范圍). 如, host foo
, net 128.3
, port 20
, portrange 6000-6008
(nt: 分別表示主機foo, 網絡128.3
, 端口20
, 端口范圍 6000-6008
). 如果不指定type修飾符, id默認的修飾符為host.
dir 修飾符描述id 所對應的傳輸方向, 即發往id 還是從id 接收(nt: 而id到底指什么需要看其前面的type修飾符).可取的方向為: src, dst, src or dst, src and dst.(nt:分別表示, id是傳輸源, id是傳輸目的, id是傳輸源或者傳輸目的, id是傳輸源并且是傳輸目的). 例如, src foo
,dst net 128.3
, src or dst port ftp-data
.(nt: 分別表示符合條件的數據包中, 源主機是foo
, 目的網絡是128.3
, 源或目的端口為 ftp-data
).如果不指定dir修飾符, id 默認的修飾符為src or dst.
proto修飾符描述id所屬的協議. 常用的協議有: ether, wlan, ip, ip6, arp, rarp, tcp以及 upd.(nt | rt: ether可理解為物理以太網傳輸協議; wlan, 無線局域網協議; ip,ip6 即通常的TCP/IP協議棧中所使用的ipv4以及ipv6網絡層協議;arp, rarp 即地址解析協議, 反向地址解析協議; tcp and udp, 即通常TCP/IP協議棧中的兩個傳輸層協議).
例如, ether src foo
, arp net 128.3
, tcp port 21
, udp portrange 7000-7009
分別表示從以太網地址foo 來的數據包,發往或來自128.3網絡的arp協議數據包, 發送或接收端口為21的 tcp協議數據包, 發送或接收端口范圍為7000-7009的udp協議數據包.
如果不指定proto 修飾符, 則默認為與相應type匹配的修飾符.
例子:
-
src foo
含義是(ip or arp or rarp) src foo
(nt: 即, 來自主機foo
的ip/arp/rarp
協議數據包, 默認type
為host
). -
net bar
含義是(ip or arp or rarp) net bar
(nt: 即, 來自或發往bar
網絡的ip/arp/rarp
協議數據包). -
port 53
含義是(tcp or udp) port 53
(nt: 即, 發送或接收端口為53
的tcp/udp
協議數據包).
對于修飾符后跟id的格式,可理解為, type id是對包最基本的過濾條件: 即對包相關的主機, 網絡, 端口的限制; dir 表示對包的傳送方向的限制; proto表示對包相關的協議限制)
除以上所描述的表達元('primitive'), 還有其他形式的表達元, 并且與上述表達元格式不同. 比如: gateway, broadcast, less, greater以及算術表達式(nt: 其中每一個都算一種新的表達元). 下面將會對這些表達元進行說明.
表達元之間還可以通過關鍵字and, or以及 not 進行連接, 從而可組成比較復雜的條件表達式. 比如,
host foo and not port ftp and not port ftp-data
(nt: 其過濾條件可理解為, 數據包的主機為foo
,并且端口不是ftp(端口21) 和ftp-data(端口20, 常用端口和名字的對應可在linux 系統中的/etc/service文件中找到)).
為了表示方便, 同樣的修飾符可以被省略, 如tcp dst port ftp or ftp-data or domain
與以下的表達式含義相同tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain
.(nt: 其過濾條件可理解為,包的協議為tcp
, 目的端口為ftp
或 ftp-data
或 domain
(端口53) ).
可用的表達元
==========================================
dst host host
如果IPv4/v6 數據包的目的ip地址是host, 那么捕獲該數據包.host 可以是一個ip地址, 也可以是一個主機名.
src host host
如果IPv4/v6 數據包的源ip地址是host, 則捕獲該數據包.host 可以是一個ip地址, 也可以是一個主機名.
host host
如果IPv4/v6數據包的源或目的ip地址是host, 則捕獲該數據包.以上的幾個host 表達式之前可以添加以下關鍵字:ip, arp, rarp, 以及 ip6.比如:
ip host host
也可以表達為:
ether proto \ip and host host # 這種表達方式在下面有說明, 其中ip之前需要有\來轉義,因為ip 對tcpdump 來說已經是一個關鍵字了.
如果host是一個擁有多個IP的主機, 那么任何一個地址都會用于包的匹配(nt: 即發向host 的數據包的目的地址可以是這幾個IP中的任何一個, 從host 接收的數據包的源地址也可以是這幾個IP中的任何一個).
==========================================
ether dst ehost
如果數據包(nt: 指tcpdump 可抓取的數據包, 包括ip 數據包, tcp數據包)的以太網目標地址是ehost,則捕獲該數據包.
ehost 可以是/etc/ethers 文件中的名字或一個數字地址(nt: 可通過 man ethers 看到對/etc/ethers 文件的描述, 樣例中用的是數字地址)
ether src ehost
如果數據包的以太網源地址是ehost(mac地址), 則捕獲該數據包.
ether host ehost
如果數據包的以太網源地址或目標地址是ehost, 則捕獲該數據包..
==========================================
dst net net
如果數據包的目標地址(IPv4或IPv6格式)的網絡號字段為net, 則捕獲該數據包.
net可以是從網絡數據庫文件/etc/networks 中的名字, 也可以用數字形式的來表示.
一個數字IPv4 網絡號可以用點分四元組(比如, 192.168.1.0
), 或點分三元組(比如, 192.168.1
), 或點分二元組(比如, 172.16
), 或單一單元組(比如,10
)來表示.
這四種情況對應的網絡掩碼分別為:四元組:255.255.255.255
(這實際上已經是是一個具體的網絡地址了),三元組:255.255.255.0
, 二元組:255.255.0.0
, 一元組:255.0.0.0
.
src net net
如果數據包的源地址(IPv4或IPv6格式)的網絡號字段為 net, 則捕獲該數據包.
net net
如果數據包的源或目的地址(IPv4或IPv6格式)的網絡號字段為 net, 則捕獲該數據包.
net net mask netmask
如果數據包的源或目的ip地址的網絡掩碼與netmask匹配, 則捕獲該數據包.
此選項之前還可以配合src和dst來進一步限定數據包的來源,比如.
src net 192.168.1.0 mask 255.255.255.0
net net/len
如果數據包的源或目的地址(IPv4或IPv6格式)的屬于該網段(net/len表示的網段), 則捕獲該數據包.
此選項之前還可以配合src和dst來進一步限定數據包的來源.
src net 192.168.1.0/24 # 表示需要匹配源地址的網絡編號有24位的數據包
dst port port
如果數據包(包括ip/tcp, ip/udp, ip6/tcp or ip6/udp協議)的目的端口為port, 則捕獲該數據包.
port 可以是一個數字也可以是一個名字(相應名字可以在/etc/services 中找到該名字, 也可以通過man tcp
和man udp
來得到相關描述信息 ). 推薦使用數字.
dst port 80 # 監聽目的端口為80的數據包
src port port
如果數據包的源端口為port, 則捕獲該數據包.
port port
如果數據包的源或目的端口為port, 則捕獲該數據包.
==========================================
dst portrange port1-port2
監聽目的端口在[port1, port2]的數據包,當然,既然存在端口,那么這個數據包必然屬于ip/tcp, ip/udp, ip6/tcp 或者ip6/udp這幾種中的一種.
src portrange port1-port2
監聽源端口在[port1, port2]范圍內的數據包.
portrange port1-port2
如果數據包的源端口或目的端口在[port1,port2]這個端口范圍, 則捕獲該數據包.以上關于port 的選項都可以在其前面添加關鍵字:tcp 或者udp對數據包加以更嚴格的限定.
tcp src port 80 # 抓取源端口是80的tcp數據包
==========================================
less length
如果數據包的長度比length 小或等于length, 則捕獲該數據包. 這與len <= length
的含義一致.
greater length
如果數據包的長度比length 大或等于length, 則捕獲該數據包. 這與len >= length
的含義一致.
==========================================
ip proto protocol
如果數據包為ipv4數據包并且其協議類型為protocol, 則與此對應的條件表達式為真.protocol可以是一個數字也可以是名字, 比如:icmp, pim, udp, tcp等. 由于tcp , udp 以及icmp是tcpdump 的關鍵字,所以在這些協議名字之前必須要用\來進行轉義(如果在C-shell 中需要用\來進行轉義). 有時候為了書寫方便,我們可以直接用tcp, upd, icmp來替換,這個其實是
ip proto p or ip6 proto p
的縮寫,p指代tcp,upd以及icmp.
tcpdump -i eth0 'ip proto \tcp and host 192.168.3.144
則只打印主機192.168.3.144
發出或接收的數據包中tcp 協議頭所包含的信息)
==========================================
ether broadcast
如果數據包是以太網廣播數據包, 則捕獲該數據包. ether 關鍵字是可選的.
ip broadcast
如果數據包是IPv4廣播數據包, 則捕獲該數據包.
==========================================
ether multicast
如果數據包是一個以太網多點廣播數據包,則捕獲該數據包.關鍵字ether可以省略.
ip multicast
如果數據包是ipv4多點廣播數據包, 則捕獲該數據包.
==========================================
ether proto protocol
如果數據包屬于以下以太協議類型, 則與此對應的條件表達式為真.協議(protocol)字段, 可以是數字或以下所列出的名字: ip, ip6, arp, rarp, stp(Spanning tree protocol, 生成樹協議, 可用于防止網絡中產生鏈接循環)等.必須要注意的是如果標識符也是關鍵字, 從而必須通過\來進行轉義.
有時候為了書寫方便,我們往往直接使用ip, ip6, arp, rarp, aarp, decnet, stp來代替,它們其實是
ether proto p
的一個省略形式,p表示ip, ip6...
expr relop expr
如果關系為真,就抓取此類數據包. relop可以是>, <, >=, <=, =, !=之一, expr是一個算數表達式,它由整數常量,常規的二進制操作符,如[+, -, *, /, &, |, <<, >>],長度操作符,包數據訪問器組成.值得注意的是,所有的組成部分都是無符號的,舉個例子, 0x80000000 and 0xffffffff 大于0.可以使用下面的語法,來獲取包中的數據:
proto [ expr : size ]
proto字段可以是 ether, fddi, wlan, ip, arp, rarp, tcp, udp, icmp, ip6等協議的名稱,expr用于描述比特偏移,size是可選的,表示我們只對從偏移處開始的size字節的數據感興趣,如果沒有的話,默認值為1.
舉個例子, ether[0] & 1 != 0
可以抓取所有的多播流量,表達式ip[0] & 0xf != 5
可以抓取到所有的帶選項的ipv4包,表達式ip[6:2] & 0x1fff = 0
可以抓取到所有未分片的ipv4包以及第一個ipv4分片包.
一些偏移量以及字段的值可以用名稱來直接描述,比如說icmptype (ICMP type字段), icmpcode (ICMP code字段), 以及tcpflags (TCP flags字段).
以下的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 flags字段的值是合法的: tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-ack, tcp-urg.
四、輸出結果介紹
下面我們介紹幾種典型的tcpdump命令的輸出信息
(1) 數據鏈路層頭信息
使用命令:
#tcpdump --e host ICE
ICE是一臺裝有linux的主機。它的MAC地址是0:90:27:58:AF:1A
, H219是一臺裝有Solaris的SUN工作站。它的MAC地址是8:0:20:79:5B:46
.
上一條命令的輸出結果如下所示:
21:50:12.847509 eth0 < 8:0:20:79:5b:46 0:90:27:58:af:1a ip 60: h219.33357 > ICE. telne t 0:0(0) ack 22535 win 8760 (DF)
21:50:12
是顯示的時間, 847509
是ID號,eth0 >
表示從網絡接口eth0
接收該分組, 同理eth0 >
表示從網絡接口設備eth0
發送分組,8:0:20:79:5b:46
是主機H219的MAC地址, 它表明是從源地址H219發來的分組.0:90:27:58:af:1a
是主機ICE的MAC地址, 表示該分組的目的地址是ICE。 ip
是表明該分組是IP分組,60
是分組的長度, h219.33357 > ICE. telnet
表明該分組是從主機H219的33357
端口發往主機ICE的 TELNET(23)端口。 ack 22535
表明對序列號是222535的包進行響應。 win 8760
表明發 送窗口的大小是8760。
(2) ARP包的tcpdump輸出信息
使用命令:
#tcpdump arp
得到的輸出結果是:
22:32:42.802509 eth0 > arp who-has route tell ICE (0:90:27:58:af:1a)
22:32:42.802902 eth0 < arp reply route is-at 0:90:27:12:10:66 (0:90:27:58:af:1a)
22:32:42是時間戳, 802509是ID號, eth0 >表明從主機發出該分組,arp表明是ARP請求包, who-has route tell ICE表明是主機ICE請求主機route的MAC地址。 0:90:27:58:af:1a 是主機 ICE的MAC地址。
(3) TCP包的輸出信息
用tcpdump捕獲的TCP包的一般輸出信息是:
src > dst: flags data-seqno ack window urgent options
src > dst:表明從源地址到目的地址, flags是TCP報文中的標志信息,具體描述如下:
標識 | 字符縮寫 | 描述 |
---|---|---|
S | SYN | 同步標識 |
F | FIN | 終止標識 |
R | RST | 復位標識 |
P | PSH | 推送標識 |
. | 以上四個標識bit全部為0 |
data-seqno是報文中的數據的順序號, ack是下次期望的順序號, window是接收緩存的窗口大小, urgent表明 報文中是否有緊急指針。 Options是選項。
(4) UDP包的輸出信息
用tcpdump捕獲的UDP包的一般輸出信息是:
route.port1 > ICE.port2: udp lenth
UDP十分簡單,上面的輸出行表明從主機route的port1端口發出的一個UDP報文 到主機ICE的port2端口,類型是UDP, 包的長度是lenth。
五、舉例
(1) 想要截獲所有210.27.48.1 的主機收到的和發出的所有的分組:
#tcpdump host 210.27.48.1
(2) 想要截獲主機210.27.48.1 和主機210.27.48.2或210.27.48.3的通信,使用命令(注意:括號前的反斜杠是必須的):
#tcpdump host 210.27.48.1 and \(210.27.48.2 or 210.27.48.3 \)
(3) 如果想要獲取主機210.27.48.1除了和主機210.27.48.2之外所有主機通信的ip包,使用命令:
#tcpdump ip host 210.27.48.1 and ! 210.27.48.2
(4) 如果想要獲取主機192.168.228.246接收或發出的ssh包,并且不轉換主機名使用如下命令:
#tcpdump -nn -n src host 192.168.228.246 and port 22 and tcp
(5) 獲取主機192.168.228.246接收或發出的ssh包,并把mac地址也一同顯示:
# tcpdump -e src host 192.168.228.246 and port 22 and tcp -n -nn
(6) 過濾的是源主機為192.168.0.1與目的網絡為192.168.0.0的報頭:
tcpdump src host 192.168.0.1 and dst net 192.168.0.0/24
(7) 過濾源主機物理地址為XXX的報頭:
tcpdump ether src 00:50:04:BA:9B and dst……
(為什么ether src后面沒有host或者net?物理地址當然不可能有網絡嘍)。
(8) 過濾源主機192.168.0.1和目的端口不是telnet的報頭,并導入到tes.t.txt文件中:
Tcpdump src host 192.168.0.1 and dst port not telnet -l > test.txt
ip icmp arp rarp 和 tcp、udp、icmp這些選項等都要放到第一個參數的位置,用來過濾數據報的類型。
六.man手冊中的一些例子
打印所有進入或離開主機sundown的數據包.
tcpdump host sundown
打印主機helios 與主機** hot** 或者與 主機ace 之間通信的數據包
tcpdump host helios and \( hot or ace \)
打印主機ace 與 任何其他主機之間通信的IP 數據包, 但不包括與helios之間的數據包.
tcpdump ip host ace and not helios
打印本地主機與Berkeley網絡上的主機之間的所有通信數據包.
tcpdump net ucb-ether
打印所有源地址或目標地址是本地主機的IP數據包(如果本地網絡通過網關連到了另一網絡, 則另一網絡并不能算作本地網絡.localnet在 實際使用時要真正替換成本地網絡的名字.
tcpdump ip and not net localnet
打印長度超過576字節, 并且網關地址是snup的IP數據包
tcpdump 'gateway snup and ip[2:2] > 576'
以下列出了tcp, ip頭的結構, 以方便查看(需要以等寬字體查看).
TCP 頭格式(rfc793)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
IPV4 頭格式(rfc791)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
七.輸出格式
tcpdump 的輸出格式與協議有關. 以下簡要描述了大部分常用的格式及相關例子.
鏈路層頭
ARP/RARP 數據包
tcpdump對arp/rarp包的輸出信息中會包含請求類型及該請求對應的參數. 顯示格式簡潔明了. 以下是從主機rtsg到主機csam的rlogin
(遠程登錄)過程開始階段的數據包樣例:
arp who-has csam tell rtsg
arp reply csam is-at CSAM
第一行表示:rtsg
發送了一個arp數據包(nt:向全網段發送,arp數據包)以詢問csam
的以太網地址,csam以她自己的以太網地址做了回應(在這個例子中, 以太網地址以大寫的名字標識, 而internet地址(即ip地址)以全部的小寫名字標識).
如果使用tcpdump -n
, 可以清晰看到以太網以及ip地址而不是名字標識:
arp who-has 128.3.254.6 tell 128.3.254.68
arp reply 128.3.254.6 is-at 02:07:01:00:01:c4
如果我們使用tcpdump -e
, 則可以清晰的看到第一個數據包是全網廣播的, 而第二個數據包是點對點的:
RTSG Broadcast 0806 64: arp who-has csam tell rtsg
CSAM RTSG 0806 64: arp reply csam is-at CSAM
第一個數據包表明:以arp包的源以太地址是RTSG, 目標地址是全以太網段, type域的值為16進制0806(表示ETHER_ARP即arp包的類型標識).包的總長度為64字節.
TCP 數據包
通常tcpdump對tcp數據包的顯示格式如下:
src > dst: flags data-seqno ack window urgent options
src 和 dst 是源和目的IP地址以及相應的端口. flags 標志由S(SYN), F(FIN), P(PUSH, R(RST)等組成,
單獨一個.
表示沒有flags標識. 數據段順序號(Data-seqno)描述了此包中數據所對應序列號空間中的一個位置.
ack描述的是同一個連接,同一個方向,下一個本端應該接收的(對方應該發送的)數據片段的順序號.
window是本端可用的數據接收緩沖區的大小(也是對方發送數據時需根據這個大小來組織數據).
urg(urgent) 表示數據包中有緊急的數據. options 描述了tcp的一些選項, 這些選項都用尖括號來表示(如 <mss 1024>
).
src, dst 和 flags 這三個域總是會被顯示. 其他域的顯示與否依賴于tcp協議頭里的信息.
下面是一個從主機trsg到csam的一個rlogin應用登錄的開始階段.
rtsg.1023 > csam.login: S 768512:768512(0) win 4096 <mss 1024>
csam.login > rtsg.1023: S 947648:947648(0) ack 768513 win 4096 <mss 1024>
rtsg.1023 > csam.login: . ack 1 win 4096
rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096
csam.login > rtsg.1023: . ack 2 win 4096
rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096
csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077
csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1
csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1
第一行表示有一個數據包從rtsg主機的tcp端口1023發送到了csam主機的tcp端口login上. S表示設置了SYN標志. 包的順序號是768512, 并且沒有包含數據.
如果包含有數據,那么數據的表示格式為:first:last(nbytes)
, 其含義是此包中數據的順序號從first開始直到last結束,不包括last. 并且總共包含nbytes的用戶數據.
沒有捎帶應答即ack, 可用的接受窗口的大小為4096bytes, 并且請求端(rtsg)的最大可接受的數據段大小是1024字節.
主機csam 向主機rtsg 回復了基本相同的SYN數據包, 其區別只是多了一個piggy-backed ack
(nt:捎帶回的ack應答, 針對rtsg的SYN數據包).
rtsg 同樣針對csam的SYN數據包回復了一ACK數據包作為應答. .
的含義就是此包中沒有標志被設置. 由于此應答包中不含有數據, 所以包中也沒有數據段序列號.
提醒! 此ACK數據包的順序號只是一個小整數1. 有如下解釋:tcpdump對于一個tcp連接上的會話, 只打印會話兩端的初始數據包的序列號,其后相應數據包只打印出與初始包序列號的差異.即初始序列號之后的序列號, 可被看作此會話上當前所傳數據片段在整個要傳輸的數據中的'相對字節'位置(nt:雙方的第一個位置都是1, 即'相對字節'的開始編號). -S
將覆蓋這個功能,使數據包的原始順序號被打印出來.
第六行的含義為:主機rtsg 向 主機csam發送了19字節的數據(字節的編號為2到20,傳送方向為rtsg到csam). 包中設置了PUSH標志.
在第7行,主機csam回應道, 她已經從主機rtsg中收到了21以下的字節, 但不包括21編號的字節. 這些字節存放在主機csam的socket的接收緩沖中, 相應地,csam的接收緩沖窗口大小會減少19字節(nt:可以從第5行和第7行win屬性值的變化看出來). csam在第7行這個包中也向rtsg發送了一個字節. 在第8行和第9行, csam 繼續向rtsg 分別發送了兩個只包含一個字節的數據包, 并且這個數據包帶PUSH標志.
如果頭部含有虛假的屬性信息(比如其長度屬性其實比頭部實際長度長或短), tcpdump會為該頭部顯示[bad opt]
.
如果頭部的長度告訴我們某些選項(nt | rt:從下文來看, 指tcp包的頭部中針對ip包的一些選項, 回頭再翻)會在此包中,而真正的IP(數據包的長度又不夠容納這些選項, tcpdump會顯示[bad hdr length]
.
UDP 數據包
UDP 數據包的顯示格式,可通過rwho這個具體應用所產生的數據包來說明:
actinide.who > broadcast.who: udp 84
其含義為:actinide主機上的端口who向broadcast主機上的端口who發送了一個udp數據包.這個數據包包含有84個字節的用戶數據.
一些UDP服務可通過數據包的源或目的端口來辨別,也可從所顯示的更高層協議信息來識別. 比如, Domain Name service requests(DNS 請求).
UDP 名稱服務請求
名稱服務請求有如下的格式:
src > dst: id op? flags qtype qclass name (len)
比如有一個實際顯示為:
h2opolo.1538 > helios.domain: 3+ A? ucbvax.berkeley.edu. (37)
主機h2opolo 向主機helios 上運行的名稱服務器查詢ucbvax.berkeley.edu
的地址記錄(nt: qtype等于A). 此查詢本身的id號為3
.
符號+
意味著遞歸查詢標志被設置(nt: dns服務器可向更高層dns服務器查詢本服務器不包含的地址記錄). 這個最終通過IP包發送的查詢請求數據長度為37字節, 其中不包括UDP和IP協議的頭數據.
因為此查詢操作為默認值(nt | rt: normal one的理解), op字段被省略.如果op字段沒被省略, 會被顯示在3
和+
之間. 同樣, qclass也是默認值, C_IN, 從而也沒被顯示, 如果沒被忽略, 她會被顯示在A
之后.
UDP 名稱服務應答
對名稱服務應答的數據包,tcpdump會有如下的顯示格式
src > dst: id op rcode flags a/n/au type class data (len)
比如具體顯示如下:
helios.domain > h2opolo.1538: 3 3/3/7 A 128.32.137.3 (273)
helios.domain > h2opolo.1537: 2 NXDomain* 0/1/0 (97)
第一行表示: 主機helios 對主機h2opolo所發送的3號查詢請求回應了3條回答記錄(nt | rt: answer records), 3條名稱服務器記錄,以及7條附加的記錄. 第一個回答記錄(nt: 3個回答記錄中的第一個)類型為A(nt: 表示地址), 其數據為internet地址128.32.137.3
.此回應UDP數據包, 包含273字節的數據(不包含UPD和IP的頭部數據). op字段和rcode字段被忽略(nt: op的實際值為Query, rcode, 即response code的實際值為NoError), 同樣被忽略的字段還有class 字段(nt | rt: 其值為C_IN, 這也是A類型記錄默認取值)
第二行表示: helios對h2opolo所發送的2號查詢請求做了回應. 回應中, rcode編碼為NXDomain(nt: 表示不存在的域)), 沒有回答記錄,但包含一個名稱服務器記錄, 不包含權威服務器記錄(nt | ck: 從上文來看, 此處的authority records 就是上文中對應的additional records).
*
表示權威服務器回答標志被設置(nt: 從而additional records就表示的是authority records).
由于沒有回答記錄, type, class, data字段都被忽略.
flag字段還有可能出現其他一些字符, 比如-
(nt: 表示可遞歸地查詢, 即RA 標志沒有被設置), |
(nt: 表示被截斷的消息, 即TC 標志被置位). 如果應答(nt | ct: 可理解為, 包含名稱服務應答的UDP數據包, tcpdump知道這類數據包該怎樣解析其數據)的'question'段一個條目(entry)都不包含(nt: 每個條目的含義, 需補充),'[nq]' 會被打印出來.
要注意的是:名稱服務器的請求和應答數據量比較大, 而默認的68字節的抓取長度(nt: snaplen, 可理解為tcpdump的一個設置選項)可能不足以抓取數據包的全部內容. 如果你真的需要仔細查看名稱服務器的負載, 可以通過tcpdump 的-s 選項來擴大snaplen值.
IP 數據包分片
IP分片數據包(nt: 即一個大的IP數據包切分后生成的小IP數據包)有如下兩種顯示格式.
(frag id:size@offset+)
(frag id:size@offset)
(第一種格式表示, 此分片之后還有后續分片. 第二種格式表示, 此分片為最后一個碎片.)
id 表示分片的編號( 每個小IP包被分配一個分片編號, 以便區分各個小分片).
size表示此分片的大小 , 不包含分片頭部數據.
offset表示此分片所含數據在原始整個IP包中的偏移.
每個分片都會使tcpdump產生相應的輸出打印. 第一個分片包含了高層協議的頭數據(nt:從下文來看, 被破碎IP數據包中相應tcp頭以及IP頭都放在了第一個碎片中 ), 從而tcpdump會針對第一個分片顯示這些信息, 并接著顯示此分片本身的信息. 其后的一些分片并不包含高層協議頭信息, 從而只會在顯示源和目的之后顯示分片本身的信息. 以下有一個例子:
這是一個從arizona.edu
到lbl-rtsg.arpa
途經CSNET網絡的ftp應用通信片段:
arizona.ftp-data > rtsg.1170: . 1024:1332(308) ack 1 win 4096 (frag 595a:328@0+)
arizona > rtsg: (frag 595a:204@328)
rtsg.1170 > arizona.ftp-data: . ack 1536 win 2560
有幾點值得注意:
第一, 第二行的打印中, 地址后面沒有端口號.
這是因為TCP協議信息都放到了第一個分片中, 當顯示第二個分片時, 我們無法知道此分片所對應TCP包的順序號.
第二, 從第一行的信息中, 可以發現主機arizona向rtsg發送308字節的用戶數據, 而事實是, 相應IP包經分片后會總共產生512字節數據(第一個分片包含308字節的數據, 第二個分片包含204個字節的數據, 這超過了308字節).
如果你在查找數據包的順序號空間中的一些空洞(nt: hole,空洞, 指數據包之間的順序號沒有上下銜接上), 512這個數據就足夠使你迷茫一陣(nt: 其實只要關注308就行,不必關注分片后的數據總量).
一個IP數據包如果帶有非IP分片標志, 則顯示時會在最后顯示(DF).
時間戳
tcpdump的所有輸出打印行中都會默認包含時間戳信息.
時間戳信息的顯示格式如下
hh:mm:ss.frac (nt: 小時:分鐘:秒.(nt: frac未知, 需補充))
此時間戳的精度與內核時間精度一致, 反映的是內核第一次看到對應數據包的時間(nt: saw, 即可對該數據包進行操作). 而數據包從物理線路傳遞到內核的時間, 以及內核花費在此包上的中斷處理時間都沒有算進來.