TCPDUMP(8) | System Manager's Manual | TCPDUMP(8) |
tcpdump - 轉儲網絡上的數據流
tcpdump [ -adeflnNOpqStvx ] [ -c count
] [ -F file ]
[ -i interface ] [ -r file ] [ -s
snaplen ]
[ -T type ] [ -w file ] [ expression ]
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
ether host ehost and not host host
tcp src port port
len <= length.
len >= length.
ether proto p
ether proto p
ip proto p
proto [ expr : size ]
例如, `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 是 流序號 (或者 流序號 和 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
如果 用 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
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 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
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 服務 能夠 識別出來(從 源目端口號 上), 因而 顯示出 更高層的 協議信息. 特別是 域名服務請求(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 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 在 目錄文件 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 選項 (-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 地址 按 這個格式 顯示
net.host.port 144.1.209.2 > icsd-net.112.220 office.2 > icsd-net.112.220 jssmag.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@*" 250 techpit.2 > icsd-net.112.220: nbp-reply 190: "techpit:LaserWriter@*" 186
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
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
如果 報文的 IP 標有 不要分片 標誌, 那麼 在尾部 顯示 (DF).
時戳
缺省情況下, 所有 輸出行 的 前面 都有 時戳. 時戳 就是 當前時間, 顯示格式爲
hh:mm:ss.frac
Van Jacobson, Craig Leres and Steven McCanne, all of the Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
當前 版本 可以 從 匿名ftp 獲得:
請把 臭蟲 報告 傳往 tcpdump@ee.lbl.gov.
NIT 不允許 監視 你自己的 傳出數據, BPF 可以. 我們 建議 你 使用 後者.
應該 試着 重組 IP 分片, 至少可以 爲 更高層的 協議 計算出 正確的 長度.
名字服務逆向詢問 轉儲的 不正確: 打印出 (空的)問題部分, 而實際上 詢問 放在了 回答部分. 有人 認爲 這種 逆向詢問 本身就是 bug, 應該 修改 產生問題 的 程序, 而非 tcpdump.
蘋果 Ethertalk DDP 的 報文 應該 象 KIP DDP 的 報文 一樣 容易 轉儲, 事實 卻 不是 這樣. 即使 我們 有意 作點什麼 來 促銷 Ethertalk (我們沒有), LBL 也不允許 Ethertalk 出現在 它的 任何網絡上, 所以 我們 沒辦法 測試 這些代碼.
如果 報文的 路徑上 出現 夏時制時間 變化, 可能 導致 時戳 混亂. (這個時間變化將忽略)
操作 FDDI 報頭的 過濾器表達式 假設 所有的 FDDI 報文 被封裝在 以太報文 中. 這對 IP, ARP 和 DECNET Phase IV 無疑是 正確的, 但對 某些 協議 如 ISO CLNS 不正確. 因此, 過濾器 有可能會 糊里糊塗的 的 接收 一些 並不真正 匹配 過濾器表達式 的 報文.
徐明 <xuming@users.sourceforge.net>
2003/05/13
http://cmpp.linuxforum.net
本頁面中文版由中文
man 手冊頁計劃提供。
中文 man
手冊頁計劃:https://github.com/man-pages-zh/manpages-zh
30 June 1997 |