【网络】为什么tcpdump抓包只有3次挥手?
1 环境准备
1.1 运行容器
# 为防止容器立即退出,sleep 1d覆盖dockerfile中默认COMMAND
$ docker run -d --name test-1 alpine:3.16.1 sleep 1d
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3d465f00340e alpine:3.16.1 "sleep 1d" 2 seconds ago Up 2 seconds test-1
# 进入容器,查看容器网络信息 eth0
$ docker exec -it test-1 sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:10 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1116 (1.0 KiB) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
1.2 安装tcpdump
# 在容器内安装tcpdump
/ # apk update
/ # apk add tcpdump
1.3 同步容器与系统时间
容器默认时区问题导致显示时间与系统不一样,同步一下系统时间看着舒服一些
# 如果容器没有该目录,创建一下
~ # mkdir -p /usr/share/zoneinfo/Asia
# 从系统拷贝至容器
sudo docker cp /usr/share/zoneinfo/Asia/Shanghai test-1:/usr/share/zoneinfo/Asia
# 进入容器覆盖localtime
~ # cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
~ # date
Wed Jul 27 16:39:47 CST 2022
2. 抓包
# 一个窗口准备抓包
~ # tcpdump -n -S -i eth0 host www.baidu.com
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:07:00.881609 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [S], seq 467889658, win 64240, options [mss 1460,sackOK,TS val 2060837270 ecr 0,nop,wscale 7], length 0
09:07:00.922335 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [S.], seq 1166385092, ack 467889659, win 65535, options [mss 1460,wscale 2,eol], length 0
09:07:00.922348 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166385093, win 502, length 0
09:07:00.932462 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [P.], seq 467889659:467889974, ack 1166385093, win 502, length 315
09:07:00.932726 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467889974, win 65535, length 0
09:07:00.972097 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166385093:1166386553, ack 467889974, win 65535, length 1460
09:07:00.972120 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166386553, win 501, length 0
09:07:00.972127 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166386553:1166388013, ack 467889974, win 65535, length 1460
09:07:00.972133 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166388013, win 495, length 0
09:07:00.972158 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166388013:1166389173, ack 467889974, win 65535, length 1160
09:07:00.972160 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166389173, win 489, length 0
09:07:00.973641 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166389173:1166390319, ack 467889974, win 65535, length 1146
09:07:00.973643 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166390319, win 501, length 0
09:07:00.974256 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [P.], seq 467889974:467890100, ack 1166390319, win 501, length 126
09:07:00.974390 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467890100, win 65535, length 0
09:07:01.012854 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166390319:1166390545, ack 467890100, win 65535, length 226
09:07:01.012856 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166390545, win 501, length 0
09:07:01.013034 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [P.], seq 467890100:467890205, ack 1166390545, win 501, length 105
09:07:01.013321 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467890205, win 65535, length 0
09:07:01.050735 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166390545:1166392005, ack 467890205, win 65535, length 1460
09:07:01.050737 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166392005, win 501, length 0
09:07:01.050794 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166392005:1166393212, ack 467890205, win 65535, length 1207
09:07:01.050857 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166393212, win 501, length 0
09:07:01.051323 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [F.], seq 467890205, ack 1166393212, win 501, length 0
09:07:01.051785 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467890206, win 65535, length 0
09:07:01.051795 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [F.], seq 1166393212, ack 467890206, win 65535, length 0
09:07:01.051806 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166393213, win 501, length 0
# 分方便后同分析,将抓到的包写入文件,生成的 pcap 文件可以用 tcpdump 或者 wireshark 之类的网络流量分析工具打开
~ # tcpdump -n -S -i eth0 host www.baidu.com -w baidu.pcap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
26 packets captured
30 packets received by filter
0 packets dropped by kernel
# 另一个窗口开始发送请求
~ # wget https://www.baidu.com
Connecting to www.baidu.com (180.101.49.12:443)
saving to 'index.html'
index.html 100% |**********************************************************************************************************************************| 2443 0:00:00 ETA
'index.html' saved
参数说明:
- -n:打印 IP 而不是 hostname,打印端口号而不是协议(例如打印 80 而不是 http)
- -S:打印绝对时间戳
- -i eth0:指定从 eth0 网卡抓包
- host www.baidu.com:抓和 www.baidu.com 通信的包(双向)
- -w 命令可以将抓到的包写到文件,注意这和用重定向方式将输出写到文件是不同的。 后者写的只是标准输出打印的 LOG,而 -w 写的是原始包。
3. tcpdump分析
3.1 每列说明
如果不指定输出到文件的话,tcpdump默认直接将信息打印到标准输出,如下:
每列说明:从左至右依次
- packet 时间戳,例如 08:00:59.640622 表示抓到这个包的时间是08时 00 分 59 秒 640 毫秒
- packet 类型,这里是 IP 包
- 源 (SRC) IP 和端口 到 目的 (DST) IP 和端口
- packet TCP flags,其中
- S 表示 syn 包
- . 表示 ack 包
- F 表示 fin 包
- P 表示 push 包(发送正常数据)
- 序列号(seq)
- 应答号(ack)
- 发送窗口(win)
- 包的 payload 长度
- 包的部分内容(ASCII)
3.2 三次握手
wget 是基于 HTTP 协议,因此它在下载文件之前,必定要和服务端建立一个连接。
而 TCP 建立连接的过程就是著名的三次握手 [4]:
- client -> server: SYN
- server -> client: SYN+ACK
- client -> server: ACK
可以看到,刚好对应的前三个包
09:07:00.881609 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [S], seq 467889658, win 64240, options [mss 1460,sackOK,TS val 2060837270 ecr 0,nop,wscale 7], length 0
09:07:00.922335 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [S.], seq 1166385092, ack 467889659, win 65535, options [mss 1460,wscale 2,eol], length 0
09:07:00.922348 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166385093, win 502, length 0
第一次握手:SYN
09:07:00.881609 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [S], seq 467889658, win 64240, options [mss 1460,sackOK,TS val 2060837270 ecr 0,nop,wscale 7], length 0
从第一次握手信息我们可以得到:
- 08:00:59.640622 时刻,客户端172.17.0.2.56832向服务端180.101.49.12.443 发起了一个SYN请求,请求建立连接
- 客户端请求的服务端端口为443(https 默认端口号),客户端使用临时端口号56832
- seq=1031088719,这是客户端的初始序列号(客户端和服务端分别维护自己的序列号,两者没有关系;另外,初始序列号是系统选择的,一般不是 0)
- length 为 0,因为 SYN 包不带 TCP payload,所有信息都在 TCP header
第二次握手:SYN+ACK
09:07:00.922335 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [S.], seq 1166385092, ack 467889659, win 65535, options [mss 1460,wscale 2,eol], length 0
从第二次握手信息我们可以得到:
- 08:00:59.841518时刻,服务端180.101.49.12.443向客户端172.17.0.2.56832发起一个SYN+ACK连接请求及响应
- seq=1276690384,服务端同样向客户发起了一个连接请求,服务端初始序列号为1276690384
- ack=1031088720=第一次握手seq+1,说明是对第一次握手的应答
- length 也是 0,说明没有 payload
- 08:00:59.841518-08:00:59.640622,说明两次握手大约用了200ms
第三次握手:ACK
09:07:00.922348 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166385093, win 502, length 0
- 08:00:59.841540 时刻,客户端172.17.0.2.56832 响应服务端180.101.49.12.443连接请求
- ack=1276690385=第二次握手seq+1,说明是对第二次握手的响应
- length 也是 0,说明没有 payload
3.3 数据传输
三次握手完成后,client 和 server 开始 HTTP 通信,客户端通过 HTTP GET 方法下载 index.html。
# client向server 发起请求,packet长度为315,这里ack=第三次握手的ack,seq=1031089035
08:00:59.849398 IP 172.17.0.2.56832 > 180.101.49.12.443: Flags [P.], seq 1031088720:1031089035, ack 1276690385, win 502, length 315
# sever向client ack 1031089035
08:00:59.849618 IP 180.101.49.12.443 > 172.17.0.2.56832: Flags [.], ack 1031089035, win 65535, length 0
# server向client发送了1460字节数据,seq=1276691845, ack=1031089035
08:00:59.894159 IP 180.101.49.12.443 > 172.17.0.2.56832: Flags [P.], seq 1276690385:1276691845, ack 1031089035, win 65535, length 1460
# client 响应sever,确认收到数据,ack=1276691845
08:00:59.894162 IP 172.17.0.2.56832 > 180.101.49.12.443: Flags [.], ack 1276691845, win 501, length 0
# 下边重复过程,直到数据传输完成
09:07:00.932462 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [P.], seq 467889659:467889974, ack 1166385093, win 502, length 315
09:07:00.932726 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467889974, win 65535, length 0
09:07:00.972097 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166385093:1166386553, ack 467889974, win 65535, length 1460
09:07:00.972120 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166386553, win 501, length 0
09:07:00.972127 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166386553:1166388013, ack 467889974, win 65535, length 1460
09:07:00.972133 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166388013, win 495, length 0
09:07:00.972158 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166388013:1166389173, ack 467889974, win 65535, length 1160
09:07:00.972160 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166389173, win 489, length 0
09:07:00.973641 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166389173:1166390319, ack 467889974, win 65535, length 1146
09:07:00.973643 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166390319, win 501, length 0
09:07:00.974256 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [P.], seq 467889974:467890100, ack 1166390319, win 501, length 126
09:07:00.974390 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467890100, win 65535, length 0
09:07:01.012854 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166390319:1166390545, ack 467890100, win 65535, length 226
09:07:01.012856 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166390545, win 501, length 0
09:07:01.013034 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [P.], seq 467890100:467890205, ack 1166390545, win 501, length 105
09:07:01.013321 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467890205, win 65535, length 0
09:07:01.050735 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166390545:1166392005, ack 467890205, win 65535, length 1460
09:07:01.050737 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166392005, win 501, length 0
09:07:01.050794 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [P.], seq 1166392005:1166393212, ack 467890205, win 65535, length 1207
09:07:01.050857 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166393212, win 501, length 0
3.4 四次挥手
我们都知道TCP关闭连接要4次挥手,我们的抓包也证实了如下过程:
- client -> server: FIN (我们看到的是 FIN+ACK,这是因为这个 FIN 包除了正常的关闭连接功能之外,还被用于应答 server发过来的前一个包)
- server -> client: ACK
- server -> client: FIN+ACK
- client -> server: ACK
09:07:01.051323 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [F.], seq 467890205, ack 1166393212, win 501, length 0
09:07:01.051785 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [.], ack 467890206, win 65535, length 0
09:07:01.051795 IP 180.101.49.12.443 > 172.17.0.2.56878: Flags [F.], seq 1166393212, ack 467890206, win 65535, length 0
09:07:01.051806 IP 172.17.0.2.56878 > 180.101.49.12.443: Flags [.], ack 1166393213, win 501, length 0
这里要注意了,有的时候只能抓到3条:
- server -> client: FIN+ACK
- client -> server: FIN+ACK
- server -> client : ACK
说好的四次挥手,为什么只有三次挥手?
再回顾一下正常四次挥手发FIN包的过程:
- 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
- 服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
- 服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次
而如果是我们抓到的3条的情况呢?我的结论是
- 服务端没有数据要发给客户端了,所以向客户端发起FIN
- 客户端先收到服务端的FIN报文,回一个ACK,这时候已经确定服务端没有数据发送给自己,自己也没有数据发送给服务端,所以FIN一起发送了
- 服务端ACK客户端的FIN请求
关闭连接可以由服务端发起,也可以由客户端发起。
这里如果说的不对,欢迎留言讨论
4. wireshark分析
tcpdump也可以读取pcap文件,我们发现跟直接输出到标准输出的是一样的。对于简单的输出可以通过tcpdump查看,对于复杂的pcap文件,可以通过wireshark查看更方便。
~ # tcpdump -r baidu.pcap
reading from file baidu4.pcap, link-type EN10MB (Ethernet), snapshot length 262144
09:23:02.084041 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [S], seq 309865409, win 64240, options [mss 1460,sackOK,TS val 2061798466 ecr 0,nop,wscale 7], length 0
09:23:02.111769 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [S.], seq 1579115950, ack 309865410, win 65535, options [mss 1460,wscale 2,eol], length 0
09:23:02.111781 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 1, win 502, length 0
09:23:02.118191 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [P.], seq 1:316, ack 1, win 502, length 315
09:23:02.118471 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [.], ack 316, win 65535, length 0
09:23:02.153470 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 1:1461, ack 316, win 65535, length 1460
09:23:02.153472 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 1461, win 501, length 0
09:23:02.153522 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 1461:2921, ack 316, win 65535, length 1460
09:23:02.153526 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 2921, win 495, length 0
09:23:02.153527 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 2921:4081, ack 316, win 65535, length 1160
09:23:02.153528 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 4081, win 489, length 0
09:23:02.154842 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 4081:5227, ack 316, win 65535, length 1146
09:23:02.154844 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 5227, win 501, length 0
09:23:02.155283 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [P.], seq 316:442, ack 5227, win 501, length 126
09:23:02.155397 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [.], ack 442, win 65535, length 0
09:23:02.181971 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 5227:5453, ack 442, win 65535, length 226
09:23:02.181973 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 5453, win 501, length 0
09:23:02.182064 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [P.], seq 442:547, ack 5453, win 501, length 105
09:23:02.182262 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [.], ack 547, win 65535, length 0
09:23:02.211711 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 5453:6913, ack 547, win 65535, length 1460
09:23:02.211713 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 6913, win 501, length 0
09:23:02.211715 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [P.], seq 6913:8120, ack 547, win 65535, length 1207
09:23:02.211716 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 8120, win 497, length 0
09:23:02.212103 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [F.], seq 547, ack 8120, win 501, length 0
09:23:02.212366 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [.], ack 548, win 65535, length 0
09:23:02.213823 IP 180.101.49.12.443 > 3d465f00340e.56884: Flags [F.], seq 8120, ack 548, win 65535, length 0
09:23:02.213835 IP 3d465f00340e.56884 > 180.101.49.12.443: Flags [.], ack 8121, win 501, length 0
wireshark 支持强大的过滤功能,支持按 IP、端口、协议、连接、TCP flag 以及它们的各 种组合进行过滤,然后进行分析,大大节省网络排障的时间。
从容器中下载文件,安装好wireshark后,双击pcap文件可直接打开
下载刚才保存的pcap文件,docker cp test-1:/root/baidu.pcap baidu.pcap
另外从wireshark里还可以看到tcpdump中看不到的信息