Linux TCP奇怪的行为

时间:2014-04-14 19:17:34

标签: python linux networking tcp scapy

我们正在尝试分析各种TCP实现的行为(Windows 8,Ubuntu 13.10)。为此,我们使用Scapy,这是一个Python工具,您可以使用它来制作数据包,通过网络发送数据并分析响应。

在我们的设置中,我们有一个假的Scapy指导客户端和一个监听服务器。通过客户端,我们将一系列TCP数据包发送到服务器并检查响应。服务器只接受连接并且不对它们执行任何操作。目的是获得一个简单但更具体的服务器行为模型。我们从模型中忽略/忽略复杂性,例如重传,窗口甚至数据交换。

在Windows 8上分析监听服务器的行为时,我们得到了一个非常好的模型。 然而,在Ubuntu上进行试验时,我们遇到了非确定性行为,至少对我来说很难解释。我在这里附上了wireshark日志的图片,其中包含几个"运行"类似的输入包。每次运行都是通过每次运行增加的端口执行的。 Wireshark capture 奇怪的情况遵循以下模式:

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,或者不发送任何内容。此行为是否由配置参数引起?在我们的设置中,我们使用默认设置。

BTW,简单的服务器代码:

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),       任何不可接受的段(窗口序列号或       不易察觉的确认号码)必须只引出一个空的       包含当前发送序列号的确认段       以及表示预期的下一个序列号的确认       被接收,并且连接保持相同状态。

你们有些人可以对此有所了解吗?协议实现是否符合标准,或者是否存在一定程度的不合规。我猜其中一些是不可避免的,因为标准有时未能指定时间限制,但在这里我们讨论的是控制流程中的不合规。

显然我有可能做错了。 :)

保罗,谢谢。

2 个答案:

答案 0 :(得分:1)

您的服务器是用Java编写的吗?我猜您观察到的“非确定性”是由于GC定时,如果您明确地致电Socket#close()或等待InputStream#read(),可能会消失。

答案 1 :(得分:0)

对任何有兴趣的人,我估计我设法追查“问题”。这是一个小规模的不符合规范,应该修复。如果您检查处理收到的细分受众群数量的代码(可用here),则会检查确认号码的可接受性,如rfc 793rfc 5961中所述。

基于构建于793的rfc 5961,只有在((SND.UNA-MAX.SND.WND)&lt; = SEG.ACK&lt; = SND.NXT)内时,ack编号才可接受。在所有其他情况下,ack编号被认为是不可接受的,应该发出ACK。

在代码本身中,仅针对落入区间的段((SND.UNA-(2 ^ 31-1))&lt; = SEG.ACK&lt; SND.UNA - MAX.SND.WND发出ACK )。如果该段在((SND.NXT + 1&lt; = SEG.ACK&lt; = SND.UNA-2 ^ 31)内,则它们丢弃该段而不发回ACK,即使在这种情况下该段也具有无效的确认号码。发布以下代码的片段。干杯。

 /* If the ack is older than previous acks
 * then we can probably ignore it.
 */
if (before(ack, prior_snd_una)) {
        /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
        if (before(ack, prior_snd_una - tp->max_window)) {
                tcp_send_challenge_ack(sk);
                return -1;
        }
        goto old_ack;
}

/* If the ack includes data we haven't sent yet, discard
 * this segment (RFC793 Section 3.9).
 */
if (after(ack, tp->snd_nxt))
        goto invalid_ack;