图源
视觉中国
来源
Python编程时光(ID:Cool-Python)
今天要给大家介绍的一个Unix下的一个网络数据采集分析工具--Tcpdump,也就是我们常说的抓包工具。
与它功能类似的工具有wireshark,不同的是,wireshark有图形化界面,而tcpdump则只有命令行。
由于我本人更习惯使用命令行的方式进行抓包,因此今天先跳过wireshark,直接给大家介绍这个tcpdump神器。
这篇文章,我肝了好几天,借助于Linux的man帮助命令,我把tcpdump的用法全部研究了个遍,才形成了本文。
不夸张的说,应该可以算是中文里把tcpdump讲得最清楚明白,并且最全的文章了(至少我从百度、谷歌的情况来看是这样),所以本文值得你收藏分享,就怕你错过了,就再也找不到像这样把tcpdump讲得直白而且特全的文章了。
在讲解之前,有两点需要声明:
第三节到第六节里的tcpdump命令示例,只为了说明参数的使用,并不一定就能抓到包,如果要精准抓到你所需要的包,需要配合第五节的逻辑逻辑运算符进行组合搭配。不同Linux发行版下、不同版本的tcpdump可能有小许差异,本文是基于CentOS7.2的4.5.1版本的tcpdump进行学习的,若在你的环境中无法使用,请参考mantcpdump进行针对性学习。
tcpdump核心参数图解
大家都知道,网络上的流量、数据包,非常的多,因此要想抓到我们所需要的数据包,就需要我们定义一个精准的过滤器,把这些目标数据包,从巨大的数据包网络中抓取出来。
所以学习抓包工具,其实就是学习如何定义过滤器的过程。
而在tcpdump的世界里,过滤器的实现,都是通过一个又一个的参数组合起来,一个参数不够精准,那就再加一个,直到我们能过滤掉无用的数据包,只留下我们感兴趣的数据包。
tcpdump的参数非常的多,初学者在没有掌握tcpdump时,会对这个命令的众多参数产生很多的疑惑。
就比如下面这个命令,我们要通过host参数指定hostip进行过滤
$tcpdumphost..10.
主程序+参数名+参数值这样的组合才是我们正常认知里面命令行该有的样子。
可tcpdump却不走寻常路,我们居然还可以在host前再加一个限定词,来缩小过滤的范围?
$tcpdumpsrchost..10.
从字面上理解,确实很容易理解,但是这不符合编写命令行程序的正常逻辑,导致我们会有所疑虑:
除了src,dst,可还有其它可以用的限定词?src,host应该如何理解它们,叫参数名?不合适,因为src明显不合适。如果你在网上看到有关tcpdump的博客、教程,无一不是给你一个参数组合,告诉你这是实现了怎样的一个过滤器?这样的教学方式,很容易让你依赖别人的文章来使用tcpdump,而不能将tcpdump这样神器消化,达到灵活应用,灵活搭配过滤器的效果。
上面加了src本身就颠覆了我们的认知,你可知道在src之前还可以加更多的条件,比如tcp,udp,icmp等词,在你之前的基础上再过滤一层。
$tcpdumptcpsrchost..10.
这种参数的不确定性,让大多数人对tcpdump的学习始终无法得其精髓。
因此,在学习tcpdump之前,我觉得有必要要先让你知道:tcpdump的参数是如何组成的?这非常重要。
为此,我画了一张图,方便你直观的理解tcpdump的各种参数:
option可选参数:将在后边一一解释,对应本文第四节:可选参数解析proto类过滤器:根据协议进行过滤,可识别的关键词有:upd,udp,icmp,ip,ip6,arp,rarp,ether,wlan,fddi,tr,decnettype类过滤器:可识别的关键词有:host,net,port,portrange,这些词后边需要再接参数。direction类过滤器:根据数据流向进行过滤,可识别的关键字有:src,dst,同时你可以使用逻辑运算符进行组合,比如srcordstproto、type、direction这三类过滤器的内容比较简单,也最常用,因此我将其放在最前面,也就是第三节:常规过滤规则一起介绍。
而option可选的参数非常多,有的甚至也不经常用到,因此我将其放到后面一点,也就是第四节:可选参数解析
当你看完前面六节,你对tcpdump的认识会上了一个台阶,至少能够满足你80%的使用需求。
你一定会问了,还有20%呢?
其实tcpdump还有一些过滤关键词,它不符合以上四种过滤规则,可能需要你单独记忆。关于这部分我会在第六节:特殊过滤规则里进行介绍。
理解tcpdump的输出
2.1输出内容结构
tcpdump输出的内容虽然多,却很规律。
这里以我随便抓取的一个tcp包为例来看一下
21:26:49.IP.20.20.1..20.20.2.:Flags[P.],seq49:97,ack,win,length48
从上面的输出来看,可以总结出:
第一列:时分秒毫秒21:26:49.第二列:网络协议IP第三列:发送方的ip地址+端口号,其中.20.20.1是ip,而是端口号第四列:箭头,表示数据流向第五列:接收方的ip地址+端口号,其中.20.20.2是ip,而是端口号第六列:冒号第七列:数据包内容,包括Flags标识符,seq号,ack号,win窗口,数据长度length,其中[P.]表示PUSH标志位为1,更多标识符见下面2.2Flags标识符
使用tcpdump抓包后,会遇到的TCP报文Flags,有以下几种:
[S]:SYN(开始连接)[P]:PSH(推送数据)[F]:FIN(结束连接)[R]:RST(重置连接)[.]:没有Flag,由于除了SYN包外所有的数据包都有ACK,所以一般这个标志也可表示ACK
常规过滤规则
3.1基于IP地址过滤:host
使用host就可以指定hostip进行过滤
$tcpdumphost..10.
数据包的ip可以再细分为源ip和目标ip两种
#根据源ip进行过滤$tcpdump-ieth2src..10.#根据目标ip进行过滤$tcpdump-ieth2dst..10.
3.2基于网段进行过滤:net
若你的ip范围是一个网段,可以直接这样指定
$tcpdumpnet..10.0/24
网段同样可以再细分为源网段和目标网段
#根据源网段进行过滤$tcpdumpsrcnet.#根据目标网段进行过滤$tcpdumpdstnet.
3.3基于端口进行过滤:port
使用port就可以指定特定端口进行过滤
$tcpdumpport
端口同样可以再细分为源端口,目标端口
#根据源端口进行过滤$tcpdumpsrcport#根据目标端口进行过滤$tcpdumpdstport
如果你想要同时指定两个端口你可以这样写
$tcpdumpport80orport
但也可以简写成这样
$tcpdumpport80or
如果你的想抓取的不再是一两个端口,而是一个范围,一个一个指定就非常麻烦了,此时你可以这样指定一个端口段。
$tcpdumpportrange-$tcpdumpsrcportrange-$tcpdumpdstportrange-
对于一些常见协议的默认端口,我们还可以直接使用协议名,而不用具体的端口号
比如