【发布时间】:2014-04-14 19:17:33
【问题描述】:
我们正在尝试分析各种 TCP 实现(Windows 8、Ubuntu 13.10)的行为。为此,我们使用了Scapy,这是一个 Python 工具,可用于制作数据包、通过网络发送数据包并分析响应。
在我们的设置中,我们有一个虚假的 Scapy 引导客户端和一个监听服务器。通过客户端,我们向服务器发送一系列 TCP 数据包并检查响应。服务器只接受连接并且对它们不做任何事情。目的是获得一个简单但更具体的服务器行为模型。我们从模型中省略/忽略重传、窗口甚至数据交换等复杂性。
在分析 Windows 8 上侦听服务器的行为时,我们得到了一个非常好的模型。 然而,在 Ubuntu 上进行实验时,我们遇到了不确定的行为,至少对我来说,这很难解释。我在此处附上了一张 wireshark 日志的图像,其中包含多个类似输入数据包的“运行”。每次运行都通过一个随每次运行递增的端口执行。 奇怪的场景遵循以下模式:
client ---- SYN 0 _ ---> server [LISTENING]
client <- SYN+ACK 0 1 -- server [SYN_RCVD]
client -- ACK+FIN 1 1 -> server [SYN_RCVD]
client <--- ACK 1 2 ---- server [CLOSE_WAIT]
client ---- ACK 1 20 --> server [CLOSE_WAIT]
client <--- ACK 1 2 ---- server [CLOSE_WAIT] or no_response [CLOSE_WAIT]
谁能向我解释一下,为什么在收到无效的确认(对从未存在的段的确认)时,服务器的行为是不确定的?也就是说,要么重新发送它为 ACK+FIN 发送的 ACK,要么不发送任何东西。这种行为是由配置参数引起的吗?在我们的设置中,我们使用默认设置。
顺便说一句,简单的服务器代码:
while (true) {
try {
Socket socket = server.accept();
}
catch (IOException e) {}
}
更新
我分析了模型,对于 Windows 8,在运行相同的序列时,我得到了超时。这不符合明确指定的rfc793 标准:
如果连接处于同步状态(ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSE-WAIT, CLOSING, LAST-ACK, TIME-WAIT), 任何不可接受的段(超出窗口的序列号或 不可接受的确认号)必须只引出一个空的 包含当前发送序列号的确认段 以及指示下一个预期序列号的确认 被接收,并且连接保持在相同的状态。
你们中的一些人能对此有所了解吗?协议实现是为了符合标准还是有一定程度的不符合标准。我想其中一些是不可避免的,因为标准有时无法指定时间限制,但这里我们谈论的是控制流中的不合规性。
显然我做错了什么的可能性仍然存在。 :)
谢谢,保罗。
【问题讨论】:
-
错误,一个错误?显然,它应该重新发送它发送的最后一个 ACK。 NB 状态是 CLOSE_WAIT,而不是 CLOSED_WAIT。本地端口根本没有关闭,关键是它正在等待关闭。
-
我的错,确实是CLOSE_WAIT,是的,端口没有关闭。我会相应地更新我的帖子。我同意你的看法,我所期望的行为是重新发送之前的 ACK。我想知道 Wireshark 是否丢失/没有看到那些 ACK 数据包。我从 Ubuntu 12.04 LTS 和 Ubuntu 13.10 得到了相同的行为。
标签: python linux networking tcp scapy