tcpdump是Linux/Unix下提供的强大的抓包分析工具,命令语法如下:
tcpdump命令_端口号

tcpdump的参数由两部分组成:option和expression,option表示命令的参数,expression用于表示哪些报文被dump出来,没有提供expression表示dump所有的报文

tcpdump参数

常用的option:

  • -n :不解析地址,直接以 IP 及 port number 显示,而非主机名与服务名称
  • -i :后面接要『监听』的网络接口,例如 eth0, lo, ppp0 等等
  • -c :抓包数量,如果没有这个参数, tcpdump 会持续不断的监听,直到使用者输入 [ctrl]-c 为止
  • -e :输出dump的报文的链路层(OSI 第二层)信息(包括源目MAC和以太类型)
  • -q :quick mode,仅列出较为简短的封包信息,每一行的内容比较精简
  • -s :抓包的长度,默认是96字节。如果要把报文保存下来分析,需配置此参数
  • -A :抓包内容以 ASCII 显示,做WWW 的网页抓包分析很有用
  • -X :可以列出十六进制 (hex) 以及 ASCII 的抓包内容,对于观察内容很有用
  • -r :从后面接的文件中读取数据,这个『文件』是由 -w 所生成的
  • -w :把抓取数据保存到文件,后面接文件名
  • -v :verbose output,打印详细的输出
  • -vv :more verbose output,打印更加详细的输出

expression选择那些报文被dump出来,它可以由多个primitive(基元,可以理解成子表达式)组成,每个primitive都会输出一个结果:true或者false,primitive之间可以用逻辑符组合,最终expression的结果为true的报文会被dump出来。
常用的expression:

  • host :匹配v4/v6地址,可以匹配源和目的。
  • src host :匹配源v4/v6地址
  • dst host :匹配目的v4/v6地址
  • ether src :匹配源MAC
  • ether dst :匹配目的MAC
  • net :匹配网络地址范围
  • src net :匹配源网络地址范围
  • dst net :匹配目的网络地址范围
  • port :匹配端口号
  • src port :匹配源端口号
  • dst port :匹配目的端口号
  • ip proto :匹配IP协议号,可以跟数字或者知名的协议名
  • ether proto :匹配以太类型
  • vlan :匹配VLAN号
  • 缩写 :ip ip6 arp stp tcp udp icmp(ether proto和ip proto的缩写)
  • 逻辑符:not and or,not的优先级最高,and和or的优先级相同,从左往右依次生效

tcpdump常见用法
主要有两种用法:一是把抓取到的报文直接打印到stdout,二是把抓取到的内容保存到文件,借助其他工具(比如wireshark)分析抓取的报文,想要保存下来就带-w选项即可。常用示例如下:
(1) 想要截获1.1.1.1主机所有收到的和发出的的报文,并把信息打印到stdout:
tcpdump ‘host 1.1.1.1’
(2) 想要截获主机1.1.1.1 和主机1.1.1.2或192.168.111.3的通信,并且不做解析:
tcpdump ‘host 1.1.1.1 and 1.1.1.2 or 192.168.111.3’ -n
(3) 想要获取主机1.1.1.1除了和主机1.1.1.2之外所有主机通信的ip包:
tcpdump ‘host 1.1.1.1 and !1.1.1.2’ -n
(4) 截取源IP是210.2.2.4主机发送给目的端口6800的所有报文,并把它保存到a.cap文件中:
tcpdump 'src host 210.2.2.4 and dst port 6800' -s 1500 -w a.cap

tcpdump进阶

tcpdump还可以根据报文里面的某个字段来做匹配,实现方式为表达式+数学运算,比如现在有个需求:

匹配所有TCP的SYN置位的报文

以上的普通expression无法实现这个需求,TCPDUMP支持匹配报文的某个字节,再利用数学运算一起构建表达式。具体如下,TCP的flag字段位于TCP报文头的第13个字节(从0开始计数)
tcpdump命令_tcpdump_02
tcp[13]可以表达tcp报文头部的第13个字节,当只有SYN置位时FLAGS如下
tcpdump命令_端口号_03
把flags的8位换算成10进制:
tcpdump命令_置位_04
所以可以用tcp[13] = 2匹配SYN置位的报文
示例:tcpdump 'tcp[13]=2' -n
但上面的表达式只能匹配只有SYN置位的报文,如果想匹配SYN置位,其他标志位不关心就需要用到逻辑运算,可以把第13字节的值跟2做与运算,这样就可以做到只关心SYN位。如下所示:

00010010(SYN-ACK) & 00000010 = 00000010
示例:tcpdump 'tcp[13] & 2 = 2' -n

有些报文头里面的部分字段它的长度大于1个字节,比如IP报文头里面的报文总长度,它总占用2个字节,如果要匹配总长度大于1000的报文,可以在位置后面跟一个size的参数,格式为proto [ expr : size ],如
示例:tcpdump 'ip[2:2] > 1000 and icmp' -n,匹配大于1000的ping报文。

常用示例:
(1)截取组播报文:
tcpdump 'ether[0] & 1 = 1' -n
(2)截取TCP的标志位是SYN的报文:
tcpdump 'tcp[13] & 2 = 2' –n
(3)截取IP报文头中携带了option选项的报文
tcpdump 'ip[0] & 5 != 5' -n