防止TCP套接字连接重试

And*_*ose 4 java language-agnostic sockets tcp

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

背景

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

Me -> Client: SYN
Client -> Me: ACK, RST
Run Code Online (Sandbox Code Playgroud)

  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);
Run Code Online (Sandbox Code Playgroud)

问题

使用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
Run Code Online (Sandbox Code Playgroud)

有没有办法让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.
 */
Run Code Online (Sandbox Code Playgroud)

...但遗憾的是,没有证据表明该函数或我所看到的任何其他(非本机)函数存在循环/重试.

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

备择方案

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

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

Jas*_*n C 8

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_retriestcp_synack_retries:它们包含的次数内核将一个给定的连接上发出SYN(分别为SYN + ACK)......这就是这么简单echo 3 > tcp_synack_retries...

请注意,这是一个系统范围的设置.

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

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

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

顺便说一句,重新:原始套接字 - 是的,你将有一个非常困难的时间.此外,从Windows XP SP2开始,Windows 实际上不允许您在任何情况下为原始套接字指定TCP协议号(请参阅限制).

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