如果一件事情你不能讲清楚,十有八九你还没有完全理解。
实验目的
基础脚本
# cat tcp_si_close_003.pkt
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+0 > S 0:0(0) <...>
+0.01 < S. 0:0(0) ack 1 win 10000 <mss 1000>
+0 > . 1:1(0) ack 1
TCP Simultaneous Close
实验测试
修改脚本如下,执行。
# cat tcp_si_close_004.pkt
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+0 > S 0:0(0) <...>
+0.01 < S. 0:0(0) ack 1 win 10000 <mss 1000>
+0 > . 1:1(0) ack 1
+0 close(3) = 0
+0 > F. 1:1(0) ack 1
+0 < F. 1:1(0) ack 1 win 10000
+0 > . 2:2(0) ack 2
+0.01 < . 2:2(0) ack 2 win 10000
#
执行脚本,并观察 tcpdump 抓包结果,预期运行正常。
# packetdrill tcp_si_close_004.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
15:09:04.579683 tun0 Out IP 192.168.210.8.40058 > 192.0.2.1.8080: Flags [S], seq 4140343214, win 65535, options [mss 1460,sackOK,TS val 876953850 ecr 0,nop,wscale 8], length 0
15:09:04.589790 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [S.], seq 0, ack 4140343215, win 10000, options [mss 1000], length 0
15:09:04.589817 tun0 Out IP 192.168.210.8.40058 > 192.0.2.1.8080: Flags [.], ack 1, win 65535, length 0
15:09:04.589877 tun0 Out IP 192.168.210.8.40058 > 192.0.2.1.8080: Flags [F.], seq 1, ack 1, win 65535, length 0
15:09:04.589899 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [F.], seq 1, ack 1, win 10000, length 0
15:09:04.589903 tun0 Out IP 192.168.210.8.40058 > 192.0.2.1.8080: Flags [.], ack 2, win 65535, length 0
15:09:04.599953 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [.], ack 2, win 10000, length 0
15:09:04.600100 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [R.], seq 2, ack 2, win 10000, length 0
#
1. 前三个数据包为 TCP 三次握手数据包,略过。
2. 第四个数据包为客户端 close 所发出的 FIN 数据包。
15:09:04.589877 tun0 Out IP 192.168.210.8.40058 > 192.0.2.1.8080: Flags [F.], seq 1, ack 1, win 65535, length 0
// 对应于脚本 +0 > F. 1:1(0) ack 1 ,close 关闭连接,预期客户端协议栈发出 FIN 。
3. 第五个数据包为模拟注入的服务器端 FIN 数据包。
15:09:04.589899 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [F.], seq 1, ack 1, win 10000, length 0
// 对应于脚本 +0 < F. 1:1(0) ack 1 win 10000 ,无时间间隔,为模拟服务器端同时发起的 FIN 。
4. 第六个数据包为客户端收到服务器端 FIN 所响应的 ACK 数据包。
15:09:04.589903 tun0 Out IP 192.168.210.8.40058 > 192.0.2.1.8080: Flags [.], ack 2, win 65535, length 0
// 对应于脚本 +0 > . 2:2(0) ack 2 ,为客户端收到 FIN 预期自动所响应的 ACK 。
5. 第七个数据包为模拟服务器端收到 FIN 所响应的 ACK 数据包。
15:09:04.599953 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [.], ack 2, win 10000, length 0
// 对应于脚本 +0.01 < . 2:2(0) ack 2 win 10000 ,为模拟服务器端收到 FIN 后所响应的 ACK 。
6. 最后一个数据包 RST/ACK
15:09:04.600100 tun0 In IP 192.0.2.1.8080 > 192.168.210.8.40058: Flags [R.], seq 2, ack 2, win 10000, length 0
// packetdrill 脚本之外产生的数据包,或者说预期之外的数据包。
// 服务器端所发送的 RST/ACK 结束连接,如前所述是 packetdrill 脚本默认构造,用于快速重置连接使用的。
// 因此这个数据包一般与 packetdrill 构建的测试脚本无关,分析时可省略。
如何确认同时打开连接时的 TCP 状态变化过程,仍可以通过 BCC 工具 tcpstate 进行检查如下,客户端 TCP 状态变化由 ESTABLISHED -> FIN_WAIT1 -> CLOSING -> CLOSE。从之前服务器端模拟的实验结果可知,目前 tcpstate 执行会缺少 TW 状态变化,属于正常情况。
# packetdrill tcp_si_close_004.pkt
#
# ./tcpstates.py -D 8080
SKADDR C-PID C-COMM LADDR LPORT RADDR RPORT OLDSTATE -> NEWSTATE MS
ffff8a82051208c0 381216 packetdril 192.168.101.216 0 192.0.2.1 8080 CLOSE -> SYN_SENT 0.000
ffff8a82051208c0 381216 packetdril 192.168.101.216 58570 192.0.2.1 8080 SYN_SENT -> ESTABLISHED 10.122
ffff8a82051208c0 381216 packetdril 192.168.101.216 58570 192.0.2.1 8080 ESTABLISHED -> FIN_WAIT1 0.122
ffff8a82051208c0 381216 packetdril 192.168.101.216 58570 192.0.2.1 8080 FIN_WAIT1 -> CLOSING 0.044
ffff8a82051208c0 381216 packetdril 192.168.101.216 58570 192.0.2.1 8080 CLOSING -> CLOSE 10.082
#
因为 TW 状态有一个 2MSL 也就是 60 秒的超时时间,所以脚本增加 sleep 后,可以用 ss 进一步检查如下,可以看到确实有 TW 状态的存在。
# cat tcp_si_close_005.pkt
0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+0 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+0 > S 0:0(0) <...>
+0.01 < S. 0:0(0) ack 1 win 10000 <mss 1000>
+0 > . 1:1(0) ack 1
+0 close(3) = 0
+0 > F. 1:1(0) ack 1
+0 < F. 1:1(0) ack 1 win 10000
+0 > . 2:2(0) ack 2
+0.01 < . 2:2(0) ack 2 win 10000
+0 `sleep 100`
#
# packetdrill tcp_si_close_005.pkt
#
# ss -anto | grep 8080
TIME-WAIT 0 0 192.168.102.135:42116 192.0.2.1:8080 timer:(timewait,55sec,0)
#
# ss -anto | grep 8080
TIME-WAIT 0 0 192.168.102.135:42116 192.0.2.1:8080 timer:(timewait,36sec,0)
#
往期推荐
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...