序言
在传输层 Tcp 的学习中,我们了解了 三次握手和四次挥手 的概念,但是看了这么多篇文章,我们也只是停留在 纸上谈兵。
欲知事情如何,我们其实可以尝试去看一下具体的网络包的信息。在这篇文章中将向大家介绍,在 Linux 上抓包工具 tcpdump 的基本使用。
一、tcpdump 的使用
1. 安装
大多数 Linux 系统都自带了这个工具,你可以如下指令来查看是否安装就绪:
tcpdump --version
如果不存在的话,我们使用指令安装一个就好:
sudo apt-get install tcpdump
现在我们就可以正式开始学习如何来使用这个简单且强大的工具了。
2. 基本使用
tcpdump 的基本语法是:
tcpdump [选项] [表达式]
- 捕获所有网络数据包:
sudo tcpdump
该条指令将捕获你所有的进出网络数据包,但是我们大多时候只需要获取特定条件的数据包即可,所以我们需要对数据包进行筛选。
- 按接口过滤:
sudo tcpdump -i [接口]
通过 -i
选项来指定要捕获的接口,接口的信息你可以使用 ifconfig 来查看。
- 按协议过滤:
sudo tcpdump [协议]
常见的协议:tcp,udp,icmp
这个选项很重要,等会我们就需要借助它来查看我们三次握手和四次挥手的过程。
- 按 IP 地址过滤:
sudo tcpdump [dst/src] [IP]
在这里的 dst 代表的是捕获发送到特定地址的包;而 src 代表的是捕获来自特定地址的包。
- 按端口过滤:
sudo tcpdump port [端口号]
- 组合多个过滤条件:
使用逻辑运算符 and、or 和 not
来组合过滤条件。例如,我需要捕捉某个源地址的某个端口的 tcp 网络数据包:
sudo tcpdump tcp and src 129.0.10.12 and port 8888
// 示例
基础的使用说到这里就结束了,咋们实战抓一下包。
二、三次握手
现在我们简单写一个用于网络通信的套接字编程,然后开启对本地端口的监听:
sudo tcpdump -i lo tcp and port 8888
大家注意咯,我使用的是本地环回进行测试,所以我们需要指定接口 lo
,不然默认的接口是 eth0
,这样就不能捕获我们的数据包;之后我们指定了进行通信的接口 8888。
现在我们启动客户端发起连接,捕获到如下信息:
现在我们来介绍一个三次握手中,具体包含了什么信息:
-
第一次:客户端发送 SYN 包
-
时间戳: 18:06:37.782287
-
源地址: localhost.48058,即源端口为 48058
-
目标地址: localhost.8888,即目标端口为 8888
-
TCP 标志: Flags [S],表示这是 SYN 包,即请求建立连接。
-
序列号: seq 3613884573,这是发送方的初始序列号。
-
窗口大小: win 65495,接收方的接收窗口大小(在 TCP 握手过程中,表示能够接收的最大字节数)。
-
-
第二次:服务器响应 SYN-ACK 包
-
时间戳: 18:06:37.782298
-
源地址: localhost.8888,即目标端口(8888)现在变成了源端口。
-
目标地址: localhost.48058,即源端口(48058)现在变成了目标端口。
-
TCP 标志: Flags [S.],表示 SYN-ACK 包,服务器响应客户端的连接请求。S 表示 SYN(同步序列号),. 表示 ACK(确认响应)。
-
序列号: seq 3949276879,服务器的序列号。
-
确认号: ack 3613884574,服务器确认客户端的初始序列号 + 1,表示已经收到客户端的请求。
-
窗口大小: win 65483,接收方窗口大小。
-
-
第三次:客户端发送 ACK 包,确认连接
- 时间戳: 18:06:37.782307
- 源地址: localhost.48058,客户端。
- 目标地址: localhost.8888,服务器。
- TCP 标志: Flags [.],表示 ACK 包,即客户端确认服务器响应的连接建立。
- 确认号: ack 1,表示客户端确认了服务器的响应包。
- 窗口大小: win 512,接收窗口大小。
- 长度: length 0,此包也没有携带数据,只有头部。
所以我们直到有三次握手,但是没想到,三次握手背后干了这么事情:
- 客服端,服务端初始化序列号
- 两者通告接受窗口大小
- 协商出一个合适的 MSS 值
现在再让我们看看四次挥手吧!
三、四次挥手
现在服务端断开连接,之后客户端也断开了连接,这中间发生了什么了:
现在我们就不逐个字段的介绍了,但是很奇怪呢?怎么四次挥手变成三次了?我们理一下:
- 服务端发送 FIN 包,表示断开连接请求
- 收到服务端的消息后,客户端发送了 ACK 表示收到,并且发送 FIN 包表示断开连接,以捎带应答的方式发出
- 收到客户端的信息后,服务端发送 ACK,连接正式断开
所以,中间分开发送的 ACK 和 FIN 被合并了!这很合理,之所以分开发送的原因是因为:服务端还存在未处理完的数据并未发送给客户端,需要处理并发送后再断开!但是我们并没有剩余的数据,所以直接就断开了!
四、总结
在这篇文章中,我们介绍了抓包工具 tcpdump 的使用,并且还实践了利用该工具抓取三次握手,四次挥手过程中数据包的信息。