tcpdump

tcpdump

描述

转储网络流量(dump traffic on a network)。tcpdump打印输出指定网络接口上,匹配指定布尔表达式(过滤器)的数据包。

tcpdump 能截获指定网络接口上所有你感兴趣的包,不足之处是tcpdump对截获的数据并没有进行彻底解码,数据包内的大部分内容是使用十六进制的形式直接打印输出的。显然这不利于分析网络故障,通常的解决办法是先使用带-w参数的tcpdump 截获数据并保存到文件中,然后再使用其他程序(如Wireshark)进行解码分析。当然也应该定义过滤规则,以避免捕获的数据包填满整个硬盘。

 

输出与输入重定向

通过使用 -w 标志可以把数据包保存到文件,以供稍后分析。

通过时用 -r 标志可以从一个保存的包文件中,而不是一个网络接口读取数据包。

使用格式:tcpdump [ -r file] [ -w file]

tcpdump表达式(适用于wireshark)

表达式实际上就是tcpdump的过滤器。表达式用于决定哪些数据包将被打印。如果没有指定表达式,就会答应输出网络接口截获的所有的包。

表达式由一个或多个表达元组成。 表达元可理解为组成表达式的基本元素。一个表达元通常由一个或多个关键字后跟一个参数组成。有三种不同类型的关键字:

第一种类型是关于类型(type)的关键字,主要包括host, net, port, portrange。例如:host 192.168.1.210,指明192.168.1.210是一台主机。 net 192.168.1.0,指明192.168.1.0是一个网络。port 53指明53是一个端口。portrange 5000-5005指定端口范围为5000至5005。 缺省类型是host。

第二种类型是关于方向(dir)的关键字,主要包括src, dst, dst or src, dst and src,这些关键字指明了传输的方向。 例如:dst host 192.168.1.210指明ip包中目标地址是192.168.1.210。缺省是dst or src。

第三种是协议(proto)的关键字,主要包括fddi, ether, tr, wlan, ip, ip6, arp, rarp, decnet, tcp, udp, http等。ether, fddi, tr, 具体含义未知, 需补充。 可理解为物理以太网传输协议,光纤分布数据网传输协议,以及用于路由跟踪的协议。  wlan, 无线局域网协议;ip,ip6 即通常的TCP/IP协议栈中所使用的ipv4以及ipv6网络层协议;arp, rarp 即地址解析协议,反向地址解析协议;decnet, Digital Equipment Corporation开发的, 最早用于PDP-11 机器互联的网络协议; tcp and udp, 即通常TCP/IP协议栈中的两个传输层协议。如果没有指定任何协议,则tcpdump将会监听所有协议的包。例如:arp net 128.3:发往或来自128.3网络的arp协议数据包。

除了上述三种类型,其它重要的关键字还包括:gateway, broadcast, less, greater。less, greater用于指定数据包的长度。

表达元之间可以通过andor以及not进行连接, 也可以使用相应的&&||!。从而可以组成比较复杂的条件表达式。例如, tcpdump -i eth0 ip and host www.baidu.com:截获发送或来自www.baidu.com的所有ip包。

借助括号以及相应操作符,可把表达元组合在一起使用(由于括号是shell的特殊字符, 所以在shell脚本或终端中使用时必须对括号进行转义, 即'(' 与')'需要分别表达成'\(' 与 '\)')。

 

tcpdump常用选项

-A     以ASCII码方式显示每一个数据包(不会显示数据包中链路层头部信息)。在抓取包含网页数据的数据包时,可方便查看数据。

-c     count

 在接收到count个包后退出

-D     打印系统中所有tcpdump可以在其上进行抓包的网络接口。每一个接口会打印出数字编号,相应的接口名字, 以及可能的一个网络接口描述。其中网络接口名字和数字编号 可以用在tcpdump 的-i flag 选项。

-e     每行的打印输出包括数据链路层的头部信息

-i     interface

指定tcpdump 需要监听的接口。如果没有指定,tcpdump 会从系统接口列表中搜寻编号最小的已配置好的接口(不包括 loopback 接口)。一但找到第一个符合条件的接口,搜寻马上结束。

-F   file

使用file 文件作为过滤条件表达式的输入, 此时命令行上的输入将被忽略。

-n    不对地址(比如, 主机地址, 端口号)进行数字表示到名字表示的转换。

-xx   tcpdump 会打印每个包的头部数据, 同时会以16进制打印出每个包的数据, 其中包 数据链路层的头部.

-X    当分析和打印时, tcpdump 会打印每个包的头部数据, 同时会以16进制和ASCII码形式打印出每个包的数据(但不包括连接层的头部).这对于分析一些新协议的 数据包很方便.

-XX  当分析和打印时, tcpdump 会打印每个包的头部数据, 同时会以16进制和ASCII码形式打印出每个包的数据, 其中包括数据链路层的头部.这对于分析一些新协议 的数据包很方便。

-C    file-size

该选项使得tcpdump 在把原始数据包直接保存到文件中之前, 检查此文件大小是否超 过file-size. 如果超过了, 将关闭此文件,另创一个文件继续用于原始数据包的记录. 新 创建的文件名与-w 选项指定的文件名一致, 但文件名后多了一个数字.该数字会从1开 始随着新创建文件的增多而增加. file-size的单位是百万字节。

-s snaplen

-s 0: 抓取数据包时默认抓取长度为68字节。加上-s 0 后可以抓到完整的数据包。

 

监视指定主机的数据包

截获发送到或来自主机www.baidu.com的数据包

tcpdump host www.baidu.com

截获本机与主机www.google.com或主机www.uc.cn之间的通信

tcpdump host localhost and \( www.google.com or www.uc.cn\ )

 

监视指定协议的数据包

TCP

TCP头中有8位控制位:

 CWR | ECE | URG | ACK | PSH | RST | SYN | FIN

假定我们想要观察用于创建TCP连接的包。我们知道TCP使用三次握手SYN > SYN-ACK >ACK来创建一个连接。

现在我们对只设置了SYN位的包感兴趣。注意,我们只想要初始的SYN包(三次握手的第一步),不想要也设置了ACK位的包(三次握手的第二步)。我们应该怎样写正确的过滤表达式呢?

我们来看看不带选项的TCP头:

0                            15                              31

-----------------------------------------------------------------

|          source port          |       destination port        |

-----------------------------------------------------------------

|                        sequence number                        |

-----------------------------------------------------------------

|                     acknowledgment number                     |

-----------------------------------------------------------------

|  HL   | rsvd  |C|E|U|A|P|R|S|F|        window size            |

-----------------------------------------------------------------

|         TCP checksum          |       urgent pointer          |

-----------------------------------------------------------------

无选项的TCP头是20字节。上图中第一行包含0-3字节,第二行是4-7字节,以此类推...

从0算起,TCP的控制位包含在第13字节:

0             7|             15|             23|             31

----------------|---------------|---------------|----------------

|  HL   | rsvd  |C|E|U|A|P|R|S|F|        window size            |

----------------|---------------|---------------|----------------

|               |  13th octet   |               |               |

进一步看看第13字节:

                |C|E|U|A|P|R|S|F|

                |---------------|

                |0 0 0 0 0 0 1 0|

                |---------------|

                |7 6 5 4 3 2 1 0|

观察控制位区域,我们发现只有bit 1(SYN)被设置了。把第13字节看做是一个网络字节序的8位无符号整型数。该字节的二进制表示为:00000010,它的十进制表示为:

7     6     5     4     3     2     1     0

0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 1*2 + 0*2  =  2

我们快知道答案了,因为现在我们知道只有SYN被设置,TCP头中的第13字节,当被解释为8位无符号整型数时,它的值正好是2。这个关系可以表达为:

tcp[13] = 2

我们可以使用这个表达式作为tcpdump的过滤器来监视仅仅设置了SYN位的包:

tcpdump -i eth0 tcp[13] = = 2

这个表达式的意思是:让TCP包的第13字节的值为2,这正是我们想要的。

 

我们来看另外一个例子。假设我们需要截获SYN包,这一次我们不关系ACK是否被设置。我们先来看看当SYN-ACK数据报到来时,TCP头的第13字节的情况:

     |C|E|U|A|P|R|S|F|

     |---------------|

     |0 0 0 1 0 0 1 0|

     |---------------|

     |7 6 5 4 3 2 1 0|

第13字节的第1位和第4位被置为1,它的二进制表示为:

00010010

十进制为18

我们不能简单的使用 ‘tcp[13] == 18’这个表达式,因为这样只能截获SYN-ACK包,而我们想要的是设置了SYN的包。记住我们不关心ACK或其它的控制位是否被设置。好了,不多说了,正确的表达式是:

tcpdump -i xl0 'tcp[13] & 2 == 2'

一些常用的偏移和位能用名称表示就好多了。例如tcp[13]可以用tcp[tcpflags]替换。tcpdump是支持这种表达的。可以使用的tcp标志域值有:tcp-fin, tcp-syn, tcp-rst, tcp-push, tcp-act, tcp-urg

一个示例:

tcpdump -i xl0 'tcp[tcpflags] & tcp-push != 0'

注意:要使用单引号或者转义字符,避免shell对‘&’进行解释和替换(‘&’是shell的特殊字符)

 

HTTP

使用tcpdump抓取http包

tcpdump -Xs 0 -i eth0 tcp[20:2]=0x4745 or tcp[20:2]=0x4854

0x4745 为"GET"前两个字母"GE",0x4854 为"HTTP"前两个字母"HT"。

如果使用tcpdump -Xs 0 -i eht0 tcp port 80 会抓取到很多额外的包

总结

tcpdump支持强大的过滤表达式,不足之处是,解码方面比较弱,只支持简单的ASCII码或16进制输出。除了上面所阐述的常用功能外,tcpdump还有很多其它功能,有待研究。

 

参考:

http://petermis.blog.51cto.com/2336802/997564

http://www.tcpdump.org/tcpdump_man.html

你可能感兴趣的:(tcpdump)