人生不如意事十之八九,常想一二
实验目的
基于 packetdrill TCP 三次握手脚本,测试 TCP 连接中的 KeepAlive 功能,此次构造模拟的是服务器端场景。
基础脚本
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 Keep-Alives
引用 RFC9293 的标准定义说明:
3.8.4. TCP Keep-Alives
A TCP connection is said to be "idle" if for some long amount of time there have been no incoming segments received and there is no new or unacknowledged data to be sent.
Implementers MAY include "keep-alives" in their TCP implementations (MAY-5), although this practice is not universally accepted. Some TCP implementations, however, have included a keep-alive mechanism. To confirm that an idle connection is still active, these implementations send a probe segment designed to elicit a response from the TCP peer. Such a segment generally contains SEG.SEQ = SND.NXT-1 and may or may not contain one garbage octet of data. If keep-alives are included, the application MUST be able to turn them on or off for each TCP connection (MUST-24), and they MUST default to off (MUST-25).
Keep-alive packets MUST only be sent when no sent data is outstanding, and no data or acknowledgment packets have been received for the connection within an interval (MUST-26). This interval MUST be configurable (MUST-27) and MUST default to no less than two hours (MUST-28).
It is extremely important to remember that ACK segments that contain no data are not reliably transmitted by TCP. Consequently, if a keep-alive mechanism is implemented it MUST NOT interpret failure to respond to any specific probe as a dead connection (MUST-29).
An implementation SHOULD send a keep-alive segment with no data (SHLD-12); however, it MAY be configurable to send a keep-alive segment containing one garbage octet (MAY-6), for compatibility with erroneous TCP implementations.
TCP Keep-Alive 功能是默认关闭的,如需使用,需要应用对每一个 TCP 连接开启,相关参数如下:
# sysctl -a|grep keepalive
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200
#
tcp_keepalive_time
TCP keepalive空闲时长,默认7200秒,即2小时。
tcp_keepalive_intvl
TCP keepalive探测包的发送间隔,默认75s。
tcp_keepalive_probes
如TCP keepalive探测包没得到响应,最大尝试次数,默认9次。
实验测试
为了简化测试,在开启 TCP KeepAlive 功能时,计划将相关参数改为如下值:
tcp_keepalive_time
TCP keepalive空闲时长,10秒。
tcp_keepalive_intvl
TCP keepalive探测包的发送间隔,5秒。
tcp_keepalive_probes
如TCP keepalive探测包没得到响应,尝试探测次数,3次。
修改脚本如下。
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_KEEPIDLE, [10], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_KEEPINTVL, [5], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_KEEPCNT, [3], 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 `sleep 60`
#
执行脚本,并观察 tcpdump 抓包结果,预期运行正常。
# packetdrill tcp_keepalive_001.pkt
#
# tcpdump -i any-nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... forfull protocol decode
listening onany, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
18:04:31.917894 tun0 In IP 192.0.2.1.57925>192.168.135.255.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0
18:04:31.917922 tun0 Out IP 192.168.135.255.8080>192.0.2.1.57925: Flags [S.], seq 738618762, ack 1, win 64240, options [mss 1460], length 0
18:04:31.927999 tun0 In IP 192.0.2.1.57925>192.168.135.255.8080: Flags [.], ack 1, win 10000, length 0
18:04:41.941597 tun0 Out IP 192.168.135.255.8080>192.0.2.1.57925: Flags [.], ack 1, win 64240, length 0
18:04:47.065593 tun0 Out IP 192.168.135.255.8080>192.0.2.1.57925: Flags [.], ack 1, win 64240, length 0
18:04:52.181616 tun0 Out IP 192.168.135.255.8080>192.0.2.1.57925: Flags [.], ack 1, win 64240, length 0
18:04:57.301595 tun0 Out IP 192.168.135.255.8080>192.0.2.1.57925: Flags [R.], seq 1, ack 1, win 64240, length
#
可以看到在 TCP 三次握手连接完成以后,因没有数据传输所以连接空闲,在 10 秒(TCP keepalive 空闲时长)后,服务器端发出 TCP KeepAlive 数据包(SeqNum-1),因没有得到对端的响应,因此每隔 5 秒(TCP keepalive探测包的发送间隔)再次发送,达到 3 次(TCP keepalive探测包尝试次数)后,服务器端发送 RST 数据包终止连接。
继续修改脚本,在发出 TCP KeepAlive 数据包一段时间后收到响应 ACK。
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 setsockopt(3, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_KEEPIDLE, [10], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_KEEPINTVL, [5], 4) = 0
+0 setsockopt(3, SOL_TCP, TCP_KEEPCNT, [3], 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
+17 < . 1:1(0) ack 1 win 10000
+0 `sleep 60`
#
执行脚本,并观察 tcpdump 抓包结果,预期运行正常。
# tcpdump -i any-nn port 8080
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... forfull protocol decode
listening onany, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
19:36:59.557909 tun0 In IP 192.0.2.1.58263>192.168.182.213.8080: Flags [S], seq 0, win 10000, options [mss 1460], length 0
19:36:59.557940 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [S.], seq 1437456361, ack 1, win 64240, options [mss 1460], length 0
19:36:59.568020 tun0 In IP 192.0.2.1.58263>192.168.182.213.8080: Flags [.], ack 1, win 10000, length 0
19:37:09.717603 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [.], ack 1, win 64240, length 0
19:37:14.837605 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [.], ack 1, win 64240, length 0
19:37:16.568102 tun0 In IP 192.0.2.1.58263>192.168.182.213.8080: Flags [.], ack 1, win 10000, length 0
19:37:26.613592 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [.], ack 1, win 64240, length 0
19:37:31.733581 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [.], ack 1, win 64240, length 0
19:37:36.853597 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [.], ack 1, win 64240, length 0
19:37:41.973588 tun0 Out IP 192.168.182.213.8080>192.0.2.1.58263: Flags [R.], seq 1, ack 1, win 64240, length 0
#
可以看到在 TCP 三次握手连接完成以后,因没有数据传输所以连接空闲,在 10 秒(TCP keepalive 空闲时长)后,服务器端发出 TCP KeepAlive 数据包(SeqNum-1),因没有得到对端的响应,因此每隔 5 秒(TCP keepalive探测包的发送间隔)再次发送,达到 2 次时收到对端 ACK 响应,但之后又进入连接空闲,再次在 10 秒后,进行了 TCP KeepAlive 数据包探测,连续 3 次无响应后终止连接。
往期推荐
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...