tcpdump实验分析TCP连接建立传输断开

63次阅读

共计 3490 个字符,预计需要花费 9 分钟才能阅读完成。

TCP 包的结构:TCP 协议规定的数据报文的构造

TCP 报文中的序列号 seq 和确认号到底指什么?

序列号 seq(sequence numer)

序列号 seq,其实 TCP 发送 payload 数据的每一个字节都是有编号的,每个报文的编号其实就是 这个报文 payload 数据中的首个字节的编号 ,通俗的例子:
一共发了 3 个报文:P1(payload=aaa), P2(payload=bb), P3(payload=c),那么

P1.seq=0
P2.seq=3(P1.seq+p1.payload.length) 
P3.seq=5(P2.seq+p2.payload.length)

确认号 ack(acknowledge numer)

确认号 ack,其实是对前一个对端发送来的报文的回复,ack=x+ 1 说明之前对端发送来的 x 个字节的 payload 数据都已经收到了,请对端下次发送 seq=x+ 1 的报文吧,或者说叫 期望从对端收到的下一字节的序号。通俗的例子:
A 主机发来了 P1(payload=aaa), B 主机接收到 P1 报文后需要发回确认报文 R1:

P1.seq=0
R1.ack=3(P1.seq+p1.payload.length) 

tcpdump 抓包分析

抓在 80 端口上的 TCP 包:

> tcpdump -S 'tcp and port 80'
21:33:01.704998 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [S], seq 396038856, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 744881175 ecr 0,sackOK,eol], length 0

其中传输的 Flags 释义:

  • [S]:SYN,表示开始连接
  • [.]:没有标记,一般是确认
  • [P]:PSH,表示数据推送
  • [F]:FIN,表示结束连接
  • [R]:RST,表示重启连接

抓包的一组 TCP 连接传输断开的数据报文:

> tcpdump -S 'tcp and port 80'
21:33:01.704998 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [S], seq 396038856, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 744881175 ecr 0,sackOK,eol], length 0
21:33:01.717502 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [S.], seq 2345237966, ack 396038857, win 14400, options [mss 1412,nop,nop,sackOK,nop,wscale 7], length 0
21:33:01.717542 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [.], ack 2345237967, win 4096, length 0
21:33:01.718011 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [P.], seq 396038857:396039622, ack 2345237967, win 4096, length 765: HTTP: POST /mmtls/22207be4 HTTP/1.1
21:33:01.727958 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [.], ack 396039622, win 125, length 0
21:33:01.758550 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [P.], seq 2345237967:2345238289, ack 396039622, win 125, length 322: HTTP: HTTP/1.1 200 OK
21:33:01.758735 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [.], ack 2345238289, win 4090, length 0
21:33:01.759551 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [F.], seq 2345238289, ack 396039622, win 125, length 0
21:33:01.759693 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [.], ack 2345238290, win 4090, length 0
21:33:01.773281 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [F.], seq 396039622, ack 2345238290, win 4096, length 0
21:33:01.786917 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [.], ack 396039623, win 0, length 0

梳理一下:

报文传输方向 Flags seq ack payload length
C -> S [S] 396038856 0
S -> C [S.] 2345237966 396038857 0
C -> S [.] (396038857) 2345237967 0
C -> S [P.] 396038857(:396039622) 2345237967 765
S -> C [.] (2345237967) 396039622 0
S -> C [P.] 2345237967(:2345238289) 396039622 322
C -> S [.] (396039622) 2345238289 0
S -> C [F.] 2345238289 396039622 0
C -> S [.] (396039622) 2345238290 0
C -> S [F.] 396039622 2345238290 0
S -> C [.] (2345238290) 396039623 0

下面图示了整个连接、传输和断开过程的 TCP 数据报:

其中需要注意的点有:

  • 为了避免过长的 seq 和 ack,图中 seq 和 ack 只展示了后 3 位;
  • tcpdump 开启 - S 命令后,所有的 seq 和 ack 都将保留绝对值而不是相对值,易于清楚呈现出连接报文的详情;
  • 报文 4 seq 396038857:396039622 length 765,这个意思是 seq=396038857,其报文的 payload length=765,所以对端 ack 的时候应该 ack=396039622(即表示 396039622 前的字节我都收到了,下一次请给我编号为 396039622 及以后的字节),显示这个就不需要人读的时候再手工计算了,简单明了的展示清楚,不过第一次用的话会很懵。报文 5 ack 396039622印证了这个观点;
  • 为什么 syn 报文明明 payload length=0,对端 ack 还要加 1 呢?因为 syn 是建立连接的关键报文,而为了确保对方接收到,使用超时重传机制,TCP 规定,只为有数据的 TCP 报文重传,SYN 占据一个序号(可以认为只有一个字节数据的报文,即使其 payload length=0),这样做 TCP 也会重传 SYN 报文;
  • ack 的 payload length=0,可以看到 ack 报文发送后之后的报文 seq 并没有变;

可以对照此经典图进行分析(不过要注意这个图里数据传输过程中的数据报文假定 payload length=1):

正文完
 0