ACK 要么Quick 要么Delay
基于 packetdrill TCP 三次握手脚本,通过构造模拟服务器端场景,继续研究测试 TCP Quick ACK 现象。
基础脚本
# cat tcp_quick_ack_000.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.01 < . 1:1(0) ack 1 win 10000
+0 accept(3, ..., ...) = 4
#
TCP Quick ACK
TCP Quick ACK,与常说的 Delayed ACK 对应,Quick ACK 模式下会对每个数据包都回复一个 ACK。一般在连接初始建立时候、收包间隔大于 RTO 时、收到不在接收窗口内的数据包等场景下就会进入 Quick ACK 模式,在进入 Quick ACK 模式的时候,会把初始化 Quick ACK 计数器为 16 或者是小于 16 的一个值,也就是说之后收到的 16 个(或小于16个)数据包都不采用 Delayed ACK。
基础测试
测试场景一
收包间隔大于 RTO 时的场景,脚本如下。
# cat tcp_quick_ack_007.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.01 < . 1:1(0) ack 1 win 10000
+0 accept(3, ..., ...) = 4
+0.01 < P. 1:101(100) ack 1 win 10000
+0 < P. 101:201(100) ack 1 win 10000
+0 < P. 201:301(100) ack 1 win 10000
+0 < P. 301:401(100) ack 1 win 10000
+0 < P. 401:501(100) ack 1 win 10000
+0 < P. 501:601(100) ack 1 win 10000
+0 < P. 601:701(100) ack 1 win 10000
+0 < P. 701:801(100) ack 1 win 10000
+0 < P. 801:901(100) ack 1 win 10000
+0 < P. 901:1001(100) ack 1 win 10000
+0 < P. 1001:1101(100) ack 1 win 10000
+0 < P. 1101:1201(100) ack 1 win 10000
+0 < P. 1201:1301(100) ack 1 win 10000
+0 < P. 1301:1401(100) ack 1 win 10000
+0 < P. 1401:1501(100) ack 1 win 10000
+0 < P. 1501:1601(100) ack 1 win 10000
+0 < P. 1601:1701(100) ack 1 win 10000
+0.25 < P. 1701:1801(100) ack 1 win 10000
+0 `sleep 1`
#
通过 tcpdump 捕获数据包如下,可以看到在收到前 16 个数据段时,服务器端都是立马响应 ACK 数据包,即 Quick ACK,在收到第 17 个数据段 Seq 1601:1701 时,服务器所发送的 ACK 数据包就变为了 Delayed ACK,间隔 40ms+,而在经过超过一个 RTO (212ms) 再接收数据 Seq 1701:1801 时,又再次进入 quickack 模式。
# packetdrill tcp_quick_ack_007.pkt
#
# tcpdump -i any -nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
# tcpdump -i any -nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
21:56:42.770393 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0
21:56:42.770421 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [S.], seq 4280587041, ack 1, win 64240, options [mss 1460], length 0
21:56:42.780501 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [.], ack 1, win 10000, length 0
21:56:42.790572 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1:101, ack 1, win 10000, length 100: HTTP
21:56:42.790589 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 101, win 64140, length 0
21:56:42.790597 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 101:201, ack 1, win 10000, length 100: HTTP
21:56:42.790600 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 201, win 64040, length 0
21:56:42.790604 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 201:301, ack 1, win 10000, length 100: HTTP
21:56:42.790605 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 301, win 63940, length 0
21:56:42.790609 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 301:401, ack 1, win 10000, length 100: HTTP
21:56:42.790611 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 401, win 63840, length 0
21:56:42.790615 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 401:501, ack 1, win 10000, length 100: HTTP
21:56:42.790616 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 501, win 63740, length 0
21:56:42.790619 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 501:601, ack 1, win 10000, length 100: HTTP
21:56:42.790621 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 601, win 63640, length 0
21:56:42.790624 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 601:701, ack 1, win 10000, length 100: HTTP
21:56:42.790625 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 701, win 63540, length 0
21:56:42.790629 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 701:801, ack 1, win 10000, length 100: HTTP
21:56:42.790631 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 801, win 63440, length 0
21:56:42.790635 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 801:901, ack 1, win 10000, length 100: HTTP
21:56:42.790637 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 901, win 63340, length 0
21:56:42.790640 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 901:1001, ack 1, win 10000, length 100: HTTP
21:56:42.790642 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1001, win 63240, length 0
21:56:42.790645 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1001:1101, ack 1, win 10000, length 100: HTTP
21:56:42.790647 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1101, win 63140, length 0
21:56:42.790659 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1101:1201, ack 1, win 10000, length 100: HTTP
21:56:42.790660 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1201, win 63040, length 0
21:56:42.790663 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1201:1301, ack 1, win 10000, length 100: HTTP
21:56:42.790665 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1301, win 62940, length 0
21:56:42.790669 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1301:1401, ack 1, win 10000, length 100: HTTP
21:56:42.790670 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1401, win 62840, length 0
21:56:42.790673 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1401:1501, ack 1, win 10000, length 100: HTTP
21:56:42.790675 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1501, win 62740, length 0
21:56:42.790679 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1501:1601, ack 1, win 10000, length 100: HTTP
21:56:42.790681 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1601, win 62640, length 0
21:56:42.790684 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1601:1701, ack 1, win 10000, length 100: HTTP
21:56:42.838102 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1701, win 62540, length 0
21:56:43.040620 tun0 In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [P.], seq 1701:1801, ack 1, win 10000, length 100: HTTP
21:56:43.040644 tun0 Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [.], ack 1801, win 62440, length 0
21:56:44.043370 ? Out IP 192.168.51.165.8080 > 192.0.2.1.45091: Flags [R.], seq 1, ack 1801, win 63784, length 0
21:56:44.043397 ? In IP 192.0.2.1.45091 > 192.168.51.165.8080: Flags [R.], seq 1801, ack 1, win 10000, length 0
#
当再次进入 quickack 模式时,同样会计算 icsk->icsk_ack.quick 的值,此时还是取自 max_quickacks 的值 16 ,说明之后的 16 个数据包仍是 Quick ACK,验证脚本如下。
# cat tcp_quick_ack_008.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.01 < . 1:1(0) ack 1 win 10000
+0 accept(3, ..., ...) = 4
+0.01 < P. 1:101(100) ack 1 win 10000
+0 < P. 101:201(100) ack 1 win 10000
+0 < P. 201:301(100) ack 1 win 10000
+0 < P. 301:401(100) ack 1 win 10000
+0 < P. 401:501(100) ack 1 win 10000
+0 < P. 501:601(100) ack 1 win 10000
+0 < P. 601:701(100) ack 1 win 10000
+0 < P. 701:801(100) ack 1 win 10000
+0 < P. 801:901(100) ack 1 win 10000
+0 < P. 901:1001(100) ack 1 win 10000
+0 < P. 1001:1101(100) ack 1 win 10000
+0 < P. 1101:1201(100) ack 1 win 10000
+0 < P. 1201:1301(100) ack 1 win 10000
+0 < P. 1301:1401(100) ack 1 win 10000
+0 < P. 1401:1501(100) ack 1 win 10000
+0 < P. 1501:1601(100) ack 1 win 10000
+0 < P. 1601:1701(100) ack 1 win 10000
+0.25 < P. 1701:1801(100) ack 1 win 10000
+0 < P. 1801:1901(100) ack 1 win 10000
+0 < P. 1901:2001(100) ack 1 win 10000
+0 < P. 2001:2101(100) ack 1 win 10000
+0 < P. 2101:2201(100) ack 1 win 10000
+0 < P. 2201:2301(100) ack 1 win 10000
+0 < P. 2301:2401(100) ack 1 win 10000
+0 < P. 2401:2501(100) ack 1 win 10000
+0 < P. 2501:2601(100) ack 1 win 10000
+0 < P. 2601:2701(100) ack 1 win 10000
+0 < P. 2701:2801(100) ack 1 win 10000
+0 < P. 2801:2901(100) ack 1 win 10000
+0 < P. 2901:3001(100) ack 1 win 10000
+0 < P. 3001:3101(100) ack 1 win 10000
+0 < P. 3101:3201(100) ack 1 win 10000
+0 < P. 3201:3301(100) ack 1 win 10000
+0 < P. 3301:3401(100) ack 1 win 10000
+0 `sleep 1`
#
通过 tcpdump 捕获数据包如下,可以看到在收到前 16 个数据段时,服务器端都是立马响应 ACK 数据包,即 Quick ACK,在收到第 17 个数据段 Seq 1601:1701 时,服务器所发送的 ACK 数据包就变为了 Delayed ACK,间隔 40ms+,而在经过超过一个 RTO (212ms) 再接收数据 Seq 1701:1801 时,又再次进入 quickack 模式,然后在之后的 15 个数据包都是立马响应 ACK 数据包,即 Quick ACK,在最后收到数据段 Seq 3301:3401 时,再次变为了 Delayed ACK,间隔 40ms+。
# packetdrill tcp_quick_ack_008.pkt
#
# tcpdump -i any -nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
22:11:54.730408 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0
22:11:54.730429 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [S.], seq 889623468, ack 1, win 64240, options [mss 1460], length 0
22:11:54.740666 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [.], ack 1, win 10000, length 0
22:11:54.750762 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1:101, ack 1, win 10000, length 100: HTTP
22:11:54.750785 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 101, win 64140, length 0
22:11:54.750794 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 101:201, ack 1, win 10000, length 100: HTTP
22:11:54.750797 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 201, win 64040, length 0
22:11:54.750808 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 201:301, ack 1, win 10000, length 100: HTTP
22:11:54.750810 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 301, win 63940, length 0
22:11:54.750813 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 301:401, ack 1, win 10000, length 100: HTTP
22:11:54.750817 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 401, win 63840, length 0
22:11:54.750820 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 401:501, ack 1, win 10000, length 100: HTTP
22:11:54.750822 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 501, win 63740, length 0
22:11:54.750825 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 501:601, ack 1, win 10000, length 100: HTTP
22:11:54.750827 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 601, win 63640, length 0
22:11:54.750829 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 601:701, ack 1, win 10000, length 100: HTTP
22:11:54.750832 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 701, win 63540, length 0
22:11:54.750836 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 701:801, ack 1, win 10000, length 100: HTTP
22:11:54.750839 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 801, win 63440, length 0
22:11:54.750843 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 801:901, ack 1, win 10000, length 100: HTTP
22:11:54.750845 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 901, win 63340, length 0
22:11:54.750847 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 901:1001, ack 1, win 10000, length 100: HTTP
22:11:54.750850 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1001, win 63240, length 0
22:11:54.750853 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1001:1101, ack 1, win 10000, length 100: HTTP
22:11:54.750855 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1101, win 63140, length 0
22:11:54.750858 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1101:1201, ack 1, win 10000, length 100: HTTP
22:11:54.750859 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1201, win 63040, length 0
22:11:54.750862 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1201:1301, ack 1, win 10000, length 100: HTTP
22:11:54.750864 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1301, win 62940, length 0
22:11:54.750874 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1301:1401, ack 1, win 10000, length 100: HTTP
22:11:54.750876 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1401, win 62840, length 0
22:11:54.750880 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1401:1501, ack 1, win 10000, length 100: HTTP
22:11:54.750881 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1501, win 62740, length 0
22:11:54.750884 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1501:1601, ack 1, win 10000, length 100: HTTP
22:11:54.750886 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1601, win 62640, length 0
22:11:54.750889 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1601:1701, ack 1, win 10000, length 100: HTTP
22:11:54.794132 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1701, win 62540, length 0
22:11:55.000761 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1701:1801, ack 1, win 10000, length 100: HTTP
22:11:55.000787 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1801, win 62440, length 0
22:11:55.000798 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1801:1901, ack 1, win 10000, length 100: HTTP
22:11:55.000809 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 1901, win 62340, length 0
22:11:55.000813 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 1901:2001, ack 1, win 10000, length 100: HTTP
22:11:55.000825 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2001, win 62240, length 0
22:11:55.000829 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2001:2101, ack 1, win 10000, length 100: HTTP
22:11:55.000831 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2101, win 62140, length 0
22:11:55.000834 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2101:2201, ack 1, win 10000, length 100: HTTP
22:11:55.000836 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2201, win 62040, length 0
22:11:55.000839 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2201:2301, ack 1, win 10000, length 100: HTTP
22:11:55.000843 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2301, win 61940, length 0
22:11:55.000847 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2301:2401, ack 1, win 10000, length 100: HTTP
22:11:55.000850 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2401, win 61840, length 0
22:11:55.000853 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2401:2501, ack 1, win 10000, length 100: HTTP
22:11:55.000854 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2501, win 61740, length 0
22:11:55.000857 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2501:2601, ack 1, win 10000, length 100: HTTP
22:11:55.000859 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2601, win 61640, length 0
22:11:55.000863 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2601:2701, ack 1, win 10000, length 100: HTTP
22:11:55.000864 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2701, win 61540, length 0
22:11:55.000867 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2701:2801, ack 1, win 10000, length 100: HTTP
22:11:55.000871 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2801, win 61440, length 0
22:11:55.000874 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2801:2901, ack 1, win 10000, length 100: HTTP
22:11:55.000876 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 2901, win 61340, length 0
22:11:55.000880 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 2901:3001, ack 1, win 10000, length 100: HTTP
22:11:55.000882 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 3001, win 61240, length 0
22:11:55.000885 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 3001:3101, ack 1, win 10000, length 100: HTTP
22:11:55.000886 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 3101, win 61140, length 0
22:11:55.000889 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 3101:3201, ack 1, win 10000, length 100: HTTP
22:11:55.000892 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 3201, win 61040, length 0
22:11:55.000895 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 3201:3301, ack 1, win 10000, length 100: HTTP
22:11:55.000906 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 3301, win 60940, length 0
22:11:55.000911 tun0 In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [P.], seq 3301:3401, ack 1, win 10000, length 100: HTTP
22:11:55.042325 tun0 Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [.], ack 3401, win 60840, length 0
22:11:56.003514 ? Out IP 192.168.133.128.8080 > 192.0.2.1.51479: Flags [R.], seq 1, ack 3401, win 63784, length 0
22:11:56.003543 ? In IP 192.0.2.1.51479 > 192.168.133.128.8080: Flags [R.], seq 3401, ack 1, win 10000, length 0
#
测试场景二
收到不在接收窗口内的数据包的场景,脚本如下。
# cat tcp_quick_ack_009.pkt
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 setsockopt(3, SOL_SOCKET, SO_RCVBUF, [3000],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
+0.01 < P. 1:1461(1460) ack 1 win 10000
+0 < P. 1461:2921(1460) ack 1 win 8000
+0 < P. 2921:3021(100) ack 1 win 10000
+0 `sleep 1`
#
通过 tcpdump 捕获数据包如下,可以看到因 SO_RCVBUF 3000 限制,服务器 win 实际大小为 2920,在收到前 2 个数据段时,服务器端实际接收窗口已经降为 0。此时根据实验需求,继续模拟注入第 3 个数据段,实际也就是超出了接收窗口,对于客户端而言是属于不在接收窗口内的数据包,那么此时会立马响应 ACK 数据包,即 Quick ACK,此时 ACK Num 为 2921,并没有接受这个 100 字节的数据。
# packetdrill tcp_quick_ack_009.pkt
#
# tcpdump -i any -nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
18:05:51.960161 tun0 In IP 192.0.2.1.39417 > 192.168.33.94.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0
18:05:51.960211 tun0 Out IP 192.168.33.94.8080 > 192.0.2.1.39417: Flags [S.], seq 2233893262, ack 1, win 2920, options [mss 1460], length 0
18:05:51.970502 tun0 In IP 192.0.2.1.39417 > 192.168.33.94.8080: Flags [.], ack 1, win 10000, length 0
18:05:51.980703 tun0 In IP 192.0.2.1.39417 > 192.168.33.94.8080: Flags [P.], seq 1:1461, ack 1, win 10000, length 1460: HTTP
18:05:51.980773 tun0 Out IP 192.168.33.94.8080 > 192.0.2.1.39417: Flags [.], ack 1461, win 1460, length 0
18:05:51.980788 tun0 In IP 192.0.2.1.39417 > 192.168.33.94.8080: Flags [P.], seq 1461:2921, ack 1, win 8000, length 1460: HTTP
18:05:51.980818 tun0 In IP 192.0.2.1.39417 > 192.168.33.94.8080: Flags [P.], seq 2921:3021, ack 1, win 10000, length 100: HTTP
18:05:51.980852 tun0 Out IP 192.168.33.94.8080 > 192.0.2.1.39417: Flags [.], ack 2921, win 0, length 0
18:05:52.983207 ? Out IP 192.168.33.94.8080 > 192.0.2.1.39417: Flags [R.], seq 1, ack 2921, win 2920, length 0
18:05:52.983291 ? In IP 192.0.2.1.39417 > 192.168.33.94.8080: Flags [R.], seq 3021, ack 1, win 10000, length 0
#
测试场景三
通过路由表设置 Quick ACK 模式,如下。
# ip route change 192.0.2.0/24 dev tun0 quickack 1
模拟连续注入 20 个数据段,如下脚本。
# cat tcp_quick_ack_010.pkt
`ip route change 192.0.2.0/24 dev tun0 quickack 1`
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
+0.01 < P. 1:101(100) ack 1 win 10000
+0 < P. 101:201(100) ack 1 win 10000
+0 < P. 201:301(100) ack 1 win 10000
+0 < P. 301:401(100) ack 1 win 10000
+0 < P. 401:501(100) ack 1 win 10000
+0 < P. 501:601(100) ack 1 win 10000
+0 < P. 601:701(100) ack 1 win 10000
+0 < P. 701:801(100) ack 1 win 10000
+0 < P. 801:901(100) ack 1 win 10000
+0 < P. 901:1001(100) ack 1 win 10000
+0 < P. 1001:1101(100) ack 1 win 10000
+0 < P. 1101:1201(100) ack 1 win 10000
+0 < P. 1201:1301(100) ack 1 win 10000
+0 < P. 1301:1401(100) ack 1 win 10000
+0 < P. 1401:1501(100) ack 1 win 10000
+0 < P. 1501:1601(100) ack 1 win 10000
+0 < P. 1601:1701(100) ack 1 win 10000
+0 < P. 1701:1801(100) ack 1 win 10000
+0 < P. 1801:1901(100) ack 1 win 10000
+0 < P. 1901:2001(100) ack 1 win 10000
+0 `sleep 1`
#
通过 tcpdump 捕获数据包如下,可以看到在收到前 16 个数据段时,服务器端都是立马响应 ACK 数据包,即 Quick ACK,在收到第 17-20 个数据段时,服务器端也依然是立马响应 ACK 数据包,始终是 Quick ACK。
原因是在判断 tcp_in_quickack_mode() 是否成立的时候,由于路由设置 quickack 1,因此返回真,会始终处于 quickack_mode 。
# packetdrill tcp_quick_ack_010.pkt
#
# tcpdump -i any -nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
11:07:43.337925 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0
11:07:43.338018 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [S.], seq 2640009434, ack 1, win 64240, options [mss 1460], length 0
11:07:43.348238 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [.], ack 1, win 10000, length 0
11:07:43.358325 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1:101, ack 1, win 10000, length 100: HTTP
11:07:43.358345 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 101, win 64140, length 0
11:07:43.358354 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 101:201, ack 1, win 10000, length 100: HTTP
11:07:43.358357 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 201, win 64040, length 0
11:07:43.358360 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 201:301, ack 1, win 10000, length 100: HTTP
11:07:43.358362 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 301, win 63940, length 0
11:07:43.358365 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 301:401, ack 1, win 10000, length 100: HTTP
11:07:43.358369 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 401, win 63840, length 0
11:07:43.358373 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 401:501, ack 1, win 10000, length 100: HTTP
11:07:43.358375 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 501, win 63740, length 0
11:07:43.358378 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 501:601, ack 1, win 10000, length 100: HTTP
11:07:43.358379 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 601, win 63640, length 0
11:07:43.358383 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 601:701, ack 1, win 10000, length 100: HTTP
11:07:43.358384 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 701, win 63540, length 0
11:07:43.358395 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 701:801, ack 1, win 10000, length 100: HTTP
11:07:43.358397 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 801, win 63440, length 0
11:07:43.358401 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 801:901, ack 1, win 10000, length 100: HTTP
11:07:43.358402 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 901, win 63340, length 0
11:07:43.358405 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 901:1001, ack 1, win 10000, length 100: HTTP
11:07:43.358407 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1001, win 63240, length 0
11:07:43.358410 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1001:1101, ack 1, win 10000, length 100: HTTP
11:07:43.358412 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1101, win 63140, length 0
11:07:43.358416 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1101:1201, ack 1, win 10000, length 100: HTTP
11:07:43.358417 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1201, win 63040, length 0
11:07:43.358420 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1201:1301, ack 1, win 10000, length 100: HTTP
11:07:43.358422 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1301, win 62940, length 0
11:07:43.358425 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1301:1401, ack 1, win 10000, length 100: HTTP
11:07:43.358426 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1401, win 62840, length 0
11:07:43.358430 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1401:1501, ack 1, win 10000, length 100: HTTP
11:07:43.358436 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1501, win 62740, length 0
11:07:43.358440 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1501:1601, ack 1, win 10000, length 100: HTTP
11:07:43.358441 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1601, win 62640, length 0
11:07:43.358444 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1601:1701, ack 1, win 10000, length 100: HTTP
11:07:43.358445 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1701, win 62540, length 0
11:07:43.358449 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1701:1801, ack 1, win 10000, length 100: HTTP
11:07:43.358450 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1801, win 62440, length 0
11:07:43.358453 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1801:1901, ack 1, win 10000, length 100: HTTP
11:07:43.358456 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 1901, win 62340, length 0
11:07:43.358459 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [P.], seq 1901:2001, ack 1, win 10000, length 100: HTTP
11:07:43.358461 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [.], ack 2001, win 62240, length 0
11:07:44.372961 tun0 Out IP 192.168.245.204.8080 > 192.0.2.1.58135: Flags [R.], seq 1, ack 2001, win 63784, length 0
11:07:44.372991 tun0 In IP 192.0.2.1.58135 > 192.168.245.204.8080: Flags [R.], seq 2001, ack 1, win 10000, length 0
#
往期推荐
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...