抓包与分析


# 抓包与分析

# 前言

tcpdumpWireshark 是最常用的网络抓包和分析工具,更是分析网络性能必不可少的利器。它们能把我们「看不见」的数据包,呈现在我们眼前,一目了然。

  • tcpdump 仅支持命令行格式使用,常用在 Linux 服务器中抓取和分析网络包。
  • Wireshark 除了可以抓包外,还提供了可视化分析网络包的图形页面。

所以,这两者实际上是搭配使用的,先用 tcpdump 命令在 Linux 服务器上抓包,接着把抓包的文件拖出到 Windows 电脑后,用 Wireshark 可视化分析。

当然,如果你是在 Windows 上抓包,只需要用 Wireshark 工具就可以。

# 使用 tcpdump 抓包

tcpdump 提供了大量的选项以及各式各样的过滤表达式,来帮助我们抓取指定的数据包。不过只需要掌握一些常用选项和过滤表达式,就可以满足大部分场景的需要了。

# 抓取 ping 包

假设我们要抓取下面的 ping 的数据包:

ping 数据包

(ping 数据包)

要抓取上面的 ping 命令数据包,首先我们要知道 ping 的数据包是 icmp 协议,接着在使用 tcpdump 抓包的时候,就可以指定只抓 icmp 协议的数据包:

# -i eth0 表示抓取 eth0 网口的数据包
# icmp    表示抓取 icmp 协议的数据包
# host    表示主机过滤,抓取对应 IP 的数据包
# -nn     表示不解析 IP 地址和端口号的名称
tcpdump -i eth0 icmp and host 112.80.248.76 -nn
1
2
3
4
5

当 tcpdump 抓取到 icmp 数据包后,输出内容如下:

抓取 ping 的数据包

(抓取 ping 的数据包)

数据的格式是:时间戳 协议 源地址.源端口 > 目的地址.目的端口 网络包详细信息

从 tcpdump 抓取的 icmp 数据包,我们很清楚的看到 icmp echo 的交互过程了,首先发送方发起了 ICMP echo request 请求报文,接收方收到后回了一个 ICMP echo reply 响应报文,之后 seq 是递增的。

# 常见用法整理

这里总结一下 tcpdump 最常见的用法。

首先是常用的选项,如下表所示:

tcpdump 使用 —— 选项选项示例说明-itcpdump -i eth0指定网络接口,默认是 0 号接口(如 eth0),any 表示所有接口-nntcpdump -nn不解析 IP 地址和端口号的名称-ctcpdump -c 5限制要抓取的网络包的个数-wtcpdump -w file.pcap保存到文件中,文件名通常以.pcap 为后缀

接下来是常用的过滤表达式,如下表所示:

tcpdump 使用 —— 过滤表达式选项示例说明host、src host、dst hosttcpdump -nn host 192.168.1.100主机过滤port、src port、dst porttcpdump -nn port 80端口过滤ip、ip6、arp、tcp、udp、icmptcpdump -nn tcp协议过滤and、or、nottcpdump -nn host192.168.1.100 and port 80逻辑表达式tcp[tcpflags]tcpdump -nn "tcp[tcpflags] &tcp-syn != 0"特定状态的 TCP 包

虽然 tcpdump 功能强大,但是输出的格式并不直观。所以在工作中 tcpdump 只是用来抓取数据包,不用来分析数据包,而是把 tcpdump 抓取的数据包保存成 pcap 后缀的文件,接着用 Wireshark 工具进行数据包分析。

# 使用 Wireshark 分析包

Wireshark 除了可以抓包外,还提供了可视化分析网络包的图形页面,同时,还内置了一系列的汇总分析工具。

# 分析 ping 包

比如,拿上面的 ping 例子来说,我们可以使用下面的命令,把抓取的数据包保存到 ping.pcap 文件。

# 先开一个 shell 窗口
tcpdump -i eth0 icmp and host 112.80.248.76 -w ping.pcap

# 再开一个 shell 窗口
ping -I eth0 -c 3 112.80.248.76
1
2
3
4
5

接着把 ping.pcap 文件拖到电脑,再用 Wireshark 打开它。打开后,就可以看到下面这个界面:

ping.pcap

(ping.pcap)

如上,在 Wireshark 的页面里,可以更加直观的分析数据包,不仅展示各个网络包的头部信息,还会用不同的颜色来区分不同的协议,由于这次抓包只有 ICMP 协议,所以只有紫色的条目。

接着,在网络包列表中选择某一个网络包后,在其下面的网络包详情中,可以更清楚的看到,这个网络包在协议栈各层的详细信息。比如,以编号 1 的网络包为例子:

编号 1 的网络包

(编号 1 的网络包)

Wireshark 用了分层的方式,展示了各个层的包头信息:

  • 可以在数据链路层,看到 MAC 包头信息,如源 MAC 地址和目标 MAC 地址等字段。
  • 可以在 IP 层,看到 IP 包头信息,如源 IP 地址和目标 IP 地址、TTL、IP 包长度、协议等 IP 协议各个字段的数值和含义。
  • 可以在 ICMP 层,看到 ICMP 包头信息,比如 Type、Code 等 ICMP 协议各个字段的数值和含义。

从 ping 的例子中,我们可以看到网络分层就像有序的分工,每一层都有自己的责任范围和信息,上层协议完成工作后就交给下一层,最终形成一个完整的网络包。

ICMP 头 + DataICMP 头 + DataICMP 头 + DataIP 头IP 头以太帧头ICMP 协议IP 层数据链路层

(ping 网络包组装过程)

接下来通过 tcpdump 和 Wireshark 这两大网络分析利器,抓取和分析 HTTP 协议网络包,并理解 TCP 三次握手和四次挥手的工作原理。

# 分析 TCP 三次握手和四次挥手

以访问 112.80.248.76 为例:

# 首先打开一个 shell 窗口,用 tcpdump 命令抓取数据包
tcpdump -i any tcp and host 112.80.248.76 and port 80 -w http.pcap

# 接着再打开一个 shell 窗口,执行下面的 curl 命令
curl http://112.80.248.76
1
2
3
4
5

最后,回到第一个 shell 窗口,按下 Ctrl+C 停止 tcpdump,并把得到的 http.pcap 取出到电脑。

使用 Wireshark 打开 http.pcap 后,你就可以在 Wireshark 中,看到如下的界面:

http.pcap

(http.pcap)

我们都知道 HTTP 是基于 TCP 协议进行传输的,那么:

  • 最开始的 3 个包就是 TCP 三次握手建立连接的包
  • 中间是 HTTP 请求和响应的包
  • 而最后的 3 个包则是 TCP 断开连接的挥手包

Wireshark 可以用时序图的方式显示数据包交互的过程,从菜单栏中,点击「统计 (Statistics)」->「流量图 (Flow Graph)」,然后在弹出的界面中的「流类型」选择「TCP Flows」,就可以更清晰的看到整个过程中 TCP 流的执行过程:

TCP Flows 时序图

(TCP Flows 时序图)

你可能会好奇,为什么三次握手连接过程的 Seq 是 0?说好是随机生成的呢,怎么那么巧是 0 的呢?

实际上是因为 Wireshark 工具帮我们做了优化,它默认显示的是序列号 Seq 是相对值,而不是真实值。

如果你想看到实际的序列号的值,可以右键菜单, 然后找到「协议首选项」,接着找到「Relative Seq」后,把它给取消,操作如下:

取消 Seq 相对值显示的方式

(取消 Seq 相对值显示的方式)

取消后,Seq 显示的就是真实值了:

Seq 真实值显示的 TCP Flows 时序图

(Seq 真实值显示的 TCP Flows 时序图)

可见,客户端和服务端的序列号实际上是不同的,序列号是一个随机值。

再来回顾下 TCP 三次握手和四次挥手,整个流程基本是这样的:

TCP 三次握手和四次挥手

(TCP 三次握手和四次挥手)

(完)