How can I prevent TCP from making multiple socket connection attempts?
I'm trying to get a rough estimate of the round-trip-time to a client. The high-level protocol I have to work with gives no way to determine the RTT, nor does it have any sort of no-op reqeust/response flow. So, I'm attempting to get information directly from the lower layers. In particular, I know that the client will actively reject TCP connection attempts on a particular port.
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);
Using Wireshark, I see that the call to lSocket.connect
makes three (failed) attempts to connect the socket before giving up - with an apparently arbitrary inter-attempt interval (often ~300ms).
Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST
Is there any way to make TCP give up after a single SYN/RST pair?
I've looked through some of the Java code. I wondered if I was on to a winner when the comment on AbstractPlainSocketImpl
said...
/**
* 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.
*/
...but sadly there's no evidence of looping/retries in that function or any of the other (non-native) functions that I've looked at.
Where does this retry behaviour actually come from? And how can it be controlled?
I may also be open to alternatives, but not...
TCP connect retries are a function of the OS's socket implementation. Configuring this depends on the platform. See https://security.stackexchange.com/questions/34607/why-is-the-server-returning-3-syn-ack-packets-during-a-syn-scan for a description of what this is and why it is happening.
On Windows, you should be able to modify the retry count in the registry:
Settings related to the RTT are detailed in that documentation as well.
On Linux, the accepted answer in the linked Security post talks about how to configure this parameter:
On a Linux system, see the special files in
/proc/sys/net/ipv4/
calledtcp_syn_retries
andtcp_synack_retries
: they contain the number of times the kernel would emit SYN (respectively SYN+ACK) on a given connection ... this is as simple asecho 3 > tcp_synack_retries
...
Note that this is a system-wide setting.
You can read the current values by reading the registry settings (on Windows) or reading the contents of the special files (on Linux).
Also, MSDN has this to say about the TCP connect RTT on Windows:
TCP/IP adjusts the frequency of retransmissions over time. The delay between the original transmission and the first retransmission for each interface is determined by the value of the
TcpInitialRTT
entry. By default, it is three seconds. This delay doubles after each attempt. After the final attempt, TCP/IP waits for an interval equal to double the last delay, and then it abandons the connection request.
By the way, re: raw sockets - Yes, you would have an extremely difficult time. Also, as of Windows XP SP2, Windows won't actually let you specify TCP protocol numbers for raw sockets under any circumstances (see Limitations).
Also, as an aside: Make sure that the TCP connection is not being blocked by a separate firewall in front of the client, otherwise you only end up measuring round trip time to the firewall.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With