易栈 · 一盏

塞外秋来,衡阳雁去

工具篇:tcpdump命令详解

tcpdump是命令行抓包工具。

一、过滤表达式

过滤表达式用来过滤要抓取的包。一旦指定了过滤表达式,只有满足过滤表达式的包才会被显示。过滤表达式(filter expression)表达元(primitives)组成。可以用运算符and、or和not对表达元进行组合,表达元和运算符之间用空格分隔。例如:

tcpdump host 192.168.1.2 and port 80

其中“host 192.168.1.2”和“port 80”都是表达元。这里是把表达式作为多个参数传递,也可以用引号“"”括起来,作为一个参数传递,例如:

tcpdump "host 192.168.1.2 and port 80"

表达元的语法如下:

primitive = [proto] [dir] [type] id

其中proto、dir、type都是修饰符,用来修饰id。一些修饰符可以单独使用(不需要id),例如inbound/outbound和大部分proto修饰符。 

  • id:是数字(端口号、端口号范围等)或者字符串(IP地址、主机名、硬件地址等)。 
  • type:用来指定id的类型。可选值为host、net、port、portrange。缺省值为host。 
  • dir:用来指定id对应的数据传输方向。可选值为src、dst、src or dst、src and dst、addr1、addr2、addr3、addr4、inbound、outbound。缺省值为src or dst。其中addr1~addr4只用于无线网卡。inbound和outbound用于串行链路(例如SLIP),表示输入输出。 
  • proto:用来指定id对应的协议类型。可选值为ether、fddi、tr、wlan、ip、ip6、arp、rarp、decnet、tcp、udp。不同类型的id,对应的proto缺省值也不同。例如id是端口时,缺省值为“tcp or udp”;id是ipv4地址时,缺省值为“ip or arp or rarp”。 不同类型的id,使用的proto修饰符也有限制。例如id是端口号时,只能用tcp、udp来修饰;id是ipv4地址时,只能用ip、arp、rare。

可以用条件表达式来做表达元。条件表达式的运算元和运算符如下:

  • 运算元:可以取协议包中的数据。“proto [start : size]”表示取proto协议包中从start位置开始的size个字节的数据,start可以是数字也可以是表达式,size默认值为1。 
  • 运算符:支持标准C运算符,例如(+, -, *, /, &, |,<<, >>, >, <, <=, =, !=)。 

也可以-F选项来指定过滤表达式文件。指定了这个选项之后,将优先使用过滤表达式文件中的过滤表达式(命令行中的过滤表达式将被忽略)。

二、打印格式

  • -n:不要把地址(主机名、端口号)显示成名字(域名、服务名)。
  • -N:不要打印完整域名。例如如果指定了该选项,“nic.ddn.mil”将被打印成“nic” 。
  • -q:安静输出模式。精简打印信息,使输出行更短。 
  • -S:打印完整的TCP序列号(而不是相对值)。 
  • -T:强制使用某种格式来解析过滤后的包数据。常用的类型有rtp、rtcp、tftp、snmp等。以rtp为例,rtp是应用层协议,而且使用的端口是动态协定的,tcpdump不能根据端口号判断协议类型,所以不会主动把包解析成rtp包。如果知道rtp的大致端口范围,可以先通过portrange来过滤出rtp包,然后指定“-T rtp”选项强制用rtp格式来解析包内容。另外由于rtp是基于udp的,所以即使指定了-T选项,tcp报文段也不会被强行解释成rtp包。

三、打印详细内容

  • -e:打印链路层首部。这个选项可以用来查看MAC地址,在抓DHCP包的时候很有用。 
  • -A:用ASCII打印每个包(除链路层头部)。用来抓http包非常好用。 
  • -x:用16进制打印每个包(除链路层首部)。对于链路层,如果有填充字节的话,填充字节也会被打印出来。 
  • -xx:用16进制打印每个包(包括链路层首部) 。
  • -X:用16进制和ASCII打印每个包(除链路层首部)。用来分析新的不了解的协议非常方便。
  • -XX:用16进制和ASCII打印每个包(包括链路层首部)。 
  • -v:解析包内容并打印时,打印稍微详细一点的内容。例如IP包中的TTL、标识、总长度和选项部分。这个选项会使能包的完整性检查,例如校验IP和ICMP的校验码。 使用-w选项输出到文件时,指定-v选项会每10s打印一次抓包数量。 
  • -vv:打印比-v更详细的内容。例如NFS应答包的附加域。 
  • -vvv:打印比-vv更详细的内容。例如telnet协商的选项。 

四、时间戳格式

  • -J:列出每个接口支持的所有时间戳类型。 数据包从发到网卡,到被协议栈取用之间有时间差,这个时间戳类型是指打印的数据包时间是主机提供的还是网卡提供的,是高精度的还是低精度的。不同的接口支持的时间戳类型可能不同。
  • -j tstamp_type:指定时间戳类型。 
  • -t:输出中不要打印时间戳。 
  • -tt:打印Unix时间戳(距离1970/01/01的秒数)。例如1460017475.599593 
  • -ttt:打印当前包相对前一个包的时间差。 
  • -tttt:打印经过格式化的时间戳。例如2016-04-07 16:25:37.077923。
  • -ttttt:打印当前包相对起始包的时间差。 

五、读写文件

可以将抓包数据保存到文件中,然后用Wireshark打开分析。

  • -w file:不解析不打印,直接把原始包内容写入指定文件。file为“-”表示使用标准输出。
  • -r file:从文件中读取抓包数据。file为“-”表示使用标准输入。 

有时候要持续抓包的时候,如果把数据都写到同一个文件,那么文件可能会很大,拷贝和查看都很困难。可以通过-C选项和-G选项来切分文件

  •  -C filesize:限制每个文件的大小为filesize,超过filesize则关闭当前文件,打开一个新的文件进行写入。新文件的文件名为-w选项指定的文件名加上一个数字的后缀(从1开始递增)。filesize的单位是百万字节,而不是MB(1,000,000字节,而不是1,048,576字节)。 
  • -G seconds:限制每个文件只写seconds秒,也就是每隔seconds秒关闭当前文件,打开一个新文件进行写入。-w选项指定的文件名中可以包含strftime的时间格式字符串(例如log_%H.%M.%S),新文件名会按照这个格式根据当前时间生成。如果没有指定时间格式字符串,表示每次重新创建文件时文件名都不会变,那么这个文件会不断被重写。
  • -W filecount:如果与-C选项一起使用,它会限定创建的文件个数。写满了filecount个文件,会循环从第一个文件写起(就像一个环状buffer)。如果与-G选项一起使用,它会限定创建的文件个数。写满了filecount个文件后程序退出。
  • -z cmd:与-C或-G选项一起使用,每写满一个文件就会执行“cmd file”。例如可以通过指定-z gzip来压缩输出文件(每写满一个文件fileN,就执行gzip fileN)。 注意命令执行和抓包是并行的,命令进程将用最低优先级来运行,以避免影响抓包的实时性。 

-C选项和-G选项混用时现象比较复杂,建议分开使用。

六、混杂模式

前面讲过以太网是一种广播网络,网络中每个节点都可以看到在网络中发送的所有数据包,但是节点一般会把不是发往自己MAC地址的数据包丢弃。如果想让网卡抓取其它主机MAC地址的数据包,必须开启网卡混杂模式。混杂模式(Promiscuous mode)简单来说就是让网卡抓取任何经过它的数据包,不管这个数据包是不是发给它或者是它发出的。 监控模式(Monitor mode)只支持WIFI网卡,监控模式对WIFI网卡的作用与混杂模式对以太网卡的作用类似(但是混杂模式在WIFI网卡和以太网卡上的表现是不同的)。

  • -L:列出网络接口所支持链路层类型(注意同一个接口在不同模式下支持的链路层类型不同)。
  • -I:将接口设置成监控模式; 只支持IEEE 802.11 Wi-Fi接口,并且只有部分系统支持。 
  • -p:不要把接口设置成混杂模式。注意接口可能会由于其他原因而处于混杂模式,这个选项无法保证接口不是混杂模式。

七、属性设置

  • -D:列出所有可以抓包的网络接口名称(eth0、lo)。这个选项不支持能列出网卡信息的命令(例如ifconfig)的系统中比较有用。 
  • -i interface:指定要监听的网络接口。如果没有指定,默认监听网络接口列表的第一个已启用的网络接口(除环回接口外)。指定多个接口时可以用逗号“,”分隔。可以用any指代“全部网络接口”。 
  • -c count:抓满count个包后退出程序 。
  • -B buffer_size:设置操作系统的抓包缓冲区大小,单位是KB。 
  • -s snaplen:设置每个包的抓取长度为snaplen(默认为65535 bytes)。如果这个值太小,包会被截断,打印的时候会显示“[|proto]”(proto为发生截断的协议层名称)。注意snaplen越大,处理包的耗费的时间越长,tcpdump缓冲区中可缓冲的包数目越少,这可能会导致包丢失。在保证能获取到足够信息的前提下,抓取长度应该越小越好。
  • -l:把标准输出设置成行缓冲。
  • -U:把标准输出/文件输出设置成包缓冲。强制每收到一包就输出(打印/写入文件),而不是等输出缓冲满。

本文链接:易栈 - 工具篇:tcpdump命令详解