用法

tcpdump采用命令行方式对接口的数据包进行筛选抓取,其丰富特性表现在灵活的表达式上。
tcpdump [ -DenNqvX ] [ -c count ] [ -F ``file`` ] [ -i interface ] [ -r ``file`` ] [ -s snaplen ] [ -``w`` ``file`` ] [ expression ]

不带任何选项的tcpdump,默认会抓取第一个网络接口,且只有将tcpdump进程终止才会停止抓包。

默认情况下,tcpdump不会抓取本机内部通讯的报文。根据网络协议栈的规定,对于报文,即使是目的地是本机,也需要经过本机的网络协议层,所以本机通讯肯定是通过API进入了内核,并且完成了路由选择。【比如本机的TCP通信,也必须要socket通信的基本要素:src ip port dst ip port】

Linux抓包是通过注册一种虚拟的底层网络协议来完成对网络报文(准确的说是网络设备)消息的处理权。当网卡接收到一个网络报文之后,它会遍历系统中所有已经注册的网络协议,例如以太网协议、x25协议处理模块来尝试进行报文的解析处理,这一点和一些文件系统的挂载相似,就是让系统中所有的已经注册的文件系统来进行尝试挂载,如果哪一个认为自己可以处理,那么就完成挂载。

当抓包模块把自己伪装成一个网络协议的时候,系统在收到报文的时候就会给这个伪协议一次机会,让它来对网卡收到的报文进行一次处理,此时该模块就会趁机对报文进行窥探,也就是把这个报文完完整整的复制一份,假装是自己接收到的报文,汇报给抓包模块。

选项

抓包选项

-c 指定要抓取的包数量。注意,是最终要获取这么多个包。例如,指定”-c 10”将获取10个包,但可能已经处理了100个包,只不过只有10个包是满足条件的包。
-i 指定tcpdump需要监听的接口。若未指定该选项,将从系统接口列表中搜寻编号最小的已配置好的接口(不包括loopback接口,要抓取loopback接口使用tcpdump -i lo),一旦找到第一个符合条件的接口,搜寻马上结束。
可以使用’any’关键字表示所有网络接口
-n 对IP地址以数字方式显式,否则显式为主机名,也就是说-n选项不做主机名解析
-nn 除了-n的作用外,还把端口显示为数值,否则显示端口服务名
-N 不打印出host的域名部分。例如tcpdump将会打印’nic’而不是’nic.ddn.mil’

输出选项

-e 输出的每行中都将包括数据链路层头部信息,例如源MAC和目标MAC
-X 输出包的头部数据,会以16进制和ASCII两种方式同时输出。
-XX 输出包的头部数据,会以16进制和ASCII两种方式同时输出,更详细
-v 当分析和打印的时候,产生详细的输出
-vv 产生比-v更详细的输出
-vvv 产生比-vv更详细的输出

功能性选项

-D 列出可用于抓包的接口。将会列出接口的数值编号和接口名,它们都可以用于”-i”后,一般还是用接口名就行了
[root@localhost ~]# tcpdump -D
1.eth0 [Up, Running]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]
-w 将抓包数据输出到文件中而不是标准输出。
可以同时配合”-G time”选项使得输出文件每time秒就自动切换到另一个文件。
可通过”-r”选项载入这些文件以进行分析和打印。
-r 从给定的数据包文件中读取数据。使用”-“表示从标准输入中读取。

表达式

表达式用于筛选输出哪些类型的数据包,如果没有给定表达式,所有的数据包都将输出,否则只输出表达式为true的包。在表达式中出现的shell元字符建议使用单引号包围。

tcpdump的表达式由一个或多个”单元”组成,每个单元一般包含 ID的修饰符 一个ID(数字或名称),有三种修饰符:

  1. proto
    1. 通过给定协议限定匹配的数据包类型。
    2. 常用的协议有tcp、udp、arp、ip、ether、icmp等,若未给定协议类型,则匹配所有可能的类型。例如”tcp port 21”,”udp portrange 7000-7009”。
  2. dir
    1. 指定ID的方向。
    2. 可以给定的值包括src、dst、src or dst、src and dst,默认为src or dst。例如,”src foo”表示源主机为foo的数据包,”dst net 128.3”表示目标网络为128.3的数据包,”src or dst port 22”表示源或目的端口为22的数据包。
      1. src:src 210.27.48.2, IP包源地址是210.27.48.2
      2. dst:dst net 202.0.0.0, 目标网络地址是202.0.0.0
      3. dst or src(缺省值)
      4. dst and src
  3. type
    1. 指定ID的类型。
    2. 可以给定的值有host、net、port、portrange。例如”host foo”,”net 128.3”,”port 20”,”portrange 6000-6008”。默认的type为host。
      1. host(缺省类型):指明一台主机,如:host 210.27.48.2
      2. net:指明一个网络地址,网段,如:net 202.0.0.0
      3. port:指明端口号,如:port 23
      4. portrange:指明端口范围,如:portrange 6000-6008

所以,一个基本的表达式单元格式为”proto dir type ID”
image.jpeg

除了使用修饰符和ID组成的表达式单元,还有关键字表达式单元:gateway、broadcast、less、greater以及算术表达式。

表达式单元之间可以使用操作符” and / && / or / || / not / ! “进行连接,从而组成复杂的条件表达式。如”host foo and not port ftp and not port ftp-data”,这表示筛选的数据包要满足”主机为foo且端口不是ftp(端口21)和ftp-data(端口20)的包”,常用端口和名字的对应关系可在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解释,所以应该使用反斜线”\”转义为”()“,在需要的时候,还需要包围在引号中,也即注意下shell的转义问题。**

示例

命令 含义
tcpdump -i eth1 指定网络接口的数据包。如果不指定网卡,默认tcpdump只会监视第一个网络接口,如eth0
tcpdump -i any 所有网络接口的数据包
tcpdump host longshuai
tcpdump host 192.168.1.1
指定主机名或IP地址的数据包,包含进出的
tcpdump host helios _and \( _hot _or _ace \) helios<—>hot 或 helios<—>ace 之间通信的数据包,限定了一个and,所以必须是源目的都符合
tcpdump src host hostname 主机hostname发送的所有数据
tcpdump dst host hostname 所有发送到主机hostname的数据包
tcpdump tcp port 22 _and host _hostname 指定主机和端口的数据包
tcpdump -c 10 _net _192.168 指定网络(也即网段)的数据包,如本机与192.168网段通信的数据包,”-c 10”表示只抓取10个包
tcpdump -i eth1 ‘((icmp) and ((ether dst host 00:01:02:03:04:05)))’ 所有经过 en0,目标 MAC 地址是 00:01:02:03:04:05 的 ICMP 数据
tcpdump -i eth1 ‘tcp[tcpflags] = tcp-syn’ 只抓 SYN 包
tcpdump -i eth1 udp dst port 53 抓 DNS 请求数据
time tcpdump -nn -i eth1 ‘tcp[tcpflags] = tcp-syn’ -c 10000 > /dev/null 上面的命令计算抓 10000 个 SYN 包花费多少时间,可以判断访问量大概是多少
tcpdump -i eth1 ‘((port 8000) and (tcp[(tcp[12]>>2):4]=0x47455420))’ -nnAl -w /tmp/GET.log 实时抓取端口号8000的GET包,然后写入GET.log