乱序 FIN 数据包并覆盖?

kum*_*mar 5 sockets networking network-programming tcp protocols

在浏览开源代码库时,我想到了一个有趣的场景。假设 TCP 连接建立成功后,TCP 客户端必须发送一个序列号 = 101 的数据包。而是发送一个序列号为 201 的 FIN。现在 TCP 服务器认为 FIN 乱序并将其排队等待一个数据包到达。我的问题是,如果服务器收到序列号 = 101 和长度 = 150 的数据包,则根据 RFC,TCP 端点的行为应该是什么。它是否会覆盖之前发送的 FIN?或者服务器将数据包修剪到 FIN 序列号?或者它依赖于 TCP 实现?

rod*_*olk 4

根据RFC 793中的一些段落

”3.如果连接处于同步状态(ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、CLOSING、LAST-ACK、TIME-WAIT),任何不可接受的段(超出窗口序列号或不可接受的确认号)必须仅引出一个空确认段,其中包含当前发送序列号和指示预期接收的下一个序列号的确认,并且连接保持在相同状态。”

....

“考虑处理传入段的一种自然方法是想象它们首先被测试是否有正确的序列号(即,它们的内容位于序列号空间中​​预期的“接收窗口”范围内),然后它们是一般按序列号顺序排队和处理。

当一个段与其他已接收到的段重叠时,我们会重建该段以仅包含新数据,并调整标头字段以保持一致。”

...

我的响应: 请记住,如果发生这种情况,那是因为客户端 TCP 行为不良。不是因为乱序,而是因为带有 FIN 标志的段中的顺序错误。或者也许是一次攻击。

当服务器端的 TCP 接收到 SEQ=201 的报文段时,它会在有限的时间内存储该报文段,并会发回 101 的 ACK,因为它正在等待该 SEQ 号。那么当SEQ=101的报文段到达时,接收端的TCP在接收到SEQ=101的报文段后会产生一个新的接收窗口。从第一个到达的 SEQ=201 的段中,它应该只获取超出字节 251 的数据(在我的测试中,它不是这样做,而是从 SEQ=101 的段中删除重叠的字节 - 这可能取决于实现),如果有的话,并接受 FIN。接收方 TCP 将发回 ACK。当服务器端关闭套接字时,接收 TCP 将发回一个 [FIN, ACK] 段。

为了测试它,我有一个客户端完全按照您所描述的方式进行操作(这是通过用户空间中的原始套接字完成的,不可能使用 TCP 套接字来模拟它。服务器是一个简单的 Nodejs 服务器),发送 FIN 段并发送 15几秒钟后发送前一个片段。服务器读取收到的数据,10 秒后关闭套接字。

这是 tcpdump,您可以看到 TCP 服务器端响应:

    [rodolk@localhost ~]$ sudo tcpdump -i p2p1 -vv tcp
tcpdump: listening on p2p1, link-type EN10MB (Ethernet), capture size 65535 bytes
19:33:03.648216 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [S], cksum 0x5f49 (correct), seq 523645, win 500, length 0
19:33:03.649826 IP (tos 0x0, ttl 128, id 26590, offset 0, flags [DF], proto TCP (6), length 44)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [S.], cksum 0x1ac8 (correct), seq 1576251572, ack 523646, win 8192, options [mss 1460], length 0
19:33:03.651208 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [.], cksum 0x5091 (correct), seq 1, ack 1, win 500, length 0
19:33:03.651567 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 74)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [F.], cksum 0x8121 (correct), seq 122:156, ack 1, win 500, length 34
19:33:03.651891 IP (tos 0x0, ttl 128, id 26591, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [.], cksum 0x5314 (correct), seq 1, ack 1, win 65392, length 0
19:33:18.652083 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 171)
    192.168.56.101.16345 > 192.168.56.1.webcache: Flags [P.], cksum 0xf973 (correct), seq 1:132, ack 1, win 500, length 131
19:33:18.652834 IP (tos 0x0, ttl 128, id 26593, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [.], cksum 0x5313 (correct), seq 1, ack 157, win 65237, length 0
19:33:28.661041 IP (tos 0x0, ttl 128, id 26594, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [F.], cksum 0x5312 (correct), seq 1, ack 157, win 65237, length 0
19:33:28.961756 IP (tos 0x0, ttl 128, id 26595, offset 0, flags [DF], proto TCP (6), length 40)
    192.168.56.1.webcache > 192.168.56.101.16345: Flags [F.], cksum 0x5312 (correct), seq 1, ack 157, win 65237, length 0
Run Code Online (Sandbox Code Playgroud)

  • 接收 TCP 将在最后发回 ACK。出站FIN是由应用程序引起的。它不是传入 FIN 确认的一部分。 (2认同)