tcpdump在Linux系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息。
tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来去掉无用的信息。
不带参数的tcpdump会收集网络中所有的信息包头,数据量巨大,必须过滤。
-i 指定监听的网络接口
-nn IP和端口均以数字形式显示
-c 在收到指定的数量的分组后,tcpdump停止,如果没有这个参数,tcpdump会持续不断的监听直到用户输入 [ctrl]-c 为止
-e 输出数据链路层的头部信息(显示MAC地址相关信息)。
-t 在输出的每一行不打印时间戳
-q 只输出较少的协议信息(仅输出协议名称,如TCP;而不输出封包标记信息,如F、P等标记)
-w FILE直接将分组写入文件中,而不是到stdout
-r FILE从后面接的文件将数据包数据读出来。那个「文件」是已经存在的文件,并且这个「文件」是由 -w 所制作出来的
-s 设置tcpdump的数据包抓取长度为len,如果不设置默认将会是65535字节。对于要抓取的数据包较大时,长度设置不够可能会产生包截断,若出现包截断,输出行中会出现"[|proto]"的标志(proto实际会显示为协议名)。但是抓取len越长,包的处理时间越长,并且会减少tcpdump可缓存的数据包的数量,从而会导致数据包的丢失,所以在能抓取我们想要的包的前提下,抓取长度越小越好(-s 0 使用默认长度65535)。
-D 列出可用于抓包的接口。将会列出接口的数值编号和接口名,它们都可以用于"-i"后
-L 列出网络接口的已知数据链路。
-F 从文件中读取抓包的过滤表达式。若使用该选项,则命令行中给定的其他表达式都将失效。
-A 数据包的内容以 ASCII 显示,通常用来捉取WWW的网页数据包资料
-X 数据包内容以十六进制 (hex)和ASCII显示,对于监听数据包内容很有用
-XX 比-X输出更详细
如果不使用-i选项明确要监听的接口,直接启动tcpdump将监视第一个网接口上所有流过的数据包
示例:
每行数据的说明:第一个分组为例
每行数据的说明:第一个分组为例
22:49:58 时间
464690 ID
IP 表明是IP分组
10.0.0.61.22 分组发出源头的主机IP地址
或< 代表封包流动方向
10.0.0.1 分组目的地的主机IP地址
62659 目的地主机端口
Flags [P.] 标记(PUSH表示传输数据)
seq 1389539161:1389539401 tcp的序列号范围(第一个包显示的是绝对值,后续的包显示的是相对值,如果也想显示绝对值,使用-T选项)
ack 718462004 表明对序列号是718462004的包进行响应
win 325 表明发送窗口的大小是325
options [nop,nop,TS val 110216407 ecr 185503372] #一些选项值
length 240 封包长度报文过滤表达式
表达式是一个正则表达式,tcpdump利用它作为过滤报文的条件,如果一个报文满足表达式的条件,则这个报文将会被捕获。如果没有给出任何条件,则网络上所有的信息包将会被截获,每条报文显示的信息过多难以分析,使用表达式经过滤出我们需要的信息
第一种是关于类型的关键字:主要包括host(默认),net,port,portrange
host和net可搭配第2类的传输方向关键字
port可搭配第3类的各种协议关键字
例:
host 210.27.48.2 #指明 210.27.48.2是一台主机,
net 202.0.0.0 #指明202.0.0.0是一个网络地址,
port 23 #指明端口号是23
portrange 6000-6008" #默认的type为host。
如果没有指定类型,缺省的类型是host
第二种是确定传输方向的关键字:主要包括src,dst,dst or src(默认),dst and src,这些关键字指明了传输的方向。可组合第一类关键字中的host,net,port,portrange
例:
src host 210.27.48.2 #指明ip包中源地址是210.27.48.2
dst net 202.0.0.0 #指明目的网络地址是202.0.0.0
如果没有指明方向关键字,则缺省是src or dst关键字
第三种是协议类关键字:主要包括ip,tcp,udp,icmp,arp,rarp,fddi等类型
只能组合第一类关键字中的port
如果没有指定任何协议,则tcpdump将会监听所有协议的信息包。
其他重要的关键字:gateway,broadcast,less,greater。
三种逻辑运算可用于组合上述的关键字:
取非运算是 ‘not’,‘!’
与运算是’and’,’&&’
或运算是’or’ ,’||’
这3个关键字可以任意组合
示例1:
在一个终端机窗口输入“tcpdump -nn -i lo”
再开一个终端,使用ssh 127.0.0.1登入,抓包,查看TCP的3次握手,和4次挥手过程
上述是TCP的3次握手
从标记P开始是传送数据
然后断开ssh连接
下面是TCP的4次挥手
示例2:测试-X选项的作用
一个窗口开始监听,另一个窗口进行ssh登录操作
可以看出使用-X选项,会将监听的数据同时以16进制及ASCII码形式显示(如果传输数据明文方式,如是有密码,将会被监听到)
示例3:
在10.0.0.61上监听,从10.0.0.8主机上ssh连接
由于使用了src port源端口过滤,因此三次握手仅监听到1次
示例4:
使用-w选项将,监听的数据输出到文件中,而不是stdout
其它示例:
1、获取所有10.0.0.61 的主机收到的和发出的所有的数据包
会有很多数据被输出
2、获取主机10.0.0.61和主机10.0.0.8 或10.0.0.7的通信,使用命令:
在命令行中使用括号时,一定要使用反斜线\转义
3、获取主机10.0.0.61除了和主机10.0.0.7之外所有主机通信的ip包,使用命令:
注意:!和IP地址之间至少有1个空格
4、获取主机10.0.0.7接收或发出的ssh(TCP)包
5、监听来自主机名为hostname主机的发送的数据包,主机名可以是本地主机,也可以是网络上的任何一台计算机
前提条件是:必须能够解析主机名
6、监听所有发送到主机hostname的数据包
tcpdump对截获的数据并没有进行彻底解码(-X选项显示),数据包内的大部分内容是使用十六进制的形式直接打印输出的。显然这不利于分析网络故障,通常的解决办法是先使用带-w参数的tcpdump 截获数据并保存到文件中,然后再使用其他程序进行解码分析。
除了过滤语句,还有一个很重要的参数,若设置不正确,会导致包数据的丢失!
它就是-s 参数,snaplen,也就是数据包的截取长度,默认截取长度为60个字节,但一般ethernet MTU都是1500字节。所以,要抓取大于60字节的包时,使用默认参数就会导致包数据丢失!只要使用-s 0就可以按包长,截取数据!
TCP协议头中有8个标记位:
CWR | ECE | URG | ACK | PSH | RST | SYN | FIN
假设我们想要观察用于建立TCP连接的数据包。 回想一下,TCP在初始化一个新的连接时使用3次握手协议; 关于TCP控制位的连接顺序是:
1.客户端发送SYN
2.服务端回应SYN和ACK
3.客户端发送ACK
现在我们对捕获仅包含SYN位的数据包感兴趣(步骤1)。 请注意,我们不希望步骤2(SYN-ACK)的数据包,只是一个普通的初始SYN。
TCP头的结构:
TCP头包含20个字节固定长度的数据(上图中的前4行),而控制位位于第13个字节(字节计算从0开始)
只看我们感兴趣的控制位:
这些是我们感兴趣的TCP控制位。我们对这个八位组中的位进行了编号,从0到7,从右到左,所以PSH位是位编号3,而URG位是编号5
回想一下,我们想要捕获只有SYN集的数据包。 让我们来看看如果一个TCP数据报到达并且在其头部设置了SYN位,会发生什么情况?
可以看到控制位部分只有位1(SYN位)被设置。
假定八位字节编号13(及第4个字节)是网络字节顺序中的8位无符号整数,则该八位字节的二进制值是 00000010
其十进制计算如下:
02 + 02 + 02 + 02 + 02 + 02 + *12* + 02 = 2
我们已经差不多完成了,因为现在我们知道如果只设置了SYN,TCP头中的第13个八位字节的值在网络字节顺序中解释为8位无符号整数时,必须恰好为2。
这种关系可以表示为:
tcp[13] == 2
我们可以使用这个表达式作为tcpdump的过滤器,以便观察只有SYN集合的数据包:
tcpdump -i xl0 tcp[13] == 2
表达式表示“让TCP数据报的第13个八位字节具有十进制值2”,这正是我们想要的。
现在,我们假设我们需要捕获SYN数据包,但我们并不在乎ACK或任何其他TCP控制位是否同时被设置。 看看带有SYN-ACK的TCP数据包是怎样的?
可以看到在第13个八位字节中只有第一位和第四位被设置。其二进制值是00010010
转换成十进制:
02 + 02 + 02 + 12 + 02 + 02 + 12 + 02 = 18
不能只用‘tcp[13] == 18‘作为tcpdump的过滤表达式, 因为这将导致只选择含有SYN-ACK标志的数据包, 其他的都被丢弃(只有SYN标志的包也会被丢弃).
而我们想要的是只要包的SYN标志被设置就将其过滤出来
为了实现我们的目标,我们需要将八位组13的二进制值与其他值进行逻辑与,以保留SYN位(只要其他包的也包含了SYN标记,进行与运算得到的结果就是1)。 我们知道我们希望在任何情况下都设置SYN,所以我们将第13个字节中的值与SYN的二进制值进行逻辑与:
我们看到,无论是否设置了ACK或另一个TCP控制位,此AND操作都会提供相同的结果。 AND值的十进制表示以及此操作的结果是2(二进制00000010),所以我们知道对于设置了SYN的数据包,以下关系必须为真:
( ( value of octet 13 ) AND ( 2 ) ) == ( 2 )
第13个字节上其他位设置不管如何 与 SYN(2)进行与操作
使用tcpdump过滤表达式如下:
tcpdump -i xl0 ’tcp[13] & 2 == 2’
其他示例:
1、打印涉及非本地主机的每个TCP会话的开始和结束数据包(SYN和FIN数据包)
tcpdump ’tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net localnet’
2、打印所有来自端口80的IPv4 HTTP数据包,即仅打印包含数据的数据包,而不打印例如SYN和FIN数据包以及仅ACK数据包。
tcpdump ’tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)’
3、打印通过网关snup发送的长度超过576字节的IP数据包:
tcpdump ’gateway snup and ip[2:2] > 576’
4、要打印未通过以太网广播或多播发送的IP广播或多播数据包:
tcpdump ’ether[0] & 1 = 0 and ip[16] >= 224’
5、要打印所有不是回显请求/回复的ICMP数据包(即不是ping数据包):
tcpdump ’icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply’
原文地址:http://blog.51cto.com/nickfox/2089655