tcpdump简要使用
# tcpdump简要使用
# 是什么
tcpdump
是一个网络数据包分析工具,主要用于捕获和分析通过网络接口传输的数据包。它在网络故障排查、性能分析、安全分析等方面非常有用。
# tcpdump
的起源 (opens new window)
该程序大致基于 SMI 的“etherfind”,尽管 etherfind
代码已全部消失。它最初由 Van Jacobson 编写,作为正在进行的研究项目的一部分,旨在调查和改进 TCP 和 Internet 网关性能。该程序最初取自 Sun 的 etherfind
的部分后来由 LBL 的 Steven McCanne 重写。为了确保 tcpdump
中不会有专有代码的痕迹,Steve 根据手册条目给出的规范编写了这些部分,而没有访问 tcpdump
或 etherfind
的源代码。
# 主要作用
- 数据包捕获:
tcpdump
可以捕获通过指定网络接口的所有网络流量。 - 过滤流量:可以通过表达式指定需要捕获的特定流量,比如指定的 IP 地址、端口、协议(TCP/UDP)等。
- 实时查看或保存捕获结果:可以实时查看捕获的数据包,也可以将捕获的数据包保存到文件中,供以后分析。
- 解析协议:可以解码多种网络协议,包括 TCP、UDP、ICMP、HTTP、DNS 等,帮助分析网络数据。
# 工作原理
该部分摘自极客时间的《网络排查案例课 (opens new window)》
tcpdump
可以工作在各种 Unix 类的操作系统上,包括 Linux、FreeBSD、macOS、Solaris 等,也是目前使用最为广泛的抓包工具之一。但是tcpdump
要过滤报文的话,还要依赖一个底层能力:BPF (opens new window)。
# BPF
BPF 全称是 Berkeley Packet Filter(也叫BSD Packet Filter),它是tcpdump
等抓包工具的底层基础。在 BPF 出现之前,虽然各家操作系统都有自己的抓包工具,但也都有这样或那样的不足。比如,有些系统把所有网络报文一股脑儿塞给用户空间程序,开销非常大;而有些系统虽然有报文过滤功能,但是工作很不稳定。
为了解决这些问题,1992年,也还是在劳伦斯伯克利国家实验室,当初tcpdump
的两个作者史蒂文·麦克凯恩(Steven McCanne)和范·雅各布森(Van Jacobson)发表了关于 BPF 的论文 (opens new window),它以一种新的基于寄存器的虚拟机方式,实现了高效稳定的报文过滤功能。从此以后,抓包技术这棵大树有了一个甚为强大的根基,而构建在 BPF 之上的libpcap
、tcpdump
等不断枝繁叶茂,进一步使得抓包工作变得方便、稳定。
# libpcap
BPF 实现了抓包虚拟机,但它是如何被用户空间程序使用的呢?于是,libpcap
出现了,它提供了 API 给用户空间程序(包括tcpdump
、Wireshark
等),使得后者能方便地调用 BPF 实现抓包过滤等功能。也就是说,libpcap
是 BPF 的一层 API 封装。
tcpdump
调用了libpcap
接口,后者调用 BPF 实现了报文过滤和抓取。我们来看一下示意图:
# WinPcap
Windows 上也可以做到类似 Linux 这样的抓包,其底层就是依赖 WinPcap,它是libpcap
的 Windows 版本。
# eBPF
Linux 从3.18版本开始支持 extended BPF,简称 eBPF。这是一个更加通用的内核接口,不仅能支持网络抓包,还能支持网络以外的内核观测点的信息收集等工作。所以事实上,eBPF 已经是一个通用工具,而不再局限在网络工具这个角色定位上了。
# 抓包文件的类型有哪些
# pcap
这个是libpcap
的格式,也是tcpdump
和Wireshark
等工具默认支持的文件格式。pcap
格式的文件中除了报文数据以外,也包含了抓包文件的元信息,比如版本号、抓包时间、每个报文被抓取的最大长度,等等。
# cap
cap
文件可能含有一些libpcap
标准之外的数据格式,它是由一些tcpdump
以外的抓包程序生成的。比如 Citrix 公司的netscaler
负载均衡器,它的nstrace
命令生成的抓包文件,就是以.cap
为扩展名的。这种文件除了包含pcap
标准定义的信息以外,还包含了 LB 的前端连接和后端连接之间的mapping
信息。Wireshark
是可以读取这些.cap
文件的,只要在正确的版本上。
# pcapng
pcap
格式虽然满足了大部分需求,但是它也有一些不足。比如,现在多网口的情况已经越来越常见了,我们也经常需要从多个网络接口去抓取报文,那么在抓包文件里,如果不把这些报文跟所属的网口信息展示清楚,那我们的分析,岂不是要张冠李戴了吗?
为了弥补pcap
格式的不足,人们需要有一种新的文件格式,pcapng
就出现了。有了它,单个抓包文件就可以包含多个网络接口上,抓取到的报文了。
# 怎么用
# 帮助文档
tcpdump
的官网:https://www.tcpdump.org/index.html,里面可以找到tcpdump
最新的版本和相关手册。
查看tcpdump
帮助文档:
$ man tcpdump
大部分使用方式都可以从中找到,但不是很友好。
我们可以使用这种语法参考:
$ tcpdump [ option ] [ protocol ] [ direction ] [ type ]
option
可选参数:一般使用-
指定,是一些常规参数。protocol
协议过滤器(位置参数,可选):根据协议进行过滤,可选的值有:tcp
,udp
,icmp
,ip
,ip6
,arp
,rarp
,ether
,wlan
,fddi
,tr
,decnet
。当然,值之间可以使用各种逻辑运算法进行组合使用,例如tcp or udp
。direction
数据流向过滤器(位置参数,可选):根据数据流向进行过滤,可选的值有:src
,dst
。当然,值之间也可以使用各种逻辑运算法进行组合使用,例如src or dst
。type
主机及端口过滤器(位置参数,可选):根据主机、网络 IP、端口等进行过滤。需要key value
形式,关键词key
有:host
、net
、port
、portrange
。
# tcpdump 内容解析
tcpdump port 80 -n
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:44:48.868348 IP 192.168.122.11.80 > 192.168.122.20.42662: Flags [F.], seq 1622076305, ack 1353075739, win 509, options [nop,nop,TS val 3549743074 ecr 1743063663], length 0
2
3
4
主要看这段内容:
12:44:48.868348 IP 192.168.122.11.80 > 192.168.122.20.42662: Flags [F.], seq 1622076305, ack 1353075739, win 509, options [nop,nop,TS val 3549743074 ecr 1743063663], length 0
第一列:时分秒毫秒
12:44:48.86834
。第二列:网络协议 IP。
第三列:发送方的 IP 地址+端口号,其中
192.168.122.11
是 IP,而80是端口号(源 IP+源端口号)。第四列:箭头
>
, 表示数据流向。第五列:接收方的 IP 地址+端口号,其中
192.168.122.20
是 IP,而42662是端口号(目标 IP+目标端口号)。第六列:冒号
:
。第七列:数据包内容,包括
Flags
标识符,seq
号,ack
号,win
窗口,数据长度length
。Flags 标识符有如下几种:
[S]
:SYN
(开始连接)[P]
:PSH
(推送数据)[F]
:FIN
(结束连接)[R]
:RST
(重置连接)[.]
:没有Flag
(意思是除上面四种类型外的其他情况,有可能是ACK
也有可能是URG
)
# 类位置参数
# 过滤主机
不使用参数:相当于不过滤,啥都抓取。
$ tcpdump
1通过
host
参数指定主机ip
或主机名进行过滤# 指定主机 IP $ tcpdump host 192.168.122.11 # 指定主机名 $ tcpdump host 11.dev.com
1
2
3
4指定源主机/目标主机
# src host 用于指定源主机 $ tcpdump src host 192.168.122.11 # dst host 用于指定目标主机 $ tcpdump dst host 192.168.122.11 # dst or src host 用于指定源主机或目标主机(两个条件之一成立即可) $ tcpdump dst or src host 192.168.122.11
1
2
3
4
5
6
# 过滤网段
根据网段进行过滤
$ tcpdump net 192.168.122.0/24
1指定源网段/目标网段
$ tcpdump src net 192.168.122.0/24 $ tcpdump dst net 192.168.122.0/24
1
2
# 过滤端口
使用
port
指定特定端口进行过滤# 过滤80端口 $ tcpdump port 80
1
2指定源端口/目标端口号
# 过滤源端口号为 80 的包 $ tcpdump src port 80 # 过滤目标端口号为 80 的包 $ tcpdump dst port 80 # 过滤目标/源端口号为 80 的包 $ tcpdump dst or src port 80
1
2
3
4
5
6指定多个端口号
# 指定 80 端口和 8080 端口 $ tcpdump port 80 or port 8080 # 可以简写成这样 $ tcpdump port 80 or 8080
1
2
3
4端口号范围
$ tcpdump portrange 80-8080 $ tcpdump src portrange 80-8080 $ tcpdump dst portrange 80-8080
1
2
3知名端口
# http 为知名端口,即80 $ tcpdump port http
1
2
# 过滤协议
可以支持的协议有:tcp
,udp
,icmp
,ip
,ip6
,arp
,rarp
,ether
,wlan
,fddi
,tr
,decnet
等等。
只过滤
icmp
的包$ tcpdump icmp
1只看
tcp
的包$ tcpdump tcp
1
# 过滤协议版本
tcpdump tcp
默认包含了 IPv4 和 IPv6 的tcp
,需要对 IPv4 和 IPv6 进行区分,可以使用proto
关联。
过滤 IPv4 的包
# 显式指定 tcp $ tcpdump 'ip && tcp' # 通过编号指定 tcp $ tcpdump ip proto 6
1
2
3
4数字 6 表示的是
tcp
在ip
报文中的编号。其他协议与数字的映射关系如下:tcp
:6icmp
:1udp
:17
过滤 IPv6 的包
# ip6 表示 IPv6 $ tcpdump 'ip6 proto tcp' # 通过编号指定 tcp $ tcpdump ip6 proto 6
1
2
3
4
# 可选参数
# 常用参数
-w
文件名,可以把报文保存到文件;-c
数量,可以抓取固定数量的报文,这在流量较高时,可以避免一不小心抓取过多报文;-s
长度,可以只抓取每个报文的一定长度;-n
,不做地址转换(比如IP
地址转换为主机名,port 80 转换为http
);-v/-vv/-vvv
,可以打印更加详细的报文信息;-e
,可以打印二层信息,特别是MAC
地址;-p
,关闭混杂模式。所谓混杂模式,也就是嗅探(Sniffering),就是把目的地址不是本机地址的网络报文也抓取下来。
# 设置不解析域名提升速度
上面过滤的结果基本都会显示域名,不利于我们分析,我们可以使用以下参数设置,不将ip
转为域名打印。
-n
:不把ip
转化成域名,直接显示ip
,避免执行 DNS lookups 的过程,速度会快很多。-nn
:不把协议和端口号转化成名字,速度也会快很多。-N
:不打印host
的域名部分。比如域名为11.dev.com
,那么只会打印11
。
# 过滤结果输出到文件
通常,我们会将tcpdump
抓到的包保存在.pcap
后缀的文件里,然后使用wireshark
进行分析。
可以使用-w
参数接.pcap
后缀的文件,就可以将结果保存到文件里。
$ tcpdump tcp -w dev-tcp.pcap
可以同时按Ctrl+c
结束抓包。
# 指定抓取固定数量的报文
指定抓取固定数量的报文,防止抓取的流量过多或写入的文件过大。
# 指定只抓取10个包
$ tcpdump tcp -w dev-tcp.pcap -c 10
2
# 从文件中读取包数据
使用 -w
是写入数据到文件,而使用 -r
是从文件中读取数据。读取后,我们照样可以使用上述的过滤器语法进行过滤分析。
$ tcpdump -r dev_tcp.pcap tcp
# 控制详细内容的输出
-v
:产生详细的输出,比如包的TTL
、id
标识、数据包长度,以及IP
包的一些选项。同时它还会打开一些附加的包完整性检测,比如对IP
或ICMP
包头部的校验和。-vv
:产生比-v
更详细的输出,比如NFS回应包中的附加域将会被打印。-vvv
:产生比-vv
更详细的输出。比如telent
时所使用的 SB、SE 选项将会被打印。
# 控制时间的显示
-t
:在每行的输出中不输出时间。-tt
:在每行的输出中会输出时间戳。-ttt
:输出每两行打印的时间间隔(以毫秒为单位)。-tttt
:在每行打印的时间戳之前添加日期的打印(此种选项,输出的时间最直观)。
# 显示数据包的头部
-x
:以16进制的形式打印每个包的头部数据(但不包括数据链路层的头部)。-xx
:以16进制的形式打印每个包的头部数据(包括数据链路层的头部)。-X
:以16进制和 ASCII码形式打印出每个包的数据(但不包括连接层的头部),这在分析一些新协议的数据包很方便。-XX
:以16进制和 ASCII码形式打印出每个包的数据(包括连接层的头部),这在分析一些新协议的数据包很方便。
# 过滤指定网卡的数据包
-i
:指定要过滤的网卡接口,如果要查看所有网卡,可以-i any
。$ tcpdump tcp -i ens33
1
# 过滤特定流向的数据包
-Q
: 选择是入方向还是出方向的数据包,可选项有:in
、out
、 inout
。
# 只抓取出去的包
$ tcpdump tcp -i ens33 -Q out
# 只抓取进来的包
$ tcpdump tcp -i ens33 -Q in
# 抓取进去的包(不指定就是)
$ tcpdump tcp -i ens33 -Q inout
2
3
4
5
6
# 其他常用的一些参数
-A
:以ASCII
码方式显示每一个数据包(不显示链路层头部信息)。在抓取包含网页数据的数据包时, 可方便查看数据。-l
: 基于行的输出(不指定默认就是),便于你保存查看,或者交给其它工具分析。-q
:简洁地打印输出。即打印很少的协议相关信息,从而输出行都比较简短。-s
:tcpdump
默认只会截取前96
字节的内容,要想截取所有的报文内容,可以使用-s number
,number
就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。-S
: 使用绝对序列号,而不是相对序列号。-C
:file-size
指定切割文件的文件大小。tcpdump
在把原始数据包直接保存到文件中之前,检查此文件大小是否超过file-size
,如果超过了,将关闭此文件,另创一个文件继续用于原始数据包的记录.。新创建的文件名与-w
选项指定的文件名一致,,但文件名后多了一个数字,该数字会从1开始随着新创建文件的增多而增加。file-size
的单位是百万字节(这里指1,000,000个字节)-G
:rotate_seconds
指定文件轮转的时间(单位为秒)。例如rotate_seconds
的值为3,表示每3秒会切割成另一个文件,一般与-C
、-w
一起使用。-F
:使用file
文件作为过滤条件表达式的输入,此时命令行上的输入将被忽略。-D
:显示所有可用网络接口的列表。-e
:每行的打印输出中将包括数据包的数据链路层头部信息。-E
:揭秘IPSEC数据。-L
:列出指定网络接口所支持的数据链路层的类型后退出。-Z
:后接用户名,在抓包时会受到权限的限制。如果以 root 用户启动tcpdump
,tcpdump
将会有超级用户权限。-d
:打印出易读的包匹配码。-dd
:以C语言的形式打印出包匹配码。-ddd
:以十进制数的形式打印出包匹配码。
# 过滤规则组合
# 逻辑运算符
支持的逻辑运算符号:
and
(与):所有的条件都需要满足,也可以表示为&&
。or
(或):只要有一个条件满足就可以,也可以表示为||
。not
(非):取反,也可以使用!
。
例如,想需要抓一个来自192.168.122.20
主机,目标端口号为 80 的包:
$ tcpdump src host 192.168.122.20 and dst port 80
当你在使用多个过滤器进行组合时,有可能需要用到括号,而括号在shell
中是特殊符号,因为你需要使用引号(单引号和双引号都可以)将其包含。例子如下:
$ tcpdump 'src 192.168.122.20 and (dst port 80 or 443)'
# 条件运算符
而在单个过滤器里,常常会判断一条件是否成立,这时候,就要使用下面的条件运算符:
=
:判断二者相等==
:判断二者相等!=
:判断二者不相等
我们想要过滤出 TCP RST 报文,那么可以用下面这种写法:
$ tcpdump 'tcp[tcpflags]&(tcp-rst) != 0'
# 特殊过滤规则
# 根据 tcpflags 进行过滤
我们想要过滤出 TCP RST 报文,那么可以用下面这种写法,相对来说比用数字做偏移量的写法,要更加容易理解和记忆:
$ tcpdump -w file.pcap 'tcp[tcpflags]&(tcp-rst) != 0'
如果是用偏移量的写法,会是下面这样:
$ tcpdump -w file.pcap 'tcp[13]&4 != 0'
# 基于包大小进行过滤
若你想查看指定大小的数据包,也是可以的
$ tcpdump less 32
$ tcpdump greater 64
$ tcpdump <= 128
2
3
# 过滤广播/多播数据包
$ tcpdump ether broadcast
$ tcpdump ether multicast
$ tcpdump ip broadcast
$ tcpdump ip multicast
$ tcpdump ip6 multicast
2
3
4
5
6
7