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 )