Tcpdump 打印出 在某個 網絡界面 上, 匹配 布爾表達式 expression 的 報頭.
對于 SunOS 的 nit 或 bpf 界面: 要 運行 tcpdump , 你 必須 有 /dev/nit 或 /dev/bpf* 的 讀訪問 權限.
對于 Solaris 的 dlpi: 你 必須 有 網絡仿真設備 (network pseudo device), 如 /dev/le 的 讀訪問 權限.
對于 HP-UX 的 dlpi: 你 必須 是 root, 或者 把它 安裝成 root 的 設置uid 程序. 對于 IRIX 的 snoop: 你 必須 是 root, 或者 把它 安裝成 root 的 設置uid 程序. 對于 Linux: 你 必須 是 root, 或者 把它 安裝成 root 的 設置uid 程序.
對于 Ultrix 和 Digital UNIX: 一旦 超級用戶 使用 pfconfig(8) 開放了 promiscuous 操作模式 (promiscuous-mode), 任何用戶 都可以 運行 tcpdump.
對于 BSD: 你 必須 有 /dev/bpf* 的 讀訪問 權限.
expression 一個或多個 原語 (primitive) 組成. 原語 通常 由 一個 標識 (id, 名稱或數字), 和 標識 前面的 一個或多個 修飾子(qualifier) 組成. 修飾子 有 三種 不同的類型:
[`fddi' 實際上 是 `ether' 的 別名; 分析器 把 它們 視為 ``用在 指定 網絡接口 上的 數據鏈路層.'' FDDI 報頭 包含 類似于 以太協議的 源目地址, 而且 通常 包含 類似于 以太協議 的 報文類型, 因此 你 可以過濾 FDDI 域, 就象 分析 以太協議 一樣. FDDI 報頭 也 包含 其他 域, 但是你 不能 在 過濾器 表達式 里 顯式描述.]
作為 上述 的 補充, 有一些 特殊的 `原語' 關鍵字, 它們 不同于 上面的模式: gateway, broadcast, less, greater 和 數學表達式. 這些 在 后面 有 敘述.
更復雜的 過濾器表達式 可以 通過 and, or 和 not 連接 原語 來 組建. 例如, `host foo and not port ftp and not port ftp-data'. 為了少敲點鍵, 可以忽略 相同的 修飾子. 例如, `tcp dst port ftp or ftp-data or domain' 實際上 就是 `tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
允許的 原語 有:
ip host host它等價于:
ether proto \ip and host host如果 host 是 擁有 多個 IP 地址 的 主機名, 它的 每個地址 都會 被查驗.
ether host ehost and not host host對于 host / ehost, 它既可以是 名字, 也可以是 數字.)
tcp src port port它 只匹配 源端口 是 port 的 TCP 報文.
len <= length.
len >= length.
ether proto p的 簡寫 形式, 其中 p 為 上述 協議 的 一種.
ether proto p的 簡寫 形式, 其中 p 為 上述 協議 的 一種. 注意 tcpdump 目前 不知道 如何 分析 這些 協議.
ip proto p的 簡寫 形式, 其中 p 為 上述 協議 的 一種.
proto [ expr : size ]Proto 是 ether, fddi, ip, arp, rarp, tcp, udp, or icmp 之一, 同時 也指出了 下標 操作 的協議層. expr 給出 字節單位 的 偏移量, 該 偏移量 相對于 指定的 協議層. Size 是 可選項, 指出 感興趣的 字節數; 它可以 是 1, 2, 4, 缺省為 1 字節. 由 關鍵字 len 給出的 長度運算符 指明 報文 的 長度.
例如, `ether[0] & 1 != 0' 捕捉 所有的 多目傳送 報文. 表達式 `ip[0] & 0xf != 5' 捕捉 所有 帶 可選域 的 IP 報文. 表達式 `ip[6:2] & 0x1fff = 0' 只捕捉 未分片 和 片偏移為0 的 數據報. 這種 檢查 隱含在 tcp 和 udp 下標操作 中. 例如, tcp[0] 一定是 TCP 報頭 的 第一個 字節, 而不是 其中 某個 IP片 的 第一個 字節.
原語 可以 用 下述 方法 結合使用:
取反操作 有 最高優先級. 或操作 和 連結操作 有 相同的 優先級, 運算時 從左到右 結合. 注意 連結操作 需要 顯式的 and 算符, 而不是 并列放置.
如果 給出 標識符, 但沒給 關鍵字, 那么 暗指 最近使用 的 關鍵字. 例如,
not host vs and ace作為
not host vs and host ace的 簡寫形式, 不應該 和
not ( host vs or ace )混淆.
表達式參數 可以 作為 單個 參數 傳給 tcpdump, 也可以 作為 復合參數, 后者 更方便 一些. 一般說來, 如果 表達式 包含 Shell 元字符(metacharacter), 傳遞 單個 括起來的 參數 要 容易 一些. 復合參數 在 被解析前 用 空格 聯接 一起.
顯示 所有 進出 sundown 的 報文:
tcpdump host sundown
顯示 helios 和 主機 hot, ace 之間 的 報文 傳送:
tcpdump host helios and \( hot or ace \)
顯示 ace 和 除了 helios 以外的 所有 主機 的 IP報文:
tcpdump ip host ace and not helios
顯示 本地的主機 和 Berkeley的主機 之間 的 網絡數據:
tcpdump net ucb-ether
顯示 所有 通過 網關 snup 的 ftp 報文 (注意 這個 表達式 被 單引號 括起, 防止 shell 解釋 園括弧):
tcpdump 'gateway snup and (port ftp or ftp-data)'
顯示 既不是 來自 本地主機, 也不是 傳往 本地主機 的 網絡數據 (如果 你 把 網關 通往 某個 其他網絡, 這個 做法 將不會 把 數據 發往 你的本地網絡).
tcpdump ip and not net localnet
顯示 每個 TCP會話 的 起始 和 結束 報文 (SYN 和 FIN 報文), 而且 會話方 中有一個 遠程主機.
tcpdump 'tcp[13] & 3 != 0 and not src and dst net localnet'
顯示 經過 網關 snup 中 大于 576 字節的 IP 數據報:
tcpdump 'gateway snup and ip[2:2] > 576'
顯示 IP 廣播 或 多目傳送 的 數據報, 這些 報文 不是 通過 以太網 的 廣播 或 多目傳送 形式 傳送的:
tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'
顯示 所有 不是 回響請求/應答 的 ICMP 報文 (也就是說, 不是 ping 報文):
tcpdump 'icmp[0] != 8 and icmp[0] != 0"
tcpdump 的 輸出格式 取決于 協議. 下面的 描述 給出 大多數 格式 的簡要說明 和 范例.
鏈路層報頭 (Link Level Headers)
如果 給出 '-e' 選項 就 顯示 鏈路層報頭. 在 以太網上, 顯示 報文的 源目地址, 協議 和 報文長度.
在 FDDI 網絡上, '-e' 選項 導致 tcpdump 顯示出 `幀控制(frame control)' 域, 源目地址 和 報文長度. (`幀控制' 域 負責 解釋 其余的 報文. 普通報文 (比如說 載有 IP數據報) 是 `異步' 報文, 優先級 介于 0 到 7; 例如, `async4'. 這些 被認為 載有 802.2 邏輯鏈路控制(LLC) 報文; 如果 它們 不是 ISO 數據報 或者 所謂的 SNAP 報文, 就顯示出 LLC 報頭.
(注意: 以下 描述中 假設 你 熟悉 RFC-1144 中說明的 SLIP 壓縮算法.)
在 SLIP 鏈路上, tcpdump 顯示出 方向指示 (``I'' 指 inbound, ``O'' 指 outbound), 報文類型 和 壓縮信息. 首先顯示的 是 報文類型. 有三種 類型 ip, utcp 和 ctcp. 對于 ip 報文 不再 顯示 更多的 鏈路信息. 對于 TCP 報文, 在 類型 后面 顯示 連接標識. 如果 報文 是 壓縮過的, 就顯示出 編碼的報頭. 特殊 情形 以 *S+n 和 *SA+n 的 形式 顯示, 這里的 n 是 順序號 (或順序號 及其 確認) 發生 的 改變 總和. 如果 不是 特殊 情形, 就顯示 0 或 多少個 改變. 改變 由 U (urgent pointer), W (window), A (ack), S (sequence number) 和 I (packet ID) 指明, 后跟 一個 變化量(+n or -n), 或 另一個 值(=n). 最后顯示 報文中 的 數據總和, 以及 壓縮報頭 的 長度.
例如, 下面一行 顯示了 一個 傳出的 壓縮的 TCP 報文, 有一個 隱含的 連接標識; 確認(ack)的 變化量是 6, 順序號 是 49, 報文ID 是 6; 有三個字節的數據 和六個字節 的 壓縮報頭:
O ctcp * A+6 S+49 I+6 3 (6)
ARP/RARP 報文
Arp/rarp 報文 的 輸出 顯示 請求類型 及其 參數. 輸出格式 傾向于 能夠 自我解釋. 這里 是一個 簡單的例子, 來自 主機 rtsg 到 主機 csam 的 'rlogin' 開始 部分:
arp who-has csam tell rtsgarp reply csam is-at CSAM
如果 用 tcpdump -n 看上去 要 清楚一些:
arp who-has 128.3.254.6 tell 128.3.254.68arp reply 128.3.254.6 is-at 02:07:01:00:01:c4
如果 用 tcpdump -e, 可以 看到 實際上 第一個 報文 是 廣播, 第二個報文 是 點到點 的:
RTSG Broadcast 0806 64: arp who-has csam tell rtsgCSAM RTSG 0806 64: arp reply csam is-at CSAM
TCP 報文
(注意: 以下的描述中 假設 你 熟悉 RFC-793 中 說明的 TCP 協議, 如果 你不了解 這個 協議, 無論是 本文 還是 tcpdump 都對你 用處 不大)
一般說來 tcp 協議的 輸出格式是:
src > dst: flags data-seqno ack window urgent options
Src, dst 和 flags 肯定 存在. 其他域 依據 報文的 tcp 報頭 內容, 只輸出 有必要 的 部分.
下面 是 從 主機 rtsg rlogin 到 主機 csam 的 開始部分.
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 4096rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096csam.login > rtsg.1023: . ack 2 win 4096rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1
Csam 用類似的 形式 應答, 只是 增加了 一個 對 rtsg SYN 的 捎帶確認. 然后 Rtsg 確認 csam 的 SYN. `.' 意味著 沒有 設置 標志. 這個 報文 不包含 數據, 因此 也就 沒有 數據的流序號. 注意這個 確認流序號 是一個 小整數(1). 當 tcpdump 第一次 發現 一個 tcp 會話時, 它 顯示 報文 攜帶的 流序號. 在 隨后收到的 報文里, 它 顯示 當前報文 和 最初那個 報文 的 流序號 之 差. 這 意味著 從第一個報文 開始, 以后的 流序號 可以 理解成 數據流 中的 相對位移 as relative byte positions in the conversation's data stream (with the first data byte each direction being `1'). `-S' 選項 能夠 改變 這個 特性, 直接 顯示 原始的 流序號.
在 第六行, rtsg 傳給 csam 19 個字節 的 數據 (字節 2 到 20). 報文中 設置了 PUSH 標志. 第七行 csam 表明 它 收到了 rtsg 的 數據, 字節序號是 21, 但不包括 第21個 字節. 顯然 大多數 數據 在 socket 的 緩沖區內, 因為 csam 的 接收窗口 收到的 數據小于 19 個 字節. 同時 csam 向 rtsg 發送了 一個字節 的 數據. 第八和第九行 顯示 csam 發送了 兩個字節 的 緊急數據 到 rtsg.
如果 捕捉區 設置的 過小, 以至于 tcpdump 不能 捕捉到 完整的 TCP 報頭, tcpdump 會 盡可能的 翻譯 已捕獲的 部分, 然后 顯示 ``[|tcp]'', 表明 無法 翻譯 其余 部分. 如果 報頭 包含 一個 偽造的 選項 (one with a length that's either too small or beyond the end of the header), tcpdump 顯示 ``[bad opt]'' 并且 不再 翻譯 其他 選項部分 (因為 它 不可能 判斷出從哪兒 開始). 如果 報頭長度 表明 存在 選項, 但是 IP 數據報 長度 不夠, 不可能 真的 保存 選項, tcpdump 就顯示 ``[bad hdr length]''.
UDP 報文
UDP 格式 就象 這個 rwho 報文 顯示的:
actinide.who > broadcast.who: udp 84
某些 UDP 服務 能夠 識別出來(從 源目端口號 上), 因而 顯示出 更高層的 協議信息. 特別是 域名服務請求(RFC-1034/1035) 和 NFS 的 RPC 調用(RFC-1050).
UDP 域名服務請求 (Name Server Requests)
(注意: 以下的描述中 假設 你 熟悉 RFC-1035 說明的 域名服務協議. 如果你 不熟悉 這個協議, 下面的內容 就象是 天書.)
域名服務請求 的 格式 是
src > dst: id op? flags qtype qclass name (len)h2opolo.1538 > helios.domain: 3+ A? ucbvax.berkeley.edu. (37)
Tcpdump 會檢查 一些 不規則 情況, 相應的 結果 作為 補充域 放在 方括號內: 如果 某個 查詢 包含 回答, 名字服務 或 管理機構部分, 就把 ancount, nscount, 或 arcount 顯示成 `[na]', `[nn]' 或 `[nau]', 這里的 n 代表 相應的 數量. 如果 在 第二和第三字節 中, 任何一個 回答位(AA, RA 或 rcode) 或 任何一個 `必須為零' 的位 被 置位, 就顯示 `[b2&3=x]', 這里的 x 是 報頭 第二和第三字節 的 16進制數.
UDP 名字服務回答
名字服務回答的 格式 是
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 對 標識為2 的 詢問 作出 域名不存在 (NXDomain) 的 回答, 沒有 回答記錄, 一個 名字服務記錄, 而且 沒有 管理結構.
`*' 表明 設置了 權威回答(authoritative answer). 由于 沒有 回答記錄, 這里就 不顯示 type, class 和 data.
其他 標志 字符 可以 顯示為 `-' (沒有設置遞歸有效(RA)) 和 `|' (設置 消息截短(TC)). 如果 `問題' 部分 沒有 有效的 內容, 就 顯示 `[nq]'.
注意 名字服務的 詢問和回答 一般說來 比較大, 68 字節的 snaplen 可能無法 捕捉到 足夠的 報文內容. 如果 你 的確 在 研究 名字服務 的 情況, 可以使用 -s 選項 增大 捕捉緩沖區. `-s 128' 應該 效果 不錯了.
NFS 請求和響應
Sun NFS (網絡文件系統) 的 請求和響應 顯示格式 是:
src.xid > dst.nfs: len op argssrc.nfs > dst.xid: reply stat len op resultssushi.6709 > wrl.nfs: 112 readlink fh 21,24/10.73165wrl.nfs > sushi.6709: reply ok 40 readlink "../var"sushi.201b > wrl.nfs: 144 lookup fh 9,74/4096.6878 "xcolors"wrl.nfs > sushi.201b: reply ok 128 lookup fh 9,74/4134.3150
在第三行, sushi 請求 wrl 在 目錄文件 9,74/4096.6878 中 查找 `xcolors'. 注意 數據的 打印格式 取決于 操作類型. 格式 應該是 可以自我說明的.
給出 -v (verbose) 選項 可以 顯示 附加信息. 例如:
sushi.1372a > wrl.nfs: 148 read fh 21,11/12.195 8192 bytes @ 24576wrl.nfs > sushi.1372a: reply ok 1472 read REG 100664 ids 417/0 sz 29388
如果再給一個 -v 選項 (-vv), 還能 顯示 更多的細節.
注意 NFS 請求 的 數據量 非常大, 除非 增加 snaplen, 否則 很多細節 無法顯示. 試一試 `-s 192' 選項.
NFS 應答報文 沒有明確 標明 RPC 操作. 因此 tcpdump 保留有 ``近來的'' 請求 記錄, 根據 交易號 匹配 應答報文. 如果 應答報文 沒有 相應的 請求報文, 它 就 無法分析.
KIP Appletalk (UDP 上的 DDP)
Appletalk DDP 報文 封裝在 UDP 數據報 中, 解包后 按 DDP 報文 轉儲 (也就是說, 忽略 所有的 UDP 報頭 信息). 文件 /etc/atalk.names 用來 把 appletalk 網絡和節點號 翻譯成 名字. 這個文件 的 行格式 是
number name1.254 ether16.1 icsd-net1.254.110 ace
Appletalk 地址 按 這個格式 顯示
net.host.port144.1.209.2 > icsd-net.112.220office.2 > icsd-net.112.220jssmag.149.235 > icsd-net.2
Tcpdump 可以 翻譯 NBP (名字聯結協議) 和 ATP (Appletalk 交互協議) 的 報文內容. 其他協議 只轉儲 協議名稱 (或號碼, 如果 還 沒給 這個協議 注冊 名稱) 和 報文大小.
NBP 報文 的 輸出格式 就象 下面的 例子:
icsd-net.112.220 > jssmag.2: nbp-lkup 190: "=:LaserWriter@*"jssmag.209.2 > icsd-net.112.220: nbp-reply 190: "RM1140:LaserWriter@*" 250techpit.2 > icsd-net.112.220: nbp-reply 190: "techpit:LaserWriter@*" 186
ATP 報文 格式 如 下例 所示:
jssmag.209.165 > helios.132: atp-req 12266<0-7> 0xae030001helios.132 > jssmag.209.165: atp-resp 12266:0 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:1 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:2 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:4 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:6 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp*12266:7 (512) 0xae040000jssmag.209.165 > helios.132: atp-req 12266<3,5> 0xae030001helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000jssmag.209.165 > helios.132: atp-rel 12266<0-7> 0xae030001jssmag.209.133 > helios.132: atp-req* 12267<0-7> 0xae030002
Helios 用 8 個 512字節 的 報文 應答. 跟在 交易號 后面的 `:digit' 給出了 交易過程中 報文的 序列號, 括弧內的 數字 是 報文的 數據量, 不包括 atp 報頭. 報文 7 的 `*' 表明 設置了 EOM 位.
然后 Jssmag.209 請求 重傳 第 3 & 5 報文. Helios 做了 重傳后 jssmag.209 結束 這次 交易. 最后, jssmag.209 發起 下一次 交易請求. 請求中的 `*' 表明 沒有 設置 XO (只有一次) 位.
IP 分片
分片的 Internet 數據報 顯示為
(frag id:size@offset+)(frag id:size@offset)
Id 是 分片 標識號. Size 是 分片 大小 (字節), 不包括 IP 報頭. Offset 是 該分片 在 原數據報 中 的 偏移 (單位是字節).
每一個 分片 的 信息 都可以 打印出來. 第一個 分片 包含了 高層 協議 報頭, 顯示 協議信息 后 顯示 分片 的 信息. 第一個 分片 以后的 分片 不再 含有高層協議 報頭, 所以 在 源目地址 后面 只顯示 分片 信息. 例如, 下面是 從 arizona.edu 到 lbl-rtsg.arpa 的 一部分 ftp 傳輸, 途經的 CSNET 看上去 處理不了 576 字節的 數據報:
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
如果 報文的 IP 標有 不要分片 標志, 顯示時 在尾部 加上 (DF).
時戳
缺省情況下, 所有 輸出行 的 前面 都有 時戳. 時戳 就是 當前時間, 顯示格式為
hh:mm:ss.frac