Linux tcp connect timeout

linux connect() timeout and syncookies

In the man page for connect(2) [version for Linux 2.6.7 2004-06-23], the section describing ETIMEDOUT says:

ETIMEDOUT Timeout while attempting connection. The server may be too busy to accept new connections. Note that for IP sockets the timeout may be very long when syncookies are enabled on the server.

The same remark appears at least also in release 3.35 of the Linux man-pages project. I don’t follow how enabling syncookies on the server cause the client to have potentially longer timeouts.

A syncookie is cryptographically encoded directly in the server’s SYN+ACK reply to the client’s SYN . It may take some extra time for the server to verify a syncookie, which would delay processing of the final ACK that establishes the connection. Also, the use of syncookies disables the use of TCP options, that might have otherwise enhanced the performance of the connection. See this page.

Thanks @RemyLebeau. As I understand it, from the client’s perspective a connect() finishes upon receiving the SYN+ACK, so the final ACK in the handshake wouldn’t even enter the latency picture on the connecting side.

Then the only possibility would be if the generation of the syncookie is delaying the SYN+ACK from being sent. According to the page I linked you to: «the server is limited to only 8 unique MSS values, as that is all that can be encoded in 3 bits.» Maybe if the server has a lot of connections, or at least a lot of pending connections, it may take longer for a unique MSS to become available for the connection being SYN+ACK ed? Or maybe the cryptography takes a long time to create a new hash? That seems like the only candidates.

My interpretation of that part of the article is that the restriction to 8 unique MSS values doesn’t mean that it is a limited resource like a semaphore. It seems to me, it means it has a limited universe of values to choose from, but it can repeat the same MSS.

2 Answers 2

My only explanation is that this is a bug in the man pages and that is not what the author meant to say. The source to handle connection timeouts in Linux is relatively simple and can been seen here in the retransmits_timed_out() and tcp_write_timeout() functions.

Читайте также:  Linux convert partition to gpt

tcp_retransmit_timer() is called based on the normal exponential backoff timer (i.e. a syn is retransmitted just like any other packet, there is no special handling). tcp_retransmit_timer() calls tcp_write_timeout() (line 396) which, if the socket is in the SYN_SENT or SYN_RECV state, sets a variable retry_until to either icsk_syn_retries (if it has been set using setsockopt()) or the sysctl tcp_syn_retries value. It also sets syn_set = true. These two are passed on the retransmits_timed_out(), which checks to see if there have been retry_until attempts to send the syn. If so it returns true and tcp_write_err() is called, which returns the ETIMEDOUT error (line 37).

In the case that syn_set is true, retransmits_timed_out uses TCP_TIMEOUT_INIT as the base timeout for its calculations, which is a constant (defined here). So even if the presence of syncookies somehow magically changed the retransmit timer, it couldn’t change how retransmits_timed_out() calculates if enough time has passed to warrant returning ETIMEDOUT. It could only possibly change the number of retransmits, but icsk_syn_retries is only set here when handling a setsockopt, and sysctl_tcp_syn_retries is only set through the sysctl mechanism.

So I don’t see any way that syncookies on the server could have any effect on the connect() timeout. Which, as you point out, makes sense. How could the client know that the server was using syncookies? Especially before even receiving a syn|ack, which would complete connect().

I’m guessing the author was trying to convey that the timeout should be set relatively high, because with the advent of syncookies a server that is totally backlogged can still get around to successfully making a connection, but it might take some time. (Note that this line dates back to before the current man-pages repo was setup, as it was brought in with the initial import of man-pages 1.70 in 2004).

Источник

How to decrease TCP connect() system call timeout?

In command below I enable file /dev/tcp/10.10.10.1/80 both for reading and writing and associate it with file descriptor 3:

$ time exec 3<>/dev/tcp/10.10.10.1/80 bash: connect: Operation timed out bash: /dev/tcp/10.10.10.1/80: Operation timed out real 1m15.151s user 0m0.000s sys 0m0.000s 

This automatically tries to perform TCP three-way handshake. If 10.10.10.1 is not reachable as in example above, then connect system call tries to connect for 75 seconds. Is this 75 second timeout determined by bash ? Or is this system default? Last but not least, is there a way to decrease this timeout value?

Читайте также:  Версия линукс через консоль

Stack Overflow is a site for programming and development questions. This question appears to be off-topic because it is not about programming or development. See What topics can I ask about here in the Help Center. Perhaps Super User or Unix & Linux Stack Exchange would be a better place to ask.

3 Answers 3

It’s not possible in Bash without modifying the source as already mentioned, although here is the workaround by using timeout command, e.g.:

Using this syntax, the timeout command will kill the process after the given time.

See: timeout —help for more options.

This should be the accepted answer, instead changing the values (not recommended) system widely on /proc/sys/net/ipv4/tcp_keepalive_time is god to know that sending the signal to the parent of the process that open the socket will close it. I was wondering why this works and $ timeout 1

It is determined by TCP. It can be decreased on a per-socket basis by application code.

NB The timeout only takes effect if there is no response at all. If there is a connection refusal, the error occurs immediately.

I see. Is it also possible to decrease this in bash ? I guess not.. Probably only in C , python and other programming languages?

No: there is no way of changing timeout by using /dev/tcp/

Yes, you could change default timeout for TCP connection in any programming language.

But, bash is not a programming language!

You could have a look into source code (see: Bash Homepage), you may find lib/sh/netopen.c file where you could read in _netopen4 function:

s = socket(AF_INET, (typ == 't') ? SOCK_STREAM : SOCK_DGRAM, 0); 

You could read this file carefully, there are no consideration of connection timeout.

Without patching bash sources, there is no way of changing connection timeout by a bash script.

Simple HTTP client using netcat (near pure bash)

There is a little sample HTTP client written in pure bash, but using netcat :

#!/bin/bash tmpfile=$(mktemp -p $HOME .netbash-XXXXXX) exec 7> >(nc -w 3 -q 0 stackoverflow.com 80 >$tmpfile) exec 6&7 "GET %s HTTP/1.0\r\nHost: stackoverflow.com\r\n\r\n" \ /questions/24317341/how-to-decrease-tcp-connect-system-call-timeout timeout=100; while ! read -t .001 -u 6 status ; do read -t .001 foo;done echo STATUS: $status [ "$status" ] && [ -z "$" ] || exit 1 echo HEADER: while read -u 6 -a head && [ "$" ]; do printf "%-20s : %s\n" $ "$" done echo TITLE: sed '//s/<[^>]*>//gp;d' &- exec 6 
STATUS: HTTP/1.1 200 OK HEADER: Cache-Control : private Content-Type : text/html; charset=utf-8 X-Frame-Options : SAMEORIGIN X-Request-Guid : 46d55dc9-f7fe-425f-a560-fc49d885a5e5 Content-Length : 91642 Accept-Ranges : bytes Date : Wed, 19 Oct 2016 13:24:35 GMT Via : 1.1 varnish Age : 0 Connection : close X-Served-By : cache-fra1243-FRA X-Cache : MISS X-Cache-Hits : 0 X-Timer : S1476883475.343528,VS0,VE100 X-DNS-Prefetch-Control : off Set-Cookie : prov=ff1129e3-7de5-9375-58ee-5f739eb73449; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly TITLE: bash - How to decrease TCP connect() system call timeout? - Stack Overflow 

We create first a temporary file (under private directory for security reason), bind and delete before using them.

$ tmpfile=$(mktemp -p $HOME .netbash-XXXXXX) $ exec 7> >(nc -w 3 -q 0 stackoverflow.com 80 >$tmpfile) $ exec 6 /dev/pts/1 lrwx------ 1 user user 64 Oct 19 15:20 1 -> /dev/pts/1 lrwx------ 1 user user 64 Oct 19 15:20 2 -> /dev/pts/1 lr-x------ 1 user user 64 Oct 19 15:20 3 -> /proc/30237/fd lr-x------ 1 user user 64 Oct 19 15:20 6 -> /home/user/.netbash-rKvpZW (deleted) l-wx------ 1 user user 64 Oct 19 15:20 7 -> pipe:[2097453] $ echo GET / HTTP/1.0$'\r\n\r' >&7 $ read -u 6 foo $ echo $foo HTTP/1.1 500 Domain Not Found $ exec 7>&- $ exec 6>&- 

Источник

Linux TCP Connection timeout

I observe the TCP timeout from server to client. When TCP Three-way Handshake finished, and then the client does not anything for a long time. How many times will timeout TCP sessions? I consult the RFC 793 document, 3.8 Interfaces:

The timeout, if present, permits the caller to set up a timeout for all data submitted to TCP. If data is not successfully delivered to the destination within the timeout period, the TCP will abort the connection.
The present global default is five minutes

enter image description here

The following is the captured packet connection, More than 10 minutes have passed and there is no TCP disconnection. Am I misunderstanding somewhere? OS: Ubuntu 20 The following is my test code. Client Code:

#include #include #include int main(int argc, char *argv[]) < int socket_desc; struct sockaddr_in server; socket_desc = socket(AF_INET, SOCK_STREAM, 0); if(socket_desc == -1)< printf("Socket failed\n"); >server.sin_addr.s_addr = inet_addr("192.168.88.88"); server.sin_family = AF_INET; server.sin_port = htons(8888); if(connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) <0)< printf("Connect failed\n"); >else < printf("Connected\n"); while(0); // When connected, do not anything. return 0; >
#include #include #include int main(int argc, char *argv[]) < int socket_desc, new_socket, c; struct sockaddr_in server; socket_desc = socket(AF_INET, SOCK_STREAM, 0); if(socket_desc == -1)< printf("Socket failed\n"); >server.sin_addr.s_addr = INADDR_ANY; server.sin_family = AF_INET; server.sin_port = htons(8888); if(bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) <0)< printf("bind failed\n"); >listen(socket_desc, 5); c = sizeof(struct sockaddr_in); new_socket = accept(socket_desc, (struct sockaddr *) &client, (socklen_t *) &c); if (new_socket < 0)< printf("Accept failed\n"); >else < printf("Accept\n"); while(1); // When accept , do not anything. >return 0; > 

Источник

Оцените статью
Adblock
detector