先从第一个最简单的抓包指令开始


抓经过本主机上的所有网络接口的所有ARP、ICMP、IGMP、IP、TCP、UDP等所有网络包(以下简称“所有网络包”)
tcpdump -i any -vnn
(注:-i用来指定tcpdump抓包所指定的网络接口名,比如eth0 eth1等等,这些网络接口名可以通过ifconfig看到。而any代表所有网络接口)
(注:-v表示显示每个包的更详细信息。-n表示禁用域名解析,不加它的话,tcpdump会对每次收到的数据包尝试域名解析这会导致有些时候“迟迟看不到输出”。加上这个选项让tcpdump直接输出IP地址。)
(注:这个指令几乎是最简单的,但它抓到的包却是包罗万象最全面的,经过本主机的所有网络通信数据全都逃不掉。但也正因为如此而实用性不强,因为抓到的网络包往往会含有太多与我们分析问题无关的数据而造成干扰。因此需要进行过滤。下面将介绍的种种抓包方法都是用来进行网络包过滤的)
 

根据IP、端口、网段进行过滤 
 
抓enp0s25网络接口上的所有网络包
tcpdump -i enp0s25 -vnn
(注:enp0s25是我用ifconfig命令看到的一个网络接口名)
 
抓enp0s25网络接口上的,源主机IP目的主机IP都不是192.168.26.141的所有网络包
tcpdump -i enp0s25 -vnn "host not 192.168.26.141"
 
(注:所有的单双引号都可以去掉并且完全不会改变语义,下同,比如上面的命令可以写成tcpdump -i enp0s25 -vnn host not 192.168.26.141,但是建议加上双引号,这样看起来清晰)
 
抓enp0s25网络接口上的,源端口和目的端口都不是7942的所有网络包
tcpdump -i enp0s25 -vnn "port not 7942"
 
抓enp0s25网络接口上的,源主机与目的主机所处的网段都不是192.168.26.0/24的网络包
tcpdump -i enp0s25 -vnn "net not 192.168.26.0/24"
(注:192.168.26.0/24 指子网掩码为24个1,IP为192.168.26.0的子网IP地址)
 
抓enp0s25网络接口上的,源主机不是192.168.26.200的所有网络包
tcpdump -i enp0s25 -vnn "src host not 192.168.26.200"
 
抓enp0s25网络接口上的,目的主机不是192.168.26.141的所有网络包
tcpdump -i enp0s25 -vnn "dst host not 192.168.26.141"
 
抓enp0s25网络接口上的,源端口不是7942的所有网络包
tcpdump -i enp0s25 -vnn "src port not 7942"
 
抓enp0s25网络接口上的,目的端口不是7942的所有网络包
tcpdump -i enp0s25 -vnn "dst port not 7942"
 
抓enp0s25网络接口上的,源主机IP所在的网段不为192.168.26.0/24的所有网络包
tcpdump -i enp0s25 -vnn "src net not 192.168.26.0/24"
 
抓enp0s25网络接口上的,目的主机IP所在的网段不为192.168.26.0/24的所有网络包
tcpdump -i enp0s25 -vnn "dst net not 192.168.26.0/24"
 
......
(注:可以看到他们的写法是完全类似的,有针对源和目的IP、源和目的端口、源和目的IP所在的子网地址这三者来进行网络包过滤的方法。其写法都是类似的:[src|dst] [host|port|net] [not] xxx)
 
(注:把not去掉则变成了“是”,比如:tcpdump -i enp0s25 -vnn "dst port 7942",表示抓取目的端口是7942的网络包,这对IP、port、net都有效)
 
抓enp0s25网络接口上的,源或者目的端口是7942的所有网络包
tcpdump -i enp0s25 -vnn "port 7942"
 
抓enp0s25网络接口上的,源主机IP是192.168.26.141的所有网络包
tcpdump -i enp0s25 -vnn "src host 192.168.26.141"
 
抓enp0s25网络接口上的,目的主机IP所在网段是192.168.26.0/24的所有网络包
tcpdump -i enp0s25 -vnn "dst net 192.168.26.0/24"
 
 

与协议相关的过滤
 
抓enp0s25网络接口上的所有TCP包
tcpdump -i enp0s25 -vnn tcp
 
抓enp0s25网络接口上的所有UDP包
tcpdump -i enp0s25 -vnn udp
 
抓enp0s25网络接口上的所有ICMP包
tcpdump -i enp0s25 -vnn icmp
 
抓enp0s25网络接口上的所有IGMP包
tcpdump -i enp0s25 -vnn igmp
 
抓enp0s25网络接口上的所有IP包
tcpdump -i enp0s25 -vnn ip
 
抓enp0s25网络接口上的所有ARP包
tcpdump -i enp0s25 -vnn arp
 
同样,它们也能用not关键字表示否定:
 
抓enp0s25网络接口上的所有不是UDP的网络包
tcpdump -i enp0s25 -vnn not udp
 
抓enp0s25网络接口上的所有不是ARP的网络包
tcpdump -i enp0s25 -vnn not arp
 
等等。
 
(注:用法都类似,[not] [ip|tcp|udp|icmp|igmp|arp|rarp|......])
 
 


 逻辑与或非操作


抓enp0s25网络接口上的,源主机不是192.168.26.141并且目的主机是192.168.26.141的所有网络包
tcpdump -i enp0s25 -vnn "src host not 192.168.26.141" and "dst host 192.168.26.141"
 
抓enp0s25网络接口上的,源主机不是192.168.26.141,并且源端口和目的端口都不是22的所有网络包
tcpdump -i enp0s25 -vnn "src host not 192.168.26.141" and "port not 22"
 
抓enp0s25网络接口上的,源主机所在网段为192.168.26.0/24的,且目的端口是22的所有网络包
tcpdump -i enp0s25 -vnn "src net 192.168.26.0/24" and "dst port 22"
 
抓enp0s25网络接口上的,源主机所在网段为192.168.27.0/24的,或者源端口为23的,或者目的端口不是22的所有网络包
tcpdump -i enp0s25 -vnn "src net 192.168.27.0/24" or "src port 23" or "dst port not 22"
 
抓enp0s25网络接口上的,源主机所在网段为192.168.27的,或者不满足“目的主机不是192.168.26.200”的所有网络包(即目的主机就是192.168.26.200)
tcpdump -i enp0s25 -vnn "src net 192.168.27.0/24" or not "dst host not 192.168.26.200"
 
抓enp0s25网络接口上的,源主机所在网段为192.168.27的,或者不满足 不满足“目的主机不是192.168.26.200”的所有网络包(即目的主机不是192.168.26.200)
tcpdump -i enp0s25 -vnn "src net 192.168.27.0/24" or not not "dst host not 192.168.26.200"
 
抓enp0s25网络接口上的,源或目的主机其中有一者的地址为192.168.26.200 并且 源或目的端口其中有一者为80的所有网络包
tcpdump -i enp0s25 -vnn "host 192.168.26.200" and "port 80"
 
抓enp0s25网络接口上的,源与目的主机地址都不是192.168.26.141 并且 源或目的端口其中有一者为80的所有网络包
tcpdump -i enp0s25 -vnn "host not 192.168.26.200" and "port 80"
 
 
能参与逻辑运算的,不仅仅是IP、port、net,协议相关的条件也能一起参与进来:
 
抓enp0s25网络接口上的,源与目的主机端口都不是22的所有网络包,或者所有UDP包。
tcpdump -i enp0s25 -vnn "port not 22" or udp
 
抓enp0s25网络接口上的,源或目的主机端口为80的TCP包,一般就是HTTP通信网络包
tcpdump -i enp0s25 -vnn "port 80" and tcp
 
下面这个命令啥都抓不到,因为ICMP包没有端口的概念,既是ICMP包并且源或目的端口是12345的包肯定没有。同理,IGMP、ARP包也一样。
tcpdump -i enp0s25 -vnn icmp and "port 12345"
 
抓enp0s25网络接口上的,IP或者TCP或者UDP或者IGMP或者ARP或者ICMP包。因为tcp udp igmp icmp都是属于ip包,唯独arp不属于ip包,因此下面这条指令可以简单地写成:tcpdump -i enp0s25 ip or arp
tcpdump -i enp0s25 ip or tcp or udp or igmp or arp or icmp
 
抓enp0s25网络接口上的,不是UDP并且不是TCP的所有网络包
tcpdump -i enp0s25 "not udp" and "not tcp"
 
抓enp0s25网络接口上的,源或主机IP是192.168.26.141的所有网络包,或者arp包,或者icmp包
tcpdump -i enp0s25 "host 192.168.26.141" or icmp or arp
 
抓enp0s25网络接口上的,源或目的主机IP为192.168.26.200的ARP包。
tcpdump -i enp0s25 arp and "host 192.168.26.200"
(注:ARP包可以看做是具有源和目的IP的概念的。主机A(192.168.26.200)向本子网发出了询问某个IP地址(192.169.26.141)的主机的硬件地址是多少的ARP询问报文,那么这个ARP询问报文的源主机IP可以看作是主机A的IP地址(192.168.26.200),目的主机IP可以看作是192.169.26.141)
 
抓enp0s25网络接口上的,源或目的主机IP为192.168.26.200的ICMP包
tcpdump -i enp0s25 icmp and "host 192.168.26.200"
 
抓enp0s25网络接口上的,源或目的主机IP所处网段为192.168.26.0/24的ARP包。
tcpdump -i enp0s25 "net 192.168.26.0/24" and arp
(注:ARP包只能在子网内传输,因此上面所指的网段肯定要是网络接口enp0s25的IP地址所处的网段,要不什么都抓不到)
 
 
 
 
括号将优先级限定  


当过滤条件超过了2个,往往需要用括号将他们的优先级限定。
 
先看一个例子:
tcpdump -i enp0s25 -vvn udp or tcp and "host 192.168.26.200"
我们往往认为and的优先级比or高,但tcpdump不是这样。tcpdump逻辑运算符没有优先级高低之分,而是按照“先来后到”的原则进行逻辑运算。
上面这条命令等价于:
tcpdump -i enp0s25 -vvn ( udp or tcp ) and "host 192.168.26.200"
 
同理:
tcpdump -i enp0s25 -vvn udp and tcp or "host 192.168.26.200"
等价于
tcpdump -i enp0s25 -vvn ( udp and tcp ) or "host 192.168.26.200"
 
所以为了避免混淆,对两个以上的条件判断,建议加上括号。但不能简单地像上面这么写,因为对于shell命令,括号需要进行转义:
tcpdump -i enp0s25 -vvn \( udp and tcp \) or "host 192.168.26.200"
tcpdump -i enp0s25 -vvn \( udp or tcp \) and "host 192.168.26.200"
 
抓enp0s25网络接口上的,源和目的端口没有22的,且不是TCP的,且如果是ARP包则只保留源或目的IP为192.168.26.200的,且如果是ICMP包则只保留目的IP为192.168.26.200的,所有网络包。
tcpdump -i enp0s25 -vnn "port not 22" and "not tcp" and \( arp and "host 192.168.26.200" or not arp \) and \( icmp and "dst host 192.168.26.200" or not icmp \)
(注:上面外层的3个and依次出现但没有加括号是允许的,连续出现纯粹and或者纯粹or的运算符怎么加括号结果都一样)
(注:对ARP和ICMP过滤的括号当中都依次出现了and和or,也没加括号,则tcpdump按照“先来后到”方式处理,这种简单地情况加括号倒是看得眼花。但是如果依次出现or和and而不加括号的话,也容易误解)
 
抓enp0s25网络接口上的,源或目的端口不是22的,且不符合条件“源或目的端口为80 或者 arp包 或者 udp包”的所有网络包。
tcpdump -i enp0s25 -vnn "port not 22" and not \( "port 80" or arp or udp \)
 
 


 tcpdump常用选项


-i [name]  用来指定抓包所监听的网络接口
 
-v         输出每个包较详细的信息,比如可以输出IP包的ttl和tos
 
-vv        输出每个包更详细的信息
 
-vvvv      输出每个包更更详细的信息
 
-n         表示禁用域名解析,不加它的话,tcpdump会对每次收到的数据包尝试域名解析这会导致有些时候“迟迟看不到输出”。加上这个选项让tcpdump直接输出IP地址。
 
-nn        在-n功能的基础上,禁用端口名称转换。不加它的话,tcpdump会尝试将端口号转换成对应的应用名后显示。加上后也能一定程度提速。
 
-e         指定将监听到的数据包链路层的信息打印出来,包括源MAC和目的MAC,以及网络层的协议。
 
-X         功能非常强大的选项,将数据包的内容转换成十六进制ASCII码进行输出
 
-XX        功能非常强大的选项,将数据包的内容转换成十六进制ASCII码进行输出,并且包括帧头
 
-S         打印每个TCP数据包的绝对序列号而非相对序列号
 
-c [n]     指定抓到包的数量,抓到数量为n的网络包后tcpdump自动退出。
 
 
尝试使用下列命令观察结果:
tcpdump -i any
tcpdump -i any -vvnn
tcpdump -i any -vvvvnn
tcpdump -i any -evvvvnn
tcpdump -i any -evvvvnnX
tcpdump -i any -evvvvnnXX
tcpdump -i any -vnn tcp
tcpdump -i any -vnnS tcp
tcpdump -i any -evvvvnnXXS
tcpdump -i any -vnn -c 5
tcpdump -i any -evvvvnnXXS port 80 or udp
 
 


 tcpdump文件读写


分析问题的时候,将tcpdump抓到的包存到文件里是非常重要的功能。tcpdump当然提供了这样的选项
 
-w  [FILE]    将抓到的包直接写到文件而不输出信息到终端
 
-r  [FILE]    从指定文件中读取数据包
 
 
示例:
 
抓所有网络接口的所有网络包,并写到当前目录的文件test.cap
tcpdump -i any -vnn -w ./test.cap
 
从test.cap中读取网络包,并将“源或目的IP”为192.168.26.200的ARP包过滤出来显示
tcpdump -evvvvnnXXS -r ./test.cap arp and "host 192.168.26.200"
 
从test.cap中读取网络包,并将553端口的UDP数据包过滤出来后写到test2.cap
tcpdump -vnn -r ./test.cap -w ./test2.cap udp and port 553
 
 
 
 tcpdump高级用法


----->  TCP flags相关的过滤
 
抓用于TCP建立连接的SYN包
tcpdump -i any -evvvvnnX tcp[tcpflags] = tcp-syn
 
抓TCP的ACK包
tcpdump -i any -evvvvnnX tcp[tcpflags] = tcp-ack
 
抓TCP的FIN包
tcpdump -i any -evvvvnnX tcp[tcpflags] = tcp-fin
 
抓TCP的PUSH包
tcpdump -i any -evvvvnnX tcp[tcpflags] = tcp-push
 
抓TCP的紧急指针包
tcpdump -i any -evvvvnnX tcp[tcpflags] = tcp-urg
 
抓tcpflags中含有SYN的包(注意这里一定要加引号,下同)
tcpdump -i any -evvvvnnXXS "tcp[tcpflags] & (tcp-syn) != 0"
 
抓tcpflags中含有SYN和ACK的包,即SYN-ACK确认所在的包
tcpdump -i any -evvvvnnXXS "tcp[tcpflags] = tcp-syn|tcp-ack"
 
抓tcpflags中含有SYN的包或者含有FIN的包
tcpdump -i any -evvvvnnXXS "tcp[tcpflags] & tcp-syn != 0" or "tcp[tcpflags] & tcp-fin != 0"
 
-----> 指定位置数据过滤
 
抓从IP包头部开始偏移量为1处的2个字节是0x00 0x05的包
tcpdump -i any -evvvvnnX ip[1:2] = 0x0005
 
抓从TCP包头部开始偏移量为20处的2个字节是0x12 0x35的包
tcpdump -i any -evvvvnnX tcp[20:2] = 0x1235
 
 
从ascasc.cap中读取数据,过滤tcp的syn或者ack,并且从IP包头部开始偏移量1处的2个字节是0x00 0x05的包
tcpdump -vvnnX -r ./ascasc.cap "tcp[tcpflags] = tcp-syn" or "tcp[tcpflags] = tcp-ack" and "ip[1:2]=0x0005"
 
 
------> 截取包指定长度数据

tcpdump默认抓包会将每个包完整数据捕获,即从链路层的帧头到帧尾的所有字节。

你可以让tcpdump只捕获过滤出来了的每个包前面的N个字节,方法是使用-s选项:

 

-s  [Bytes]          捕获每个包从帧头开始的Bytes个字节,如果Bytes指定为0,则捕获整个包

 

如果不加-s选项,则默认捕获整个包,与-s0是一样的。

 

只抓取每个tcp包的前40字节

tcpdump -i any -evvvvnnXXS -s40 tcp

 

这个选项的作用就是,如果捕获的数据比较短,则可以减少丢包率。