最近在听协议相关的音频,关于 tcp 协议既熟悉又陌生,一直犯愁如何才能看见 tcp 的包,tcp 的报文到底是如何发送和接受,在看到一个工具 tcpdump 后,终于有机会领略 tcp 协议运作的整个过程,mac 上面直接用 brew 安装一下即可。
测试
第一轮测试
开启终端 A,这时候输入密码,就可以监听一切和 baidu.com 发送的报文了。
$ sudo tcpdump host baidu.com -vv
开启终端 B,向 baidu.com 发起一个 http 请求
$ baidu.com
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>
终端A 中有一系列的报文,“【】” 是我人为添加,便于后续分析
$ sudo tcpdump host baidu.com -vv
Password:
tcpdump: data link type PKTAP
tcpdump: listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
23:11:09.672388 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64)
【1】192.168.1.5.63902 > 39.156.69.79.http: Flags [S], cksum 0x17ad (correct), seq 2890741236, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 703720084 ecr 0,sackOK,eol], length 0
23:11:09.704087 IP (tos 0x0, ttl 49, id 0, offset 0, flags [DF], proto TCP (6), length 64)
【2】39.156.69.79.http > 192.168.1.5.63902: Flags [S.], cksum 0xd879 (correct), seq 4200742011, ack 2890741237, win 8192, options [mss 1412,nop,wscale 5,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,sackOK,eol], length 0
23:11:09.704204 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【3】192.168.1.5.63902 > 39.156.69.79.http: Flags [.], cksum 0x5e2b (correct), seq 1, ack 1, win 4096, length 0
23:11:09.704294 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 113)
【4】192.168.1.5.63902 > 39.156.69.79.http: Flags [P.], cksum 0x178d (correct), seq 1:74, ack 1, win 4096, length 73: HTTP, length: 73
GET / HTTP/1.1
Host: baidu.com
User-Agent: curl/7.64.1
Accept: */*
23:11:09.737895 IP (tos 0x0, ttl 41, id 14106, offset 0, flags [DF], proto TCP (6), length 40)
【5】39.156.69.79.http > 192.168.1.5.63902: Flags [.], cksum 0x6ade (correct), seq 1, ack 74, win 772, length 0
23:11:09.738365 IP (tos 0x0, ttl 41, id 14107, offset 0, flags [DF], proto TCP (6), length 345)
【6】39.156.69.79.http > 192.168.1.5.63902: Flags [P.], cksum 0xaf53 (correct), seq 1:306, ack 74, win 772, length 305: HTTP, length: 305
HTTP/1.1 200 OK
Date: Tue, 12 Jan 2021 15:11:09 GMT
Server: Apache
Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
ETag: "51-47cf7e6ee8400"
Accept-Ranges: bytes
Content-Length: 81
Cache-Control: max-age=86400
Expires: Wed, 13 Jan 2021 15:11:09 GMT
Connection: Keep-Alive
Content-Type: text/html
23:11:09.738368 IP (tos 0x0, ttl 41, id 14108, offset 0, flags [DF], proto TCP (6), length 121)
【7】39.156.69.79.http > 192.168.1.5.63902: Flags [P.], cksum 0x66a5 (correct), seq 306:387, ack 74, win 772, length 81: HTTP
23:11:09.738419 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【8】192.168.1.5.63902 > 39.156.69.79.http: Flags [.], cksum 0x5c67 (correct), seq 74, ack 387, win 4089, length 0
23:11:09.738600 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【9】192.168.1.5.63902 > 39.156.69.79.http: Flags [F.], cksum 0x5c5f (correct), seq 74, ack 387, win 4096, length 0
23:11:09.771243 IP (tos 0x0, ttl 41, id 14109, offset 0, flags [DF], proto TCP (6), length 40)
【10】39.156.69.79.http > 192.168.1.5.63902: Flags [.], cksum 0x695b (correct), seq 387, ack 75, win 772, length 0
23:11:09.771248 IP (tos 0x0, ttl 41, id 14110, offset 0, flags [DF], proto TCP (6), length 40)
【11】39.156.69.79.http > 192.168.1.5.63902: Flags [F.], cksum 0x695a (correct), seq 387, ack 75, win 772, length 0
23:11:09.771388 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【12】192.168.1.5.63902 > 39.156.69.79.http: Flags [.], cksum 0x5c5e (correct), seq 75, ack 388, win 4096, length 0
23:11:12.820275 IP (tos 0x0, ttl 49, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【13】39.156.69.79.http > 192.168.1.5.63902: Flags [R], cksum 0x4ef7 (correct), seq 4200742399, win 0, length 0
FLAG 的含义已经放在参考文档,. 表示 ACK 应答
开始连接
【1】是客户端向服务端发了一个 SYN
【2】是服务端向客户端发了一个 SYN和ACK
【3】是客户端向服务端发了一个 ACK
开始交换数据
【4】是客户端向服务端发一个 PUSH,推送数据包
【5】【6】【7】都是服务端向客户端推送数据包
【8】是客户端向服务端发了一个 ACK
开始断开
【9】是客户端向服务端发了一个 FIN
【10】是服务端向客户端发 ACK
【11】是服务端向客户端发 FIN
【12】客户端发送 ACK
【13】服务端发送 RST,这里多了一个中断连接的包。
第二轮测试
终端A:
$ sudo tcpdump host aliyun.com -vv
终端B :
$ curl aliyun.com
查看终端A:
$ sudo tcpdump host aliyun.com -vv
Password:
tcpdump: data link type PKTAP
tcpdump: listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
23:25:16.161588 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 64)
【1】192.168.1.5.63976 > 106.11.172.51.http: Flags [S], cksum 0x24d0 (correct), seq 3441982897, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 704564014 ecr 0,sackOK,eol], length 0
23:25:16.167068 IP (tos 0x0, ttl 54, id 0, offset 0, flags [DF], proto TCP (6), length 64)
【2】106.11.172.51.http > 192.168.1.5.63976: Flags [S.], cksum 0x2097 (correct), seq 2914919378, ack 3441982898, win 11520, options [mss 1412,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,sackOK,eol], length 0
23:25:16.167133 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【3】192.168.1.5.63976 > 106.11.172.51.http: Flags [.], cksum 0xc142 (correct), seq 1, ack 1, win 65535, length 0
23:25:16.167195 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 114)
【4】192.168.1.5.63976 > 106.11.172.51.http: Flags [P.], cksum 0xccc3 (correct), seq 1:75, ack 1, win 65535, length 74: HTTP, length: 74
GET / HTTP/1.1
Host: aliyun.com
User-Agent: curl/7.64.1
Accept: */*
23:25:16.176513 IP (tos 0x0, ttl 49, id 15986, offset 0, flags [DF], proto TCP (6), length 40)
【5】106.11.172.51.http > 192.168.1.5.63976: Flags [.], cksum 0xa474 (correct), seq 1, ack 75, win 7300, length 0
23:25:16.176514 IP (tos 0x0, ttl 49, id 15987, offset 0, flags [DF], proto TCP (6), length 542)
【6】106.11.172.51.http > 192.168.1.5.63976: Flags [P.], cksum 0xf47c (correct), seq 1:503, ack 75, win 7300, length 502: HTTP, length: 502
HTTP/1.1 301 Moved Permanently
Server: Tengine
Date: Tue, 12 Jan 2021 15:25:16 GMT
Content-Type: text/html
Content-Length: 239
Connection: keep-alive
Location: https://aliyun.com/
EagleEye-TraceId: 0b57ff8516104651162244933e7cf7
Timing-Allow-Origin: *
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr/>Powered by Tengine<hr><center>tengine</center>
</body>
</html>
23:25:16.176552 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【7】192.168.1.5.63976 > 106.11.172.51.http: Flags [.], cksum 0xbf02 (correct), seq 75, ack 503, win 65535, length 0
23:25:16.176856 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【8】192.168.1.5.63976 > 106.11.172.51.http: Flags [F.], cksum 0xbf01 (correct), seq 75, ack 503, win 65535, length 0
23:25:16.184031 IP (tos 0x0, ttl 49, id 15988, offset 0, flags [DF], proto TCP (6), length 40)
【9】106.11.172.51.http > 192.168.1.5.63976: Flags [F.], cksum 0xa27c (correct), seq 503, ack 76, win 7300, length 0
23:25:16.184112 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
【10】192.168.1.5.63976 > 106.11.172.51.http: Flags [.], cksum 0xbf00 (correct), seq 76, ack 504, win 65535, length 0
【1】【2】【3】挥手建立连接
【4】【5】【6】【7】交换数据
【8】客户端想断开发送 FIN
【9】服务端也想断开发送 FIN和ACK
【10】客户端发送 ACK
这里推测服务端想少发一个包,将FIN和ACK 合并发送,从而加快和客户端的断开流程。
小结
我在测试过程中发现,tcp 连接确实需要 3 次握手,但是断开各家都不一样,3 次、4 次、5 次都有可能,理论知识和实践很多时候也是不同的。
网友评论