Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传

admin 2024年6月29日18:55:22评论1 views字数 9179阅读30分35秒阅读模式

问题解决,再出发。

实验目的

基于 packetdrill TCP 三次握手脚本,通过构造模拟服务器端场景,测试服务器端 SYN/ACK 超时重传现象。

基础脚本

# cat tcp_3hs_000.pkt // TCP 基础之三次握手0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0+0  bind(3, ..., ...) = 0+0  listen(3, 1) = 0+0  < S 0:0(0) win 10000 <mss 1460>+0  > S. 0:0(0) ack 1 <...>+0.01 < . 1:1(0) ack 1 win 10000+0 accept(3, ..., ...) = 4

基础测试

和 SYN 超时重传测试一样,注释掉或者删除 ACK 即可 ,并使得程序不要退出即可,这样在服务器端协议栈发出 SYN/ACK 后,没有得到响应,即会进入超时重传现象。

# cat tcp_rto_002.pkt 0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0+0  bind(3, ..., ...) = 0+0  listen(3, 1) = 0+0  < S 0:0(0) win 10000 <mss 1460>+0  > S. 0:0(0) ack 1 <...>+0 `sleep 10000000`# 执行脚本,保持不退出状态# packetdrill tcp_rto_002.pkt 同时 tcpdump 捕获数据包,等待一段时间后,即可捕获到所有的 SYN/ACK 超时重传数据包。# tcpdump -i any -nn port 8080tcpdump: data link type LINUX_SLL2tcpdump: verbose output suppressed, use -v[v]... for full protocol decodelistening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes20:30:13.170724 tun0  In  IP 192.0.2.1.56859 > 192.168.237.87.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 020:30:13.170763 tun0  Out IP 192.168.237.87.8080 > 192.0.2.1.56859: Flags [S.], seq 1467398021, ack 1, win 64240, options [mss 1460], length 020:30:14.200707 tun0  Out IP 192.168.237.87.8080 > 192.0.2.1.56859: Flags [S.], seq 1467398021, ack 1, win 64240, options [mss 1460], length 020:30:16.216702 tun0  Out IP 192.168.237.87.8080 > 192.0.2.1.56859: Flags [S.], seq 1467398021, ack 1, win 64240, options [mss 1460], length 020:30:20.280703 tun0  Out IP 192.168.237.87.8080 > 192.0.2.1.56859: Flags [S.], seq 1467398021, ack 1, win 64240, options [mss 1460], length 020:30:28.472703 tun0  Out IP 192.168.237.87.8080 > 192.0.2.1.56859: Flags [S.], seq 1467398021, ack 1, win 64240, options [mss 1460], length 020:30:44.600702 tun0  Out IP 192.168.237.87.8080 > 192.0.2.1.56859: Flags [S.], seq 1467398021, ack 1, win 64240, options [mss 1460], length 0

通过 tcpdump 捕获的数据包跟踪文件,再通过 Wireshark 打开如下,共计重传 5 次,间隔时间以 1s、2s、4s、8s、16s 翻倍递增,最后一次超时重传后还会持续 32s。

Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传


不通过 packetdrill 脚本测试的话,简单写一个过滤发给目标 IP ACK 数据包的规则,再发起一个到目标 IP + 端口的 TCP 连接即可,同样现象。

# iptables -A OUTPUT -d 1.1.1.1 -p tcp --tcp-flags ACK ACK -j DROP# telnet 1.1.1.1 22# tcpdump -i any -nn host 1.1.1.1tcpdump: data link type LINUX_SLL2tcpdump: verbose output suppressed, use -v[v]... for full protocol decodelistening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes19:41:17.197654 IP 1.1.1.2.60464 > 1.1.1.1.22: Flags [S], seq 3702000069, win 29200, options [mss 1460,sackOK,TS val 4026416615 ecr 0,nop,wscale 7], length 019:41:17.197890 IP 1.1.1.1.22 > 1.1.1.2.60464: Flags [S.], seq 2521530521, ack 3702000070, win 28960, options [mss 1460,sackOK,TS val 988806450 ecr 4026416615,nop,wscale 7], length 019:41:18.599017 IP 1.1.1.1.22 > 1.1.1.2.60464: Flags [S.], seq 2521530521, ack 3702000070, win 28960, options [mss 1460,sackOK,TS val 988807852 ecr 4026416615,nop,wscale 7], length 019:41:20.599007 IP 1.1.1.1.22 > 1.1.1.2.60464: Flags [S.], seq 2521530521, ack 3702000070, win 28960, options [mss 1460,sackOK,TS val 988809852 ecr 4026416615,nop,wscale 7], length 019:41:24.599051 IP 1.1.1.1.22 > 1.1.1.2.60464: Flags [S.], seq 2521530521, ack 3702000070, win 28960, options [mss 1460,sackOK,TS val 988813852 ecr 4026416615,nop,wscale 7], length 019:41:32.599018 IP 1.1.1.1.22 > 1.1.1.2.60464: Flags [S.], seq 2521530521, ack 3702000070, win 28960, options [mss 1460,sackOK,TS val 988821852 ecr 4026416615,nop,wscale 7], length 019:41:48.599057 IP 1.1.1.1.22 > 1.1.1.2.60464: Flags [S.], seq 2521530521, ack 3702000070, win 28960, options [mss 1460,sackOK,TS val 988837852 ecr 4026416615,nop,wscale 7], length 0

服务器端的 SYN/ACK 报文最大重传次数由 tcp_synack_retries 内核参数控制,这个参数是可以自定义的,本次测试系统的 SYN/ACK 报文最大重传次数为 5 次,相关参数如下:

# uname -r5.15.0-76-generic# cat /proc/sys/net/ipv4/tcp_synack_retries5# sysctl -a | grep synacknet.ipv4.tcp_synack_retries = 5#

扩展测试一

可以写一个过滤目标 IP 发来的 SYN/ACK 数据包的规则,这时候会出现客户端 SYN 和服务器端 SYN/ACK 同时重传的现象,因为本端客户端收不到 SYN/ACK,因此会不断重传 SYN,而对端服务器端收不到 ACK,因此会不断重传 SYN/ACK。但仔细数数重传的次数,会发现一个有趣的现象是,SYN 的重传次数是 6,但 SYN/ACK 的重传次数看起来是 11,而不是 5

# telnet 10.1.1.2 22Trying 10.1.1.2...telnet: Unable to connect to remote host: Connection timed out## tcpdump -i 1 -nn host 10.1.1.1 and tcptcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on ens160, link-type EN10MB (Ethernet), capture size 262144 bytes13:22:12.323503 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149412385 ecr 0,nop,wscale 7], length 013:22:12.323532 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518049389 ecr 3149412385,nop,wscale 7], length 013:22:13.340313 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149413402 ecr 0,nop,wscale 7], length 013:22:13.340330 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518050405 ecr 3149412385,nop,wscale 7], length 013:22:14.342714 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518051408 ecr 3149412385,nop,wscale 7], length 013:22:15.356303 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149415418 ecr 0,nop,wscale 7], length 013:22:15.356318 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518052421 ecr 3149412385,nop,wscale 7], length 013:22:17.382713 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518054448 ecr 3149412385,nop,wscale 7], length 013:22:19.548280 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149419610 ecr 0,nop,wscale 7], length 013:22:19.548293 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518056613 ecr 3149412385,nop,wscale 7], length 013:22:23.558716 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518060624 ecr 3149412385,nop,wscale 7], length 013:22:27.740240 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149427802 ecr 0,nop,wscale 7], length 013:22:27.740256 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518064805 ecr 3149412385,nop,wscale 7], length 013:22:35.846721 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518072912 ecr 3149412385,nop,wscale 7], length 013:22:43.868150 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149443930 ecr 0,nop,wscale 7], length 013:22:43.868173 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518080933 ecr 3149412385,nop,wscale 7], length 013:22:59.910723 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518096976 ecr 3149412385,nop,wscale 7], length 013:23:17.147935 IP 10.1.1.1.36716 > 10.1.1.2.22: Flags [S], seq 2691663877, win 64240, options [mss 1460,sackOK,TS val 3149477210 ecr 0,nop,wscale 7], length 013:23:17.147965 IP 10.1.1.2.22 > 10.1.1.1.36716: Flags [S.], seq 4199882703, ack 2691663878, win 65160, options [mss 1460,sackOK,TS val 3518114213 ecr 3149412385,nop,wscale 7], length 0

通过 Wireshark 打开数据包跟踪文件,各自的重传数据包交错在一起,乍看下来挺晕。

Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传

注:数据包跟踪文件取自另一次测试,忽略时间差异。

完整分析过程如下:

1. No.1 为客户端 SYN;

2. No.2 为服务器响应 SYN/ACK;

3. No.3 为客户端第一次超时重传 SYN,间隔 No.1 1 秒;

4. No.4 为服务器 SYN/ACK,实际上是对 No.3 SYN 的响应,而不是服务器第一次超时重传 SYN/ACK,且此时 SYN/ACK 的超时时间仍为 1 秒;

5. No.5 为服务器对 No.4 的超时重传 SYN/ACK,间隔 No.4 1 秒,此时 SYN/ACK 的超时时间为 2 秒;

6. No.6 为客户端第二次超时重传 SYN,间隔 No.3 2 秒;

7. No.7 为服务器 SYN/ACK,是对 No.6 SYN 的响应此时 SYN/ACK 的超时时间仍为 2 秒;

8. No.8 为服务器对 No.7 的超时重传 SYN/ACK,间隔 No.7 2 秒,此时 SYN/ACK 的超时时间为 4 秒;

9. No.9 为客户端第三次超时重传 SYN,间隔 No.6 4 秒;

10. No.10 为服务器 SYN/ACK,是对 No.9 SYN 的响应此时 SYN/ACK 的超时时间仍为 4 秒;

11. No.11 为服务器对 No.10 的超时重传 SYN/ACK,间隔 No.10 4 秒,此时 SYN/ACK 的超时时间为 8 秒;

12. No.12 为客户端第四次超时重传 SYN,间隔 No.9 8 秒;

13. No.13 为服务器 SYN/ACK,是对 No.12 SYN 的响应此时 SYN/ACK 的超时时间仍为 8 秒;

14. No.14 为服务器对 No.13 的超时重传 SYN/ACK,间隔 No.13 8 秒,此时 SYN/ACK 的超时时间为 16 秒;

15. No.15 为客户端第五次超时重传 SYN,间隔 No.12 16 秒;

16. No.16 为服务器 SYN/ACK,是对 No.15 SYN 的响应此时 SYN/ACK 的超时时间仍为 16 秒;

17. No.17 为服务器对 No.16 的超时重传 SYN/ACK,间隔 No.16 16 秒,此时 SYN/ACK 的超时时间为 32 秒;

18. No.18 为客户端第六次超时重传 SYN,间隔 No.15 32 秒+;

19. No.19 为服务器 SYN/ACK,是对 No.18 SYN 的响应,此时 SYN/ACK 的超时时间仍为 32 秒,此时停止,不再继续进行超时重传。


总结:

  1. 客户端 SYN 是真正 tcp_syn_retries 参数下所控制的超时重传,因为始终没有收到 SYN/ACK,所以不断地 RTO 时间翻倍产生超时重传;

Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传

  1. 服务器 SYN/ACK 实际上包括接收到 SYN 后触发产生的响应 SYN/ACK,以及针对上个 SYN/ACK 所产生的超时重传,这其中在超时时间上的变化会有点特殊。

扩展测试二

当然,如果你测试的次数如果多了,也会发现其他现象,那就是 SYN/ACK 偶尔会先发生超时。

上边的例子都是 SYN 超时重传先至,先触发了 SYN/ACK 的响应,然后再发生 SYN/ACK 的超时重传,而下面的这个测试结果部分就会不太一样。

Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传


再一次完整分析过程如下:

  1. No.1 为客户端 SYN;

  2. No.2 为服务器响应 SYN/ACK;

  3. No.3 为服务器第一次超时重传 SYN/ACK,间隔 No.2 1 秒,此时 SYN/ACK 的超时时间为 2 秒;

  4. No.4 为客户端第一次超时重传 SYN,间隔 No.1 1 秒;

  5. No.5 为服务器 SYN/ACK,是对 No.4 SYN 的响应,此时 SYN/ACK 的超时时间仍为 2 秒;

  6. No.6 为客户端第二次超时重传 SYN,间隔 No.4 2 秒;(之后 No.7-No.19 同测试一现象)

  7. No.7 为服务器 SYN/ACK,是对 No.6 SYN 的响应此时 SYN/ACK 的超时时间仍为 2 秒;

  8. No.8 为服务器对 No.7 的超时重传 SYN/ACK,间隔 No.7 2 秒,此时 SYN/ACK 的超时时间为 4 秒;

  9. No.9 为客户端第三次超时重传 SYN,间隔 No.6 4 秒;

10. No.10 为服务器 SYN/ACK,是对 No.9 SYN 的响应此时 SYN/ACK 的超时时间仍为 4 秒;

11. No.11 为服务器对 No.10 的超时重传 SYN/ACK,间隔 No.10 4 秒,此时 SYN/ACK 的超时时间为 8 秒;

12. No.12 为客户端第四次超时重传 SYN,间隔 No.9 8 秒;

13. No.13 为服务器 SYN/ACK,是对 No.12 SYN 的响应此时 SYN/ACK 的超时时间仍为 8 秒;

14. No.14 为服务器对 No.13 的超时重传 SYN/ACK,间隔 No.13 8 秒,此时 SYN/ACK 的超时时间为 16 秒;

15. No.15 为客户端第五次超时重传 SYN,间隔 No.12 16 秒;

16. No.16 为服务器 SYN/ACK,是对 No.15 SYN 的响应此时 SYN/ACK 的超时时间仍为 16 秒;

17. No.17 为服务器对 No.16 的超时重传 SYN/ACK,间隔 No.16 16 秒,此时 SYN/ACK 的超时时间为 32 秒;

18. No.18 为客户端第六次超时重传 SYN,间隔 No.15 32 秒+;

19. No.19 为服务器 SYN/ACK,是对 No.18 SYN 的响应,此时 SYN/ACK 的超时时间仍为 32 秒,此时停止,不再继续进行超时重传。

Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传

往期推荐

1. Wireshark 提示和技巧 | 捕获点之 TCP 三次握手
2. Wireshark 提示和技巧 | a == ${a} 显示过滤宏
3. Wireshark TS | 防火墙空闲会话超时问题
4. Wireshark TS | HTTP 传输文件慢问题
5. 网络设备 MTU MSS Jumboframe 全解

后台回复「TT」获取 Wireshark 提示和技巧系列 合集
后台回复「TS」获取 Wireshark Troubleshooting 系列 合集
如需交流或加技术群,可后台直接留言,我会在第一时间回复,谢谢!
Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传

原文始发于微信公众号(Echo Reply):Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月29日18:55:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Wireshark & Packetdrill | TCP 三次握手之 SYN/ACK 超时重传https://cn-sec.com/archives/2894324.html

发表评论

匿名网友 填写信息