防止TCP套接字连接重试

时间:2014-03-14 22:55:31

标签: java sockets tcp language-agnostic

如何阻止TCP进行多个套接字连接尝试?

背景

我试图粗略估计一下客户的往返时间。我必须使用的高级协议无法确定RTT,也没有任何类型的无操作请求/响应流程。所以,我试图直接从较低层获取信息。特别是,我知道客户端将主动拒绝特定端口上的TCP连接尝试。

Me -> Client: SYN
Client -> Me: ACK, RST

代码

  long lStartTime = System.nanoTime() / 1000000;
  long lEndTime;

  // Attempt to connect to the remote party.  We don't mind whether this
  // succeeds or fails.
  try
  {
    // Connect to the remote system.
    lSocket.connect(mTarget, MAX_PING_TIME_MS);

    // Record the end time.
    lEndTime = System.nanoTime() / 1000000;

    // Close the socket.
    lSocket.close();
  }
  catch (SocketTimeoutException|IOException lEx)
  {
    lEndTime = System.nanoTime() / 1000000;
  }

  // Calculate the interval.
  lInterval = lEndTime - lStartTime;
  System.out.println("Interval = " + lInterval);

问题

使用Wireshark,我看到对lSocket.connect的调用在放弃之前尝试连接套接字三次(失败) - 显然是任意的尝试间间隔(通常是~300ms)。

Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST

问题

有没有办法让TCP在单个SYN / RST对之后放弃?

我查看了一些Java代码。当AbstractPlainSocketImpl的评论说...

时,我想知道我是不是赢了
/**
 * The workhorse of the connection operation.  Tries several times to
 * establish a connection to the given <host, port>.  If unsuccessful,
 * throws an IOException indicating what went wrong.
 */

......但遗憾的是,没有证据表明该功能或我所查看过的任何其他(非原生)功能都有循环/重试。

这种重试行为实际上来自哪里?它怎么能被控制?

替代

我也可以接受替代方案,但不是......

  • 使用ICMP回应请求(ping)。我知道很多客户都不会回复他们。
  • 使用原始套接字。其中一个平台是Windows,这些天严重限制了使用原始套接字的能力。 (我还认为,如果Linux网络堆栈在尝试使用原始套接字执行TCP的应用程序的交叉攻击中陷入困境,那么它就无济于事。)
  • 使用JNI,除非作为最后的手段。我的代码需要至少使用2种不同的操作系统。

1 个答案:

答案 0 :(得分:7)

TCP连接重试是OS的套接字实现的一个功能。配置这取决于平台。请参阅https://security.stackexchange.com/questions/34607/why-is-the-server-returning-3-syn-ack-packets-during-a-syn-scan,了解这是什么以及为什么会发生这种情况。

在Windows上,您应该能够修改注册表中的重试次数:

与RTT相关的设置也在该文档中详细说明。

在Linux上,链接的安全帖子中接受的答案讨论了如何配置此参数:

  

在Linux系统上,请参阅名为/proc/sys/net/ipv4/tcp_syn_retries的{​​{1}}中的特殊文件:它们包含内核在a上发出SYN(分别为SYN + ACK)的次数给定连接......这就像tcp_synack_retries ...

一样简单

请注意,这是系统范围的设置。

您可以通过读取注册表设置(在Windows上)或读取特殊文件的内容(在Linux上)来读取当前值。

此外,MSDN还有关于Windows上TCP连接RTT的说法:

  

TCP / IP随时间调整重传频率。每个接口的原始传输和第一次重传之间的延迟由echo 3 > tcp_synack_retries条目的值确定。默认情况下,它是三秒钟。每次尝试后,此延迟加倍。在最后一次尝试之后,TCP / IP等待的间隔等于上一次延迟的两倍,然后它放弃连接请求。

顺便说一下,重新:原始套接字 - 是的,你会有一个非常困难的时间。此外,从Windows XP SP2起,Windows won't actually let you specify TCP protocol numbers for raw sockets under any circumstances(请参阅限制)。

另外,请注意:确保TCP连接没有被客户端前面的单独防火墙阻止,否则您最终只能测量到防火墙的往返时间。