tcpdump工作原理
tcpdump 是 Linux 系统中非常有用的网络工具,运行在用户态,本质上是通过调用 libpcap 库的各种
api 来实现数据包的抓取功能,利用内核中的 AF_PACKET 套接字,抓取网络接口中传输的网络包。查 看 tcpdump 的 手册 ,以及 pcap-filter 的手册,tcpdump 提供了大量的选项以及各式各样的过滤表达 式。tcpdump 的输出格式
时间戳 协议 源地址.源端口 > 目的地址.目的端口 网络包详细信息

通过上图,我们可以很直观的看到,数据包到达网卡后,经过数据包过滤器(BPF)筛选后,拷贝至用 户态的 tcpdump 程序,以供 tcpdump 工具进行后续的处理工作,输出或保存到 pcap 文件。 数据包过滤器(BPF)主要作用,就是根据用户输入的过滤规则,只将用户关心的数据包拷贝至 tcpdump,这样能够减少不必要的数据包拷贝,降低抓包带来的性能损耗。
思考:
如果某些数据包被 iptables 封禁,是否可以通过 tcpdump 抓到包?
因为 Linux 系统中 netfilter 是工作在协议栈阶段的,tcpdump 的过滤器(BPF)工作位置在协议栈 之前,所以是可以抓到包的!
实战:基础用法
我们先通过几个简单的示例来介绍 tcpdump 基本用法。
- 不加任何参数,默认情况下将抓取第一个非 lo 网卡上所有的数据包
$ tcpdump
- 抓取 wlp3s0 网卡上的所有数据包
$ tcpdump -i wlp3s0
- 抓包时指定 -n 选项,不解析主机和端口名。这个参数很关键,会影响抓包的性能,一般抓包时都需 要指定该选项。
$ tcpdump -n -i wlp3s0
- 抓取指定主机 192.168.1.100 的所有数据包
$ tcpdump -ni wlp3s0 host 192.168.1.100
- 抓取指定主机 10.1.1.2 发送的数据包
$ tcpdump -ni wlp3s0 src host 10.1.1.2
- 抓取发送给 10.1.1.2 的所有数据包
$ tcpdump -ni wlp3s0 dst host 10.1.1.2
- 抓取 wlp3s0 网卡上发往指定主机的数据包,抓到 10 个包就停止,这个参数也比较常用
$ tcpdump -ni wlp3s0 -c 10 dst host 192.168.1.200
- 抓取 wlp3s0 网卡上所有 SSH 请求数据包,SSH 默认端口是 22
$ tcpdump -ni wlp3s0 dst port 22
- 抓取 wlp3s0 网卡上 5 个 ping 数据包
$ tcpdump -ni wlp3s0 -c 5 icmp
- 抓取 wlp3s0 网卡上所有的 arp 数据包
$ tcpdump -ni wlp3s0 arp
- 使用十六进制输出,当想检查数据包内容是否有问题时,十六进制输出会很有帮助。
$ tcpdump -ni wlp3s0 -c 1 arp -X tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on wlp3s0, link-type EN10MB (Ethernet), capture size 262144 bytes 14:38:52.549659 ARP, Request who-has 192.168.0.106 tell 192.168.0.1, length 28 0x0000: 0001 0800 0604 0001 0840 f3d3 ad70 c0a8 [email protected].. 0x0010: 0001 0000 0000 0000 c0a8 006a ...........j
- 只抓取 wlp3s0 网卡上 IPv6 的流量
$ tcpdump -ni wlp3s0 ip6
- 抓取指定端口范围的流量
$ tcpdump -ni wlp3s0 portrange 80-9000
- 抓取指定网段的流量
$ tcpdump -ni wlp3s0 net 192.168.1.0/24
实战:高级进阶
tcpdump 强大的功能和灵活的策略,主要体现在过滤器(BPF)强大的表达式组合能力。
- 抓取指定客户端访问 ssh 的数据包
$ tcpdump -ni wlp3s0 src 192.168.1.100 and dst port 22
- 抓取从某个网段来,到某个网段去的流量
$ tcpdump -ni wlp3s0 src net 192.168.1.0/16 and dst net 10.0.0.0/8 or 172.16.0.0/16
- 抓取来自某个主机,发往非 ssh 端口的流量
$ tcpdump -ni wlp3s0 src 10.0.2.4 and not dst port 22
- 当构建复杂查询的时候,可能需要使用引号,单引号告诉 tcpdump 忽略特定的特殊字符,这里的
$ tcpdump -ni wlp3s0 'src 10.0.2.4 and (dst port 3389 or 22)'
() 就是特殊符号,如果不用引号的话,就需要使用转义字符
- 基于包大小进行筛选,如果正在查看特定的包大小,可以使用这个参数 小于等于 64 字节:
$ tcpdump -ni less 64
大于等于 64 字节:
$ tcpdump -ni wlp3s0 greater 64
等于 64 字节:
$ tcpdump -ni wlp3s0 length == 64
- 过滤 TCP 特殊标记的数据包 抓取某主机发送的 RST 数据包:
$ tcpdump -ni wlp3s0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-rst) != 0'
抓取某主机发送的 SYN 数据包:
$ tcpdump -ni wlp3s0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-syn) != 0'
抓取某主机发送的 FIN 数据包:
$ tcpdump -ni wlp3s0 src host 192.168.1.100 and 'tcp[tcpflags] & (tcp-fin) != 0'
抓取 TCP 连接中的 SYN 或 FIN 包
$ tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0'
- 抓取所有非 ping 类型的 ICMP 包
$ tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'
- 抓取端口是 80,网络层协议为 IPv4, 并且含有数据,而不是 SYN、FIN 以及 ACK 等不含数据的数据 包
$ tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)>2)) != 0)'
解释一下这个复杂的表达式,具体含义就是,整个 IP 数据包长度减去 IP 头长度,再减去 TCP 头的长 度,结果不为 0,就表示数据包有 data ,如果还不是很理解,需要自行补一下 tcp/ip 协议
- 抓取 HTTP 报文, 0x4754 是 GET 前两字符的值, 0x4854 是 HTTP 前两个字符的值
$ tcpdump -ni wlp3s0 'tcp[20:2]=0x4745 or tcp[20:2]=0x4854'
常用选项
常用的选项参数。
(一)基础选项
-i :指定接口
-D :列出可用于抓包的接口
-s :指定数据包抓取的长度
-c :指定要抓取的数据包的数量
-w :将抓包数据保存在文件中
-r :从文件中读取数据
-C :指定文件大小,与 -w 配合使用
-F :从文件中读取抓包的表达式
-n :不解析主机和端口号,这个参数很重要,一般都需要加上
-P :指定要抓取的包是流入还是流出的包,可以指定的值 in 、 out 、 inout
(二)输出选项
-e :输出信息中包含数据链路层头部信息
-t :显示时间戳, tttt 显示更详细的时间
过滤表达式

tcpdump 强大的功能和灵活的策略,主要体现在过滤器(BPF)强大的表达式组合能力。
(一)操作对象
表达式中可以操作的对象有如下几种:
type ,表示对象的类型,比如: host 、 net 、 port 、 portrange ,如果不指定 type 的话,默 认是 host
dir :表示传输的方向,可取的方式为: src 、 dst 。
proto :表示协议,可选的协议有: ether 、 ip 、 ip6 、 arp 、 icmp 、 tcp 、 udp 。
(二)条件组合
表达对象之间还可以通过关键字 and 、 or 、 not 进行连接,组成功能更强大的表达式。
or :表示或操作
and :表示与操作
not :表示非操作
tips
-
在高流量场景下,抓包可能会影响系统性能,如果是在生产环境,请谨慎使用!
-
在高流量场景下, tcpdump 并不适合做流量统计,如果需要,可以使用交换机镜像的方式去分析 统计。
-
在 Linux 上使用 tcpdump 抓包,结合 wireshark 工具进行数据分析,能事半功倍。
-
抓包时,尽可能不要使用 any 接口来抓包。
-
抓包时,尽可能指定详细的数据包过滤表达式,减少无用数据包的拷贝。
-
抓包时,尽量指定 -n 选项,减少解析主机和端口带来的性能开销。
Wireshark
查找可用的网络设备
在 wireshark 能够分析数据包之前,它需要捕获这些数据包。网络数据包通过服务器、工作站或台式机 上的网络接口卡(NIC)或笔记本电脑上的 WiFi 卡进行处理。首先识别用于连接互联网的网卡或 WiFi 卡。
sudo wireshark -D
-
wlp3s0
-
vmnet1
-
vmnet8
-
lo (Loopback)
-
any
-
enp2s0f0
-
enp5s0
-
bluetooth-monitor
-
nflog
-
nfqueue
-
ciscodump (Cisco remote capture)
-
dpauxmon (DisplayPort AUX channel monitor capture)
-
randpkt (Random packet generator)
-
sdjournal (systemd Journal Export)
-
sshdump (SSH remote capture)
-
udpdump (UDP Listener remote capture)
捕获选项
图形化或者命令皆可
- 命令
sudo wireshark -i wlp3s0
可以使用 -c (count)选项限制捕获和显示在屏幕上的数据包数量。下面的示例显示捕获的10个数据 包
sudo wireshark -i wlp3s0 -c 10
查询出来的线路包括箭头两侧的两个 IP 地址--这两个地址是交换数据包的主机。箭头的方向指示数 据包的前进方向。因此,192.168.0.6→14.215.158.102意味着数据包来源于主机192.168.0.6, 我的笔记本电脑前往目的地14.215.158.102。在目标 IP 地址之后,还有DNS、NTP、tcp等协议,
DNS 协议将主机名转换为 IP 地址,将 IP 地址转换为主机名。有专用的 DNS 服务器,可以使用主 机名或 IP 地址查询 可以通过/etc/resolv.conf查找域名服务器相关信息,然后通过nslookup或者dig解析 先用另一个终端执行
sudo wireshark -i wlp3s0 host 1.1.1.1
然后
dig opensource.com ; > DiG 9.16.1-Ubuntu > opensource.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER33748
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 4
;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1280
; COOKIE: 3fec9b884e3a642d944ac20261b792c57e39c04d210c6ba3 (good) ;; QUESTION SECTION:
;opensource.com. IN A ;; ANSWER SECTION: opensource.com. 600 IN A 54.204.39.132 ;; AUTHORITY SECTION: opensource.com. 150455 IN NS ns1.redhat.com. opensource.com. 150455 IN NS ns3.redhat.com. opensource.com. 150455 IN NS ns2.redhat.com. ;; ADDITIONAL SECTION: ns2.redhat.com. 2680 IN A 209.132.183.2 ns3.redhat.com. 2680 IN A 66.187.233.212 ns1.redhat.com. 2680 IN A 209.132.186.218
只查找某种类型协议
sudo wireshark -i wlp3s0 udp
通过-x将二进转化成十六进制(网络数据包是以二进制格式发送)
sudo wireshark -i wlp3s0 -x -c 2 host x.x.x.x
保存输出
sudo wireshark -w /tmp/nlog.pcap -i wlp3s0 host x.x.x.x file命令查看文件类型
sudo file /tmp/nlog.pcap
读取(pcapng文件不能用vim等查看)
sudo wireshark -r /tmp/nlog.pcap
- 图形化

点击选择后 有波动线的对应网卡是存在流量交互的,选择一个网卡点击开始,即开始抓包了,更加方便的是双击选 择一个网卡进行抓包,同时还可以选择使用捕获过滤器,抓自己想要的一些包。
混杂模式与非混杂模式的区别

非混杂模式:主机仅嗅探那些跟它直接有关的通信,如发向它的,从它发出的,或经它路由的等都会被 嗅探器捕捉。简单理解就是只接受我们该接受的数据包。
混杂模式:嗅探网卡传输线路上所有的通信,并且在非交换式网络,嗅探的是整个网络中的通信,会因 为的嗅网络原因任何对有用或者没用的包都会抓取,混杂模式同时是可以被探测到,如果在一个高负荷 网络中,主机系统资源消耗会非常严重。
过滤器设置
捕获过滤器

捕获过滤器的菜单栏路径为捕获 --> 捕获过滤器。用于在抓取数据包前设置。或者可以在主界面选择网卡 的时候就选择应用过滤器规则。
显示过滤器
显示过滤器是用于在抓取数据包后设置过滤条件进行过滤数据包。通常是在抓取数据包时设置条件相对 宽泛,抓取的数据包内容较多时使用显示过滤器设置条件顾虑以方便分析。

我们这里应用的是只显示TCP传输控制协议的数据包,我们在最底下可以看见显示了195个相关的流量 包。
数据详细区(数据包的结构)


数据包详细信息面板(数据包的结构)主要用来查看协议中的每一个字段。各行信息分别为: (1)Frame: 物理层的数据帧概况 (2)Ethernet II: 数据链路层以太网帧头部信息,端点会话的MAC地址(3)Internet Protocol Version 4: 互联网层IP包头部信息,端点会话IP地址 (4)Transmission Control Protocol: 传输层的数据段头部信息,此处是TCP,端点会话的端口 (5)Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议


数据流追踪及分析
通常一个完整的数据流一般都是由很多个包组成的,如果查看某条数据包数据流的话。可以选中数据, 然后右键选择追踪流。里面就会有TCP流、UDP流、SSL流、HTTP流等。数据包属于哪种流就选择对应 的流,例如上图属于TCP我们就选择追逐TCP流。

包 括 我 们 可 以 选 择 流 之 间 的IP 对 话 , 找 指 定 的 会 话 。
C o n v e r s i o n s 对 话

Conversions窗口可以看到两个主机之间发送/接收数据包的数量、字节大小以及数据的流向情况,可以 通过排序来判断占用最大带宽的主机,也可以解析名称,选择作为会话过滤器。
抓包理解三次握手四次挥手
tcpdump 仅支持命令行格式使用,常用在服务器中抓取和分析网络包。Wireshark 除了可以抓包外,还 提供了强大的图形界面和汇总分析工具,因而,可以先用 tcpdump 抓包,后用 Wireshark 分析,可以执 行下面的命令,把抓取的网络包保存到 ping.pcap 文件中:
tcpdump -nn udp port 53 or host 35.190.27.188 -w ping.pcap
接着,把它拷贝到安装有 Wireshark 的机器中进行分析。
tcpdump -nn host 93.184.216.34 -w web.pcap 或者直接使用域名,即 tcpdump -nn host example.com -w web.pcap
执行下面的 curl 命令,访问 http://example.com:
curl http://example.com
最后,再回到终端一,按下 Ctrl+C 停止 tcpdump,并把得到的 web.pcap 拷贝出来。 使用 Wireshark 打开 web.pcap 后,就可以在 Wireshark 中,看到如下的界面:

由于 HTTP 基于 TCP ,所以最先看到的三个包,分别是 TCP 三次握手的包。接下来,中间的才是 HTTP
请求和响应包,而最后的三个包,则是 TCP 连接断开时的三次挥手包。 从菜单栏中,点击 Statistics -> Flow Graph,然后,在弹出的界面中的 Flow type 选择 TCP Flows,可以 更清晰的看到,整个过程中 TCP 流的执行过程:

跟各种教程上讲到的,TCP 三次握手和四次挥手很类似,作为对比, 通常看到的 TCP 三次握手和四次挥 手的流程,基本是这样的:
