抓包与分析
# 抓包与分析
# 前言
tcpdump 和 Wireshark 是最常用的网络抓包和分析工具,更是分析网络性能必不可少的利器。它们能把我们「看不见」的数据包,呈现在我们眼前,一目了然。
- tcpdump 仅支持命令行格式使用,常用在 Linux 服务器中抓取和分析网络包。
- Wireshark 除了可以抓包外,还提供了可视化分析网络包的图形页面。
所以,这两者实际上是搭配使用的,先用 tcpdump 命令在 Linux 服务器上抓包,接着把抓包的文件拖出到 Windows 电脑后,用 Wireshark 可视化分析。
当然,如果你是在 Windows 上抓包,只需要用 Wireshark 工具就可以。
# 使用 tcpdump 抓包
tcpdump 提供了大量的选项以及各式各样的过滤表达式,来帮助我们抓取指定的数据包。不过只需要掌握一些常用选项和过滤表达式,就可以满足大部分场景的需要了。
# 抓取 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
2
3
4
5
当 tcpdump 抓取到 icmp 数据包后,输出内容如下:
(抓取 ping 的数据包)
数据的格式是:时间戳 协议 源地址.源端口 > 目的地址.目的端口 网络包详细信息
从 tcpdump 抓取的 icmp 数据包,我们很清楚的看到 icmp echo
的交互过程了,首先发送方发起了 ICMP echo request
请求报文,接收方收到后回了一个 ICMP echo reply
响应报文,之后 seq
是递增的。
# 常见用法整理
这里总结一下 tcpdump 最常见的用法。
首先是常用的选项,如下表所示:
接下来是常用的过滤表达式,如下表所示:
虽然 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
2
3
4
5
接着把 ping.pcap 文件拖到电脑,再用 Wireshark 打开它。打开后,就可以看到下面这个界面:
(ping.pcap)
如上,在 Wireshark 的页面里,可以更加直观的分析数据包,不仅展示各个网络包的头部信息,还会用不同的颜色来区分不同的协议,由于这次抓包只有 ICMP 协议,所以只有紫色的条目。
接着,在网络包列表中选择某一个网络包后,在其下面的网络包详情中,可以更清楚的看到,这个网络包在协议栈各层的详细信息。比如,以编号 1 的网络包为例子:
(编号 1 的网络包)
Wireshark 用了分层的方式,展示了各个层的包头信息:
- 可以在数据链路层,看到 MAC 包头信息,如源 MAC 地址和目标 MAC 地址等字段。
- 可以在 IP 层,看到 IP 包头信息,如源 IP 地址和目标 IP 地址、TTL、IP 包长度、协议等 IP 协议各个字段的数值和含义。
- 可以在 ICMP 层,看到 ICMP 包头信息,比如 Type、Code 等 ICMP 协议各个字段的数值和含义。
从 ping 的例子中,我们可以看到网络分层就像有序的分工,每一层都有自己的责任范围和信息,上层协议完成工作后就交给下一层,最终形成一个完整的网络包。
(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
2
3
4
5
最后,回到第一个 shell 窗口,按下 Ctrl+C 停止 tcpdump,并把得到的 http.pcap 取出到电脑。
使用 Wireshark 打开 http.pcap 后,你就可以在 Wireshark 中,看到如下的界面:
(http.pcap)
我们都知道 HTTP 是基于 TCP 协议进行传输的,那么:
- 最开始的 3 个包就是 TCP 三次握手建立连接的包
- 中间是 HTTP 请求和响应的包
- 而最后的 3 个包则是 TCP 断开连接的挥手包
Wireshark 可以用时序图的方式显示数据包交互的过程,从菜单栏中,点击「统计 (Statistics)」->「流量图 (Flow Graph)」,然后在弹出的界面中的「流类型」选择「TCP Flows」,就可以更清晰的看到整个过程中 TCP 流的执行过程:
(TCP Flows 时序图)
你可能会好奇,为什么三次握手连接过程的 Seq 是 0?说好是随机生成的呢,怎么那么巧是 0 的呢?
实际上是因为 Wireshark 工具帮我们做了优化,它默认显示的是序列号 Seq 是相对值,而不是真实值。
如果你想看到实际的序列号的值,可以右键菜单, 然后找到「协议首选项」,接着找到「Relative Seq」后,把它给取消,操作如下:
(取消 Seq 相对值显示的方式)
取消后,Seq 显示的就是真实值了:
(Seq 真实值显示的 TCP Flows 时序图)
可见,客户端和服务端的序列号实际上是不同的,序列号是一个随机值。
再来回顾下 TCP 三次握手和四次挥手,整个流程基本是这样的:
(TCP 三次握手和四次挥手)
(完)