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 是 流序號 (或者 流序號 和 ack) 的 變化總量. 如果 不是 特殊情況, 就顯示出 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 rtsg
arp reply csam is-at CSAM
第一行 說明 rtsg 發出 一個 arp 報文 詢問 internet 主機 csam 的 乙太網地址. Csam 用 它的 以太地址 作應答 (這個例子中, 以太地址 是 大寫的, internet 地址 為 小寫). 如果 用 tcpdump -n 看 就 清楚一些:
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
這裡 第一個 報文 指出 乙太網源地址是 RTSG, 目的地址 是 乙太網廣播地址, 型別域 為 16進位制數 0806 (型別 ETHER_ARP), 報文全長 64 位元組. TCP 報文
(注意: 以下的描述中 假設 你 熟悉 RFC-793 中 說明的 TCP 協議, 如果 你 不瞭解 這個 協議, 無論是 本文 還是 tcpdump 都對你 用處 不大)
一般說來 tcp 協議的 輸出格式是:
src > dst: flags data-seqno ack window urgent options
Src 和 dst 是 源目IP地址和埠. Flags 是 S (SYN), F (FIN), P (PUSH) 或 R (RST) 或 單獨的 `.'(無標誌), 或者是 它們的 組合. Data-seqno 說明了 本報文中的資料 在 流序號 中的 位置 (見下例). Ack 是 在這條連線上 信源機 希望 下一個 接收的 位元組的 流序號 (sequence number). Window 是 在這條連線上 信源機 接收緩衝區 的 位元組大小. Urg 表明 報文內 是 `緊急(urgent)' 資料. Options 是 tcp 選項, 用 尖括號 括起 (例如, <mss 1024>). 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 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 的 login 埠 傳送 報文. S 標誌 表明 設定了 SYN 標誌. 報文 的 流序號 是 768512, 沒有 資料. (這個寫成 `first:last(nbytes)', 意思是 `從 流序號 first 到 last, 不包括 last, 有 nbytes 位元組的 使用者資料'.) 此時 沒有 捎帶確認(piggy-backed ack), 有效的 接收視窗 是 4096 位元組, 有一個 最大分段長度(max-segment-size) 的 選項, 請求 設定 mss 為 1024 位元組. Csam 用類似的 形式 應答, 只是 增加了 一個 對 rtsg SYN 的 捎帶確認. 然後 Rtsg 確認 csam 的 SYN. `.' 意味著 沒有 設定 標誌. 這個 報文 不包含 資料, 因此 也就 沒有 資料的流序號. 注意這個 確認流序號 是一個 小整數(1). 當 tcpdump 第一次 發現 一個 tcp 會話時, 它 顯示 報文 攜帶的 流序號. 在 隨後收到的 報文裡, 它 顯示 當前 報文 和 最初那個 報文 的 流序號 之 差. 這 意味著 從第一個報文 開始, 以後的 流序號 可以 理解成 資料流 中的 相對位移 (每個報文 的 第一個 資料位元組 從 '1' 計數). `-S' 選項 能夠 改變 這個 特性, 直接 顯示 原始的 流序號.
在 第六行, rtsg 傳給 csam 19 個位元組 的 資料 (位元組 2 到 20). 報文中 設定了 PUSH 標誌. 第七行 csam 表明 它 收到了 rtsg 的 資料, 位元組序號 是 21, 但不包括 第21個 位元組. 顯然 大多數 資料 在 socket 的 緩衝區內, 因為 csam 的 接收視窗 收到的 資料 小於 19 個 位元組. 同時 csam 向 rtsg 傳送了 一個位元組 的 資料. 第八和第九行 顯示 csam 傳送了 兩個位元組 的 緊急資料 到 rtsg.
如果 捕捉區 設定的 過小, 以至於 tcpdump 不能 捕捉到 完整的 TCP 報頭, tcpdump 會 儘可能的 翻譯 已捕獲的 部分, 然後 顯示 ``[|tcp]'', 表明 無法 翻譯 其餘 部分. 如果 報頭 包含 有問題的 選項 (選項表 長度 太小 或者 超出 報頭範圍), tcpdump 顯示 ``[bad opt]'' 並且 不再 翻譯 其他 選項部分 (因為 它 不可能 判斷出 從哪兒 開始). 如果 報頭長度 表明 存在 選項, 但是 IP 資料報 長度 不夠, 不可能 真的 儲存 選項, tcpdump 就顯示 ``[bad hdr length]''.
UDP 報文
UDP 格式 就象 這個 rwho 報文 顯示的:
actinide.who > broadcast.who: udp 84
就是說 把一個 udp 資料報 從 主機 actinide 的 who 埠 傳送到 broadcast, Internet 廣播地址 的 who 埠. 報文 包含 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)
主機 h2opolo 訪問 helios 上的 域名服務, 詢問 和 ucbvax.berkeley.edu. 關聯的 地址記錄(qtype=A). 查詢號是 `3'. `+' 表明 設定了 遞迴請求 標誌. 查詢長度是 37 位元組, 不包括 UDP 和 IP 頭. 查詢操作 是 普通的 Query 操作, 因此 op 域 可以 忽略. 如果 op 設定成 其他什麼東西, 它應該 顯示在 `3' 和 `+' 之間. 類似的, qclass 是 普通的 C_IN 型別, 也被 忽略了. 其他型別的 qclass 應該 在 `A' 後面 顯示. 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 回答了 h2opolo 發出的 標識為3 的 詢問, 一共是 3 個 回答記錄, 3 個 名字服務記錄 和 7 個管理結構記錄. 第一個 回答紀錄 的 型別是 A (地址), 資料是 internet 地址 128.32.137.3. 回答的 全長 為 273 位元組, 不包括 UDP 和 IP 報頭. 作為 A 記錄的 class(C_IN) 可以 忽略 op (詢問) 和 rcode (NoError). 在第二個例子裡, 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 args
src.nfs > dst.xid: reply stat len op results
sushi.6709 > wrl.nfs: 112 readlink fh 21,24/10.73165
wrl.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 傳送 號碼為 6709 的 互動會話 (注意 源主機 後面的 數字 是 互動號, 不是 埠). 這項請求 長 112 位元組, 不包括 UDP 和 IP 報頭. 在 檔案控制代碼 (fh) 21,24/10.731657119 上執行 readlink (讀取 符號連線) 操作. (如果 運氣 不錯, 就象 這種情況, 檔案控制代碼 可以 依次翻譯成 主次裝置號, i 節點號, 和 事件號(generation number). ) Wrl 回答 `ok' 和 連線的 內容. 在第三行, sushi 請求 wrl 在 目錄檔案 9,74/4096.6878 中 查詢 `xcolors'. 注意 資料的 列印格式 取決於 操作型別. 格式 應該 可以 自我說明.
給出 -v (verbose) 選項 可以 顯示 附加資訊. 例如:
sushi.1372a > wrl.nfs:
148 read fh 21,11/12.195 8192 bytes @ 24576
wrl.nfs > sushi.1372a:
reply ok 1472 read REG 100664 ids 417/0 sz 29388
(-v 同時 使它 顯示 IP 報頭的 TTL, ID, 和 分片域, 在 這個例子裡 把它們 省略了.) 在第一行, sushi 請求 wrl 從 檔案 21,11/12.195 的 偏移位置 24576 開始, 讀取 8192 位元組. Wrl 回答 `ok'; 第二行 顯示的 報文 是 應答的 第一個 分片, 因此 只有 1472 位元組 (其餘資料 在 後續的 分片中 傳過來, 但由於 這些分片裡 沒有 NFS 甚至 UDP 報頭, 因此 根據 所使用的 過濾器表示式, 有可能 不再顯示). -v 選項 還會 顯示 一些 檔案屬性 (它們 作為 檔案資料 的 附帶部分 傳回來): 檔案型別 (普通檔案 ``REG''), 存取模式 (八進位制數), uid 和 gid, 以及 檔案大小. 如果再給一個 -v 選項 (-vv), 還能 顯示 更多的細節.
注意 NFS 請求 的 資料量 非常大, 除非 增加 snaplen, 否則 很多細節 無法顯示. 試一試 `-s 192' 選項.
NFS 應答報文 沒有明確 標明 RPC 操作. 因此 tcpdump 保留有 ``近來的'' 請求 記錄, 根據 互動號 匹配 應答報文. 如果 應答報文 沒有 相應的 請求報文, 它 就 無法分析.
KIP Appletalk (UDP 上的 DDP)
Appletalk DDP 報文 封裝在 UDP 資料報 中, 解包後 按 DDP 報文 轉儲 (也就是說, 忽略 所有的 UDP 報頭 資訊). 檔案 /etc/atalk.names 用來 把 appletalk 網路和節點號 翻譯成 名字. 這個檔案 的 行格式 是
number name
1.254 ether
16.1 icsd-net
1.254.110 ace
前兩行 給出了 appletalk 的 網路名稱. 第三行 給出 某個主機 的 名字 (主機和網路 依據 第三組 數字 區分 - 網路號 一定 是 兩組數字, 主機號 一定 是 三組 數字.) 號碼 和 名字 用 空白符(空格或tab) 隔開. /etc/atalk.names 檔案 可以 包含 空行 或 註釋行(以`#'開始的行). Appletalk 地址 按 這個格式 顯示
net.host.port
144.1.209.2 > icsd-net.112.220
office.2 > icsd-net.112.220
jssmag.149.235 > icsd-net.2
(如果 不存在 /etc/atalk.names , 或者 裡面 缺少 有效專案, 就以 數字形式 顯示 地址.) 第一個例子裡, 網路 144.1 的 209 節點的 NBP (DDP 埠 2) 向 網路 icsd 的 112 節點 的 220 埠 傳送資料. 第二行 和 上面 一樣, 只是 知道了 源節點 的 全稱 (`office'). 第三行 是從 網路 jssmag 的 149 節點 的 235 埠 向 icsd-net 的 NBP 埠 廣播 (注意 廣播地址 (255) 隱含在 無主機號的 網路名字 中 - 所以 在 /etc/atalk.names 中 區分 節點名 和 網路名 是個 好主意). 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@*" 250
techpit.2 > icsd-net.112.220: nbp-reply 190: "techpit:LaserWriter@*" 186
第一行 是 網路 icsd 的 112 主機 在 網路 jssmag 上的 廣播, 對 名字 laserwriter 做 名字查詢請求. 名字查詢請求 的 nbp 標識號 是 190. 第二行 顯示的是 對 這個請求 的 回答 (注意 它們 有 同樣的 標識號), 主機 jssmag.209 表示 在它的 250 埠 註冊了 一個 laserwriter 的 資源, 名字是 "RM1140". 第三行 是 這個請求 的 其他回答, 主機 techpit 的 186 埠 有 laserwriter 註冊的 "techpit". ATP 報文 格式 如 下例 所示:
jssmag.209.165 > helios.132: atp-req 12266<0-7> 0xae030001
helios.132 > jssmag.209.165: atp-resp 12266:0 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:1 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:2 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:4 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:6 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp*12266:7 (512) 0xae040000
jssmag.209.165 > helios.132: atp-req 12266<3,5> 0xae030001
helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000
jssmag.209.165 > helios.132: atp-rel 12266<0-7> 0xae030001
jssmag.209.133 > helios.132: atp-req* 12267<0-7> 0xae030002
Jssmag.209 向 主機 helios 發起 12266 號 互動操作, 請求 8 個 報文(`<0-7>'). 行尾的 十六進位制數 是 請求中 `userdata' 域 的 值. Helios 用 8 個 512位元組 的 報文 應答. 跟在 互動號 後面的 `:digit' 給出了 互動過程中 報文的 序列號, 括弧內的 數字 是 報文的 資料量, 不包括 atp 報頭. 報文 7 的 `*' 表明 設定了 EOM 位.
然後 Jssmag.209 請求 重傳 第 3 & 5 報文. Helios 做了 重傳後 jssmag.209 結束 這次 互動操作. 最後, jssmag.209 發起 下一次 互動請求. 請求中的 `*' 表明 沒有 設定 XO (exactly once) 位.
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
這裡 有幾點 需要注意: 首先, 第二行的 地址 不包括 埠號. 這是因為 TCP 協議 資訊 全部 裝到了 第一個 分片內, 所以 顯示 後續分片的 時候 不可能 知道 埠 或 流序號. 其次, 第一行的 tcp 流序號部分 看上去有 308 位元組的 使用者資料, 實際上 是 512 位元組 (第一個 分片的 308 和 第二個 分片的 204 位元組). 如果 你 正在 尋找 流序號中 的 空洞, 或者 試圖 匹配 報文 的 確認(ack), 那你上當了. 如果 報文的 IP 標有 不要分片 標誌, 那麼 在尾部 顯示 (DF).
時戳
預設情況下, 所有 輸出行 的 前面 都有 時戳. 時戳 就是 當前時間, 顯示格式為
精度 和 核心時鐘 一樣. 時戳 反映了 核心 收到 報文 的 時間. 從 以太介面 收到 報文 到 核心 響應 '報文就緒' 中斷 有一個 滯後, 該 滯後 不被考慮.