Home » Questions » Computers [ Ask a new question ]

How to reliably keep an SSH tunnel open?

How to reliably keep an SSH tunnel open?

I use an SSH tunnel from work to go around various idotic firewalls (it's ok with my boss :)). The problem is, after a while the ssh connection usually hangs, and the tunnel is broken.

Asked by: Guest | Views: 310
Total answers/comments: 5
bert [Entry]

"Sounds like you need autossh. This will monitor an ssh tunnel and restart it as needed. We've used it for a couple of years and it seems to work well.

autossh -M 20000 -f -N your_public_server -R 1234:localhost:22 -C

More details on the -M parameter here"
bert [Entry]

"I've used the following Bash script to keep spawning new ssh tunnels when the previous one dies. Using a script is handy when you don't want or can't install additional packages or use compiler.

while true
do
ssh <ssh_options> [user@]hostname
sleep 15
done

Note that this requires a keyfile to establish the connection automatically but that is the case with autossh, too."
bert [Entry]

"It sure looks to me that you're all misinterpreting ServerAliveCountMax. As I understand the docs, it is the number of server alive messages which can go unanswered without the connection being terminated. So in cases like we're discussing here, setting it to a high value will just ensure that a hung connection will not be detected and terminated!

Simply setting ServerAliveInterval should be sufficient to solve the problem with a firewall forgetting about the connection, and leaving ServerAliveCountMax low will allow the originating end to notice the failure and terminate if the connection fails anyway.

What you want is, 1) for the connection to stay open permanently under normal circumstances, 2) for connection failure to be detected and the originating side to exit on failure, and 3) for the ssh command to be re-issued every time it exits (how you do that is very platform dependent, the ""while true"" script suggested by Jawa is one way, on OS X I actually set up a launchd item)."
"It sure looks to me that you're all misinterpreting ServerAliveCountMax. As I understand the docs, it is the number of server alive messages which can go unanswered without the connection being terminated. So in cases like we're discussing here, setting it to a high value will just ensure that a hung connection will not be detected and terminated!

Simply setting ServerAliveInterval should be sufficient to solve the problem with a firewall forgetting about the connection, and leaving ServerAliveCountMax low will allow the originating end to notice the failure and terminate if the connection fails anyway.

What you want is, 1) for the connection to stay open permanently under normal circumstances, 2) for connection failure to be detected and the originating side to exit on failure, and 3) for the ssh command to be re-issued every time it exits (how you do that is very platform dependent, the ""while true"" script suggested by Jawa is one way, on OS X I actually set up a launchd item)."
bert [Entry]

"Always use ServerAliveInterval SSH option in case the tunnel issues are generated by expired NAT sessions.

Always use a respawning method in case the connectivity goes down entirely, you have at least three options here:

autossh program
bash script (while true do ssh ...; sleep 5; done) do not remove the sleep command, ssh may fail quickly and you'll respawn too many processes
/etc/inittab, to have access to a box shipped and installed in another country, behind NAT, without port forwarding to the box, you can configure it to create an ssh tunnel back to you:

tun1:2345:respawn:/usr/bin/ssh -i /path/to/rsaKey -f -N -o ""ServerAliveInterval 180"" -R 55002:localhost:22 user@publicip 'sleep 365d'

upstart script on Ubuntu, where /etc/inittab is not available:

start on net-device-up IFACE=eth0
stop on runlevel [01S6]
respawn
respawn limit 180 900
exec ssh -i /path/to/rsaKey -N -o ""ServerAliveInterval 180"" -R 55002:localhost:22 user@publicip
post-stop script
sleep 5
end script

or always use both methods."
bert [Entry]

"I solved this problem with this:

Edit

~/.ssh/config

And add

ServerAliveInterval 15
ServerAliveCountMax 4

According to man page for ssh_config:

ServerAliveCountMax
Sets the number of server alive messages (see below) which may be
sent without ssh(1) receiving any messages back from the server.
If this threshold is reached while server alive messages are
being sent, ssh will disconnect from the server, terminating the
session. It is important to note that the use of server alive
messages is very different from TCPKeepAlive (below). The server
alive messages are sent through the encrypted channel and there‐
fore will not be spoofable. The TCP keepalive option enabled by
TCPKeepAlive is spoofable. The server alive mechanism is valu‐
able when the client or server depend on knowing when a connec‐
tion has become inactive.

The default value is 3. If, for example, ServerAliveInterval
(see below) is set to 15 and ServerAliveCountMax is left at the
default, if the server becomes unresponsive, ssh will disconnect
after approximately 45 seconds. This option applies to protocol
version 2 only.

ServerAliveInterval
Sets a timeout interval in seconds after which if no data has
been received from the server, ssh(1) will send a message through
the encrypted channel to request a response from the server. The
default is 0, indicating that these messages will not be sent to
the server. This option applies to protocol version 2 only."