tcpdump采用命令行方式對接口的數據包進行篩選抓取,其豐富特性表現在靈活的表達式上
1、格式
# tcpdump --help
tcpdump version 4.1-PRE-CVS_2012_03_26
libpcap version 1.4.0
Usage: tcpdump [-aAdDefIKlLnNOpqRStuUvxX] [ -B size ] [ -c count ]
[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]
[ -i interface ] [ -M secret ] [ -r file ]
[ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ]
[ -y datalinktype ] [ -z command ] [ -Z user ]
[ expression ]
2、選項說明
標注 的為常用選項
-c:指定要抓取的包數量。注意,是最終要獲取這么多個包。例如,指定"-c 10"將獲取10個包,但可能已經處理了100個包,只不過只有10個包是滿足條件的包。
-i interface:指定tcpdump需要監聽的接口。若未指定該選項,將從系統接口列表中搜尋編號最小的已配置好的接口(不包括loopback接口,要抓取loopback接口使用tcpdump -i lo),一旦找到第一個符合條件的接口,搜尋馬上結束。可以使用'any'關鍵字表示所有網絡接口。
-n:對地址以數字方式顯式,否則顯式為主機名,也就是說-n選項不做主機名解析。
-nn:除了-n的作用外,還把端口顯示為數值,否則顯示端口服務名。
-N:不打印出host的域名部分。例如tcpdump將會打印'nic'而不是'nic.ddn.mil'。
-s snaplen:設置tcpdump的數據包抓取長度
如果不設置默認將會是65535字節。對於要抓取的數據包較大時,長度設置不夠可能會產生包截斷,若出現包截斷,輸出行中會出現"[|proto]"的標志(proto實際會顯示為協議名)。但是抓取len越長,包的處理時間越長,並且會減少tcpdump可緩存的數據包的數量,從而會導致數據包的丟失,所以在能抓取我們想要的包的前提下,抓取長度越小越好。
輸出選項:
-e:輸出的每行中都將包括數據鏈路層頭部信息,例如源MAC和目標MAC。
-q:快速打印輸出。即打印很少的協議相關信息,從而輸出行都比較簡短。
-X:輸出包的頭部數據,會以16進制和ASCII兩種方式同時輸出。
-XX:輸出包的頭部數據,會以16進制和ASCII兩種方式同時輸出,更詳細。
-v:當分析和打印的時候,產生詳細的輸出。
-vv:產生比-v更詳細的輸出。
-vvv:產生比-vv更詳細的輸出。
其他功能性選項:
-D:列出可用於抓包的接口。將會列出接口的數值編號和接口名,它們都可以用於"-i"后。
-F:從文件中讀取抓包的表達式。若使用該選項,則命令行中給定的其他表達式都將失效。
-w:將抓包數據輸出到文件中而不是標准輸出。可以同時配合"-G time"選項使得輸出文件每time秒就自動切換到另一個文件。可通過"-r"選項載入這些文件以進行分析和打印。
-r:從給定的數據包文件中讀取數據。使用"-"表示從標准輸入中讀取。
3、tcpdump表達式
表達式用於篩選輸出哪些類型的數據包,如果沒有給定表達式,所有的數據包都將輸出,否則只輸出表達式指定的包。在表達式中出現的shell元字符建議使用單引號包圍。
有時候,我們想讓 通配符,或者元字符 變成普通字符,不需要使用它。那么這里我們就需要用到轉義符了。 shell提供轉義符有三種。
shell常見通配符,轉義字符,元字符。
字符 | 含義 | 實例 |
* | 匹配 0 或多個字符 | a*b a與b之間可以有任意長度的任意字符, 也可以一個也沒有, 如aabcb, axyzb, a012b, ab。 |
? | 匹配任意一個字符 | a?b a與b之間必須也只能有一個字符, 可以是任意字符, 如aab, abb, acb, a0b。 |
[list] | 匹配 list 中的任意單一字符 | a[xyz]b a與b之間必須也只能有一個字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。 |
[!list] | 匹配 除list 中的任意單一字符 | a[!0-9]b a與b之間必須也只能有一個字符, 但不能是阿拉伯數字, 如axb, aab, a-b。 |
[c1-c2] | 匹配 c1-c2 中的任意單一字符 如:[0-9] [a-z] | a[0-9]b 0與9之間必須也只能有一個字符 如a0b, a1b... a9b。 |
{string1,string2,...} | 匹配 sring1 或 string2 (或更多)其一字符串 | a{abc,xyz,123}b a與b之間只能是abc或xyz或123這三個字符串之一。 |
字符 | 說明 |
‘’(單引號) | 又叫硬轉義,其內部所有的shell 元字符、通配符都會被關掉。注意,硬轉義中不允許出現’(單引號)。 |
“”(雙引號) | 又叫軟轉義,其內部只允許出現特定的shell 元字符:$用於參數代換 `用於命令代替 |
\(反斜杠) | 又叫轉義,去除其后緊跟的元字符或通配符的特殊意義。 |
字符 | 說明 |
IFS | 由 <space> 或 <tab> 或 <enter> 三者之一組成(我們常用 space )。 |
CR | 由 <enter> 產生。 |
= | 設定變量。 |
$ | 作變量或運算替換(請不要與 shell prompt 搞混了)。 |
> | 重導向 stdout。 * |
< | 重導向 stdin。 * |
| | 命令管線。 * |
& | 重導向 file descriptor ,或將命令置於背境執行。 * |
( ) | 將其內的命令置於 nested subshell 執行,或用於運算或命令替換。 * |
{ } | 將其內的命令置於 non-named function 中執行,或用在變量替換的界定范圍。 |
; | 在前一個命令結束時,而忽略其返回值,繼續執行下一個命令。 * |
&& | 在前一個命令結束時,若返回值為 true,繼續執行下一個命令。 * |
|| | 在前一個命令結束時,若返回值為 false,繼續執行下一個命令。 * |
! | 執行 history 列表中的命令。* |
tcpdump的表達式由一個或多個"單元"組成,每個單元一般包含ID的修飾符和一個ID(數字或名稱)。
格式:proto dir type ID
三種修飾符:
(1).type:指定ID的類型,默認的type為host。
host | 主機名稱或ip地址。如:host JN-LX-Centos6-lvs |
net | 網段。抓取192.168.0.0網段的:net 192.168 |
port | 端口。如:port 53 |
portrange | 端口范圍。如:portrange 3-10 |
(2).dir:指定ID的方向。
src | 源主機名或地址 |
dst | 目標主機名或地址 |
src or dst(默認) | 源或目標,如:src or dst port 22 |
src and dst | 源和目標 |
(3).proto:通過給定協議限定匹配的數據包類型。
常用的協議有tcp,udp,arp,ip,icmp等,若未給定協議類型,則匹配所有可能的類型。例如"tcp port 21","udp portrange 3-10"。
(4)其他表達式單元
除了使用修飾符和ID組成的表達式單元,還有關鍵字表達式單元:gateway,broadcast,less,greater以及算術表達式。
表達式單元之間可以使用操作符" and / && / or / || / not / ! "進行連接,從而組成復雜的條件表達式。如"host rsyslog and port ftp and not port 514",這表示篩選的數據包要滿足"主機為rsyslog且端口是ftp(端口21)和端口不是514)的包",常用端口和名字的對應關系可在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"意義相同,都表示包的協議為tcp且目的端口為ftp或ftp-data或domain(端口53)。
使用括號"()"可以改變表達式的優先級,但需要注意的是括號會被shell解釋,所以應該使用反斜線"\"轉義為"\(\)",在需要的時候,還需要包圍在引號中。
4、示例
(1)抓取本機eth0中tcp和udp端口號為514的數據,抓取數量為10個,詳細顯示數據包頭和分析。
# tcpdump -i eth0 -c 10 udp or tcp port 514 -XX -vvv
(2)抓取源地址為192.168.1.100,端口號不為8080的數據
# tcpdump src 192.168.1.100 and tcp port not 8080
(3)打印helios<-->192.168.1.2或192.168.1.3之間通信的數據包
#tcpdump host helios and \( 192.168.1.2 or 192.168.1.3 \)