TCPDUMP(8)

NAME
tcpdump - 轉儲網路上的數據流

總覽 (SYNOPSIS)
tcpdump [ -adeflnNOpqStvx ] [ -c count ] [ -F file ]
[ -i interface ] [ -r file ] [ -s snaplen ]
[ -T type ] [ -w file ] [ expression ]

描述 (DESCRIPTION)

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* 的 讀訪問 權限.

選項 (OPTIONS)

-a  試著 把 網路和廣播地址 轉換成 名稱.

-c  當 收到 count 報文 後 退出.

-d  把 編譯好的 報文匹配代碼 (packet-matching code) 翻譯成 可讀形式, 傳往 標準輸出, 然後退出.

-dd 把 報文匹配代碼 (packet-matching code) 以 C 程式片斷 的 形式 輸出.

-ddd
    把 報文匹配代碼 (packet-matching code) 以 十進制數 形式 輸出 (前面 加上 總數).

-e  顯示 鏈路層報頭.

-f  以 數字形式 顯示 '外部的' 網際網路地址, 而不是 字符形式 (這個 選項 用來 繞開 腦殼壞光的 SUN 黃頁伺服器 的 問題 — 一般說來 當它 翻譯 外部網路 的 數字地址 時 會長期掛起).

-F  把 file 的內容 用作 過濾表達式. 忽略 命令行 上 的 表達式.

-i  監聽 interface. 如果 不指定 接口, tcpdump 在 系統 的 接口 清單 中, 尋找 號碼最小, 已經 配置好的 接口 (loopback 除外). 選中的時候 會 中斷 連接.

-l  行緩沖 標準輸出. 可用於 捕捉 數據 的 同時 查看 數據. 例如,
    ``tcpdump -l | tee dat'' or ``tcpdump -l > dat & tail -f dat''.

-n  不要把 地址 轉換成 名字 (指的是 主機地址, 端口號等)

-N  不顯示 主機名字 中的 域名 部分. 例如, 如果 使用 這個 選項, tcpdump 只顯示 ``nic'', 而不是 ``nic.ddn.mil''.

-O  禁止運行 報文匹配代碼 的 優化器. 這個選項 只有 當你 懷疑 優化器 有 bug 時 才有用.

-p  禁止 把 接口 置成 promiscuous(雜湊) 模式. 注意, 接口 有可能 因 其他原因 而 處於 promiscuous 模式; 因此, '-p' 不能 作為 `ether host {local-hw-addr} 或 ether broadcast' 的 簡寫.

-q  快速輸出. 顯示 較少的 協議信息, 輸出行 會 短一點點.

-r  從 file 中 讀入 數據報 (檔案 是用 -w 選項 創建的). 如果 file 是 ``-'', 就從 標準輸入 讀入.

-s  從每個 報文 中 截取 snaplen 字節的數據, 而不是 預設的 68 (如果是 SunOS 的 NIT, 最小值是 96). 68 個字節 適用於 IP, ICMP, TCP 和 UDP, 但是 有可能 截掉 名字伺服器 和 NFS 報文 的 協議 信息 (見下文). 輸出時 如果指定 ``[|proto]'', tcpdump 可以 指出 那些 捕捉量過小 的 數據報, 這裏的 proto 是 截斷發生處 的 協議層 名稱. 注意, 採用 更大的 捕捉范圍 不但 增加了 處理 報文 的 時間, 而且 減少了 報文的 緩沖 數量, 可能 導致 報文的丟失. 你 應該 把 snaplen 設的 盡量小, 只要 能夠 容納 你 需要 的 協議信息 就可以了.

-T  把 通過 "expression" 挑選出來的 報文 解釋成 指定的 type. 目前 已知 的 類型 有: rpc (遠程過程調用 Remote Procedure Call), rtp (實時應用協議 Real-Time Applications protocol), rtcp (實時應用控制協議 Real-Time Applications control protocol), vat (可視音頻工具 Visual Audio Tool), 和 wb (分布式白板 distributed White Board).

-S  顯示 絕對的, 而不是 相對的 TCP 流序號.

-t  禁止 顯示 時戳標誌.

-tt 顯示 未格式化的 時戳標誌.

-v  (稍微多一點) 繁瑣的輸出. 例如, 顯示 IP 數據報 中的 生存周期 和 服務類型.

-vv 更繁瑣的輸出. 例如, 顯示 NFS 應答報文 的 附加域.

-w  把 原始報文 存進 file, 不做 分析 和 顯示. 它們 可以 以後 用 -r 選項 顯示. 如果 file 是 ``-'', 就 寫往 標準輸出.

-x  以 16 進制數 形式 顯示 每一個 報文 (去掉鏈路層報頭後) . 可以 顯示 較小的 完整 報文, 否則 只 顯示 snaplen 個 字節 .

expression
    用來 選擇 要 轉儲 的 數據報. 如果 沒有 指定 expression , 就 轉儲 網路的 全部 報文. 否則, 只轉儲 相對 expression 為 `true' 的 數據報.

    expression 由 一個或多個 原語 (primitive) 組成. 原語 通常 由 一個 標識 (id, 名稱或數字), 和 標識 前面的 一個或多個 修飾子(qualifier) 組成. 修飾子 有 三種 不同的類型:

    type
        類型修飾子 指出 標識名稱 或 標識數字 代表 什麼 類型的東西. 可以使用的 類型 有 host, net 和 port. 例如, `host foo', `net 128.3', `port 20'. 如果 不指定 類型修飾子, 就使用 預設的 host .

    dir 方向修飾子 指出 相對於 標識 的 傳輸方向 (數據是 傳入還是傳出 標識). 可以使用的 方向 有 src, dst, src or dst 和 src and dst. 例如, `src foo', `dst net 128.3', `src or dst port ftp-data'. 如果 不指定 方向修飾子, 就使用 預設的 src or dst . 對於 `null' 鏈路層 (就是說 像 slip 之類的 點到點 協議), 用 inbound 和 outbound 修飾子 指定 所需的 傳輸方向.

    proto
        協議修飾子 要求 匹配 指定的協議. 可以使用的 協議 有: ether, fddi, ip, arp, rarp, decnet, lat, sca, moprc, mopdl, tcp 和 udp. 例如, `ether src foo', `arp net 128.3', `tcp port 21'. 如果 不指定 協議修飾子, 就使用 所有 符合 類型 的 協議. 例如, `src foo' 指 `(ip 或 arp 或 rarp) src foo' (注意後者不符合語法), `net bar' 指 `(ip 或 arp 或 rarp) net bar', `port 53' 指 `(tcp 或 udp) port 53'.

    [`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'.

    允許的 原語 有:

    dst host host
        如果 報文中 IP 的 目的地址域 是 host, 則 邏輯 為 真. host 既可以 是 地址, 也可以 是 主機名.

    src host host
        如果 報文中 IP 的 源地址域 是 host, 則 邏輯 為 真.

    host host
        如果 報文中 IP 的 源地址域 或者 目的地址域 是 host, 則 邏輯 為 真. 上面 所有的 host 表達式 都可以 加上 ip, arp, 或 rarp 關鍵字 做 前綴, 就像:
        ip host host
        它等價於:
        ether proto \ip and host host
        如果 host 是 擁有 多個 IP 地址 的 主機名, 它的 每個地址 都會 被查驗.

    ether dst ehost
        如果 報文的 以太目的地址 是 ehost, 則 邏輯 為 真. Ehost 既可以是 名字 (/etc/ethers 裏有), 也可以是 數字 (有關 數字格式 另見 ethers(3N) ).

    ether src ehost
        如果 報文的 以太源地址 是 ehost, 則 邏輯 為 真.

    ether host ehost
        如果 報文的 以太源地址 或 以太目的地址 是 ehost, 則 邏輯 為 真.

    gateway host
        如果 報文 把 host 當做 網關, 則 邏輯 為 真. 也就是說, 報文的 以太源或目的地址 是 host, 但是 IP 的 源目地址 都不是 host. host 必須 是個 主機名, 而且 必須 存在 /etc/hosts 和 /etc/ethers 中. (一個等價的表達式是
        ether host ehost and not host host
        對於 host / ehost, 它既可以是 名字, 也可以是 數字.)

    dst net net
        如果 報文的 IP 目的地址 屬於 網路號 net, 則 邏輯 為 真. net 既可以 是 名字 (存在 /etc/networks 中), 也可以是 網路號. (詳見 networks(4)).

    src net net
        如果 報文的 IP 源地址 屬於 網路號 net, 則 邏輯 為 真.

    net net
        如果 報文的 IP 源地址 或 目的地址 屬於 網路號 net, 則 邏輯 為 真.

    net net mask mask
        如果 IP 地址 匹配 指定 網路掩碼(netmask) 的 net, 則 邏輯 為 真. 本原語 可以用 src 或 dst 修飾.

    net net/len
        如果 IP 地址 匹配 指定 網路掩碼 的 net, 則 邏輯 為 真, 掩碼 的 有效位寬 為 len. 本原語 可以用 src 或 dst 修飾.

    dst port port
        如果 報文 是 ip/tcp 或 ip/udp, 並且 目的端口 是 port, 則 邏輯 為 真. port 是一個 數字, 也可以是 /etc/services 中 說明過的 名字 (參看 tcp(4P) 和 udp(4P)). 如果 使用 名字, 則 檢查 端口號 和 協議. 如果 使用 數字, 或者 有二義的名字, 則 只檢查 端口號 (例如, dst port 513 將顯示 tcp/login 的數據 和 udp/who 的數據, 而 port domain 將顯示 tcp/domain 和 udp/domain 的數據).

    src port port
        如果 報文 的 源端口號 是 port, 則 邏輯 為 真.

    port port
        如果 報文 的 源端口 或 目的端口 是 port, 則 邏輯 為 真. 上述的 任意一個 端口表達式 都可以 用 關鍵字 tcp 或 udp 做 前綴, 就像:
        tcp src port port
        它 只匹配 源端口 是 port 的 TCP 報文.

    less length
        如果 報文 的 長度 小於等於 length, 則 邏輯 為 真. 它等同於:
        len <= length.

    greater length
        如果 報文 的 長度 大於等於 length, 則 邏輯 為 真. 它等同於:
        len >= length.

    ip proto protocol
        如果 報文 是 IP 數據報(參見 ip(4P)), 其 內容 的 協議類型 是 protocol, 則 邏輯 為 真. Protocol 可以是 數字, 也可以是 下列 名稱 中的 一個: icmp, igrp, udp, nd, 或 tcp. 注意 這些 標識符 tcp, udp, 和 icmp 也是 關鍵字, 所以 必須 用 反斜槓(\) 轉義, 在 C-shell 中 應該是 \\ .

    ether broadcast
        如果 報文 是 以太廣播報文, 則 邏輯 為 真. 關鍵字 ether 是 可選的.

    ip broadcast
        如果 報文 是 IP廣播報文, 則 邏輯 為 真. Tcpdump 檢查 全0 和 全1 廣播約定, 並且 檢查 本地 的 子網掩碼.

    ether multicast
        如果 報文 是 以太多目傳送報文(multicast), 則 邏輯 為 真. 關鍵字 ether 是 可選的. 這實際上 是 `ether[0] & 1 != 0' 的簡寫.

    ip multicast
        如果 報文 是 IP多目傳送報文, 則 邏輯 為 真.

    ether proto protocol
        如果 報文協議 屬於 以太類型 的 protocol, 則 邏輯 為 真. Protocol 可以是 數字, 也可以是 名字, 如 ip, arp, 或 rarp. 注意 這些 標識符 也是 關鍵字, 所以 必須 用 反斜槓(\) 轉義. [如果是 FDDI (例如, `fddi protocol arp'), 協議 標識 來自 802.2 邏輯鏈路控制(LLC)報頭, 它 通常 位於 FDDI 報頭 的 頂層. 當 根據 協議標識 過濾 報文 時, Tcpdump 假設 所有的 FDDI 報文 含有 LLC 報頭, 而且 LLC 報頭 用的是 SNAP 格式.]

    decnet src host
        如果 DECNET 的 源地址 是 host, 則 邏輯 為 真, 該 主機地址 的 形式 可能 是 ``10.123'', 或者是 DECNET 主機名. [只有 配置成 運行 DECNET 的 Ultrix 系統 支持 DECNET 主機名.]

    decnet dst host
        如果 DECNET 的 目的地址 是 host, 則 邏輯 為 真.

    decnet host host
        如果 DECNET 的 源地址 或 目的地址 是 host, 則 邏輯 為 真.

    ip, arp, rarp, decnet
        是:
        ether proto p
        的 簡寫 形式, 其中 p 為 上述 協議 的 一種.

    lat, moprc, mopdl
        是:
        ether proto p
        的 簡寫 形式, 其中 p 為 上述 協議 的 一種. 注意 tcpdump 目前 不知道 如何 分析 這些 協議.

    tcp, udp, icmp
        是:
        ip proto p
        的 簡寫 形式, 其中 p 為 上述 協議 的 一種.

    expr relop expr
        如果 這個 關系式 成立, 則 邏輯 為 真, 其中 relop 是 >, <, >=, <=, =, != 之一, expr 是 數學表達式, 由 常整數(標準C語法形式), 普通的 二進制運算符 [+, -, *, /, &, |], 一個 長度運算符, 和 指定的 報文數據訪問算符 組成. 要 訪問 報文內 的 數據, 使用 下面的 語法:
        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片 的 第一個 字節.

    原語 可以 用 下述 方法 結合使用:

        園括弧 括起來的 原語 和 操作符 (園括弧 在 Shell 中 有專用, 所以必須轉義).

        取反操作 (`!' or `not').

        連結操作 (`&&' or `and').

        或操作 (`||' or `or').

    取反操作 有 最高優先級. 或操作 和 連結操作 有 相同的 優先級, 運算時 從左到右 結合. 注意 連結操作 需要 顯式的 and 算符, 而不是 並列放置.

    如果 給出 標識符, 但沒給 關鍵字, 那麼 暗指 最近使用 的 關鍵字. 例如,
    not host vs and ace
    作為
    not host vs and host ace
    的 簡寫形式, 不應該 和
    not ( host vs or ace )
    混淆.

    表達式參數 可以 作為 單個 參數, 也可以 作為 復合參數 傳給 tcpdump, 後者 更方便 一些. 一般說來, 如果 表達式 包含 Shell 元字符(metacharacter), 傳遞 單個 括起來 的 參數 要 容易 一些. 復合參數 在 被解析前 用 空格 聯接 一起.

示例 (EXAMPLES)

顯示 所有 進出 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"

輸出格式 (OUTPUT FORMAT)

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). 時戳

預設情況下, 所有 輸出行 的 前面 都有 時戳. 時戳 就是 當前時間, 顯示格式為
    hh:mm:ss.frac
精度 和 核心時鐘 一樣. 時戳 反映了 核心 收到 報文 的 時間. 從 以太接口 收到 報文 到 核心 響應 '報文就緒' 中斷 有一個 滯後, 該 滯後 不被考慮.

另見 (SEE ALSO)
traffic(1C), nit(4P), bpf(4), pcap(3)

作者 (AUTHORS)
Van Jacobson, Craig Leres and Steven McCanne, all of the Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.

當前 版本 可以 從 匿名ftp 獲得:

    ftp://ftp.ee.lbl.gov/tcpdump.tar.Z

BUGS
請把 臭蟲 報告 傳往 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

《中國Linux論壇man手冊頁翻譯計劃》
http://cmpp.linuxforum.net