Monday, June 7, 2010

ssh Timeouts

Some time back I was encountering annoying timeouts on ssh sessions and came to know some useful details in the process of getting it resolved.



The timeouts are typically caused by NAT firewalls that terminate idle connections to keep their state tables clean and of manageable size. You can work around this by tweaking the ssh configuration such that the session does not go idle even when you are not performing any explicit activity on it. The basic idea is to enable ssh-level keepalives (not to be confused with TCP keepalives aka socket option SO_KEEPALIVE).
There are several ways of doing this and some are listed below.
1) On the client side, set ServerAliveInterval
This can be set in ~/.ssh/config e.g.
Host *
ServerAliveInterval 300

or in PuTTY
Connection -> Sending of null packets to keep session active -> Seconds between keepalives (0 to turn off)
The value e.g. 300 (or 5 mins) should be smaller than the NAT firewall timeout that you are observing (typically 10 mins). Too small a value, of course, implies too many unncessary keepalives and should be avoided. Effectively, the client will send a keepalive message to the server every 5 mins to keep the session alive.
2) On the server side, set ClientAliveInterval
This should be set in /etc/ssh/sshd_config e.g.
ClientAliveInterval 300
The value of 300 (or 5 mins) is based on the same argument as in 1). In this case, it the server that will send a keepalive message to a connected client every 5 mins.
3) Use ssh command line options for per-session control
$ ssh -o ServerAliveInterval=300 ...
Notes :
a) There are associated parameters ServerAliveMaxCount and ClientAliveCountMax which have a default value of 3 and basically specify a retry count.
For example, with a ClientAliveMaxCount of 3, the server will terminate an inactive client session after 300 x 3 seconds only if the client does not respond to 3 successive keepalives sent by the server at gaps of 300 seconds. The defaults need not be changed for our situation.

b) Some shells including bash support a TMOUT environment variable. It "is interpreted as the number of seconds to wait for input after issuing the primary prompt. Bash terminates after waiting for that number of seconds if input does not arrive."
c) ssh supports a KeepAlive parameter. If this is set to yes, the SO_KEEPALIVE option is set for the TCP socket connection opened between the ssh client and server. The various timeouts and retries for TCP keepalives have to be configured for the kernel. Any TCP connection that sets SO_KEEPALIVE will make use of these values. This can also be utilized as a means of avoiding NAT firewall inactivity timeouts but since we have a handy ssh-level way readily available, the latter is easier and more efficient as compared to a per-kernel configuration change that affects the whole TCP/IP stack on the system.

No comments:

Post a Comment