Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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.

If I could at least monitor the tunnel automatically, I could restart the tunnel when it hangs, but I haven't even figured a way of doing that.

Bonus points for the one who can tell me how to prevent my ssh connection from hanging, of course!

share|improve this question
add comment

11 Answers

up vote 74 down vote accepted

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.

share|improve this answer
    
+1 for autossh, it does what it says on the tin. I believe part of its functionality also is to send keep-alive style packets to prevent any kind of timeout. –  akent Sep 8 '09 at 13:55
    
this is the way to go. –  Joset Sep 8 '09 at 14:21
    
Awesome! thanks! –  Peltier Sep 8 '09 at 14:28
    
+1 for autossh, I've been looking for something like this for a while now –  Mala Jan 16 '10 at 6:04
11  
Could you put the example tunnel using autossh in the answer? –  shurane Dec 20 '12 at 21:45
add comment

All stateful firewalls forget about a connection after not seeing a packet for that connection for some time (to prevent the state tables from becoming full of connections where both ends died without closing the connection). Most TCP implementations will send a keepalive packet after a long time without hearing from the other side (2 hours is a common value). If, however, there is a stateful firewall which forgets about the connection before the keepalive packets can be sent, a long-lived but idle connection will die.

If that is the case, the solution is to prevent the connection from becoming idle. OpenSSH has an option called ServerAliveInterval which can be used to prevent the connection from being idle for too long (as a bonus, it will detect when the peer died sooner even if the connection is idle).

share|improve this answer
    
The interval specified is in seconds, so you can provide some fine tuning. If your stateful firewall has a 5 minute idle timeout, then 60 or 120 seconds is enough to keep the connection open. It's one of the ways I keep my ssh sessions through my home router open. –  Darren Hall Dec 2 '09 at 21:16
    
Thanks, this helped. But note (from a lower-ranked answer here, superuser.com/a/146641/115515) that if you specify ServerAliveInterval and not ServerAliveCountMax, you may find ssh intentionally disconnecting sooner than you wanted. –  metamatt Jan 26 '12 at 21:54
    
@metamatt, that lower-ranked answer you reference is lower-ranked for good reason: IT IS WRONG. –  Lambart Feb 20 at 0:14
add comment

On your own mac or linux machine configure your ssh keep the server ssh alive every 3 minutes. Open a terminal and go your your invisible .ssh in your home:

cd ~/.ssh/ 

then create a 1 line config file with:

echo "ServerAliveInterval 180" >> config

you should also add:

ServerAliveCountMax xxxx (high number)

the default is 3 so ServerAliveInterval 180 will stop sending after 9 minutes (3 of the 3-minute interval specified by ServerAliveInterval).

share|improve this answer
1  
Note that your command is not recommended if you already have a config file. Using >> for redirection would be a lot better! –  Peltier Mar 18 '11 at 9:34
    
why does ServerAliveInterval 180 give us 6 minutes? intuition makes me try this : 180/60 == 3. So, does ServerAliveInterval work in multiples of 30 secs? –  nemesisfixx Nov 30 '11 at 14:37
    
@mcnemesis: ServerAliveInterval 180 means 3 minutes. ServerAliveCountMax default of 3 means 3 of those intervals, so 9 minutes. –  metamatt Jan 26 '12 at 21:50
1  
I'm voting this answer up because thanks for mentioning ServerAliveCountMax, and what happens if you specify ServerAliveInterval without ServerAliveCountMax. But like the preceding comments, I notice the calculation on "will stop sending after" is wrong, and I think this answer would serve better if it just gave the information on these options, not telling us how to apply them with cd and echo commands. –  metamatt Jan 26 '12 at 21:51
1  
Downvoting because it makes no sense to set ServerAliveCountMax to a "high number". ServerAliveCountMax specifies how many times it will try to send the "keepalive" message before giving up. The default is 3, so with ServerAliveInterval 180, it will stop sending ONLY if the server has NOT RESPONDED after 9 minutes, in which case your connection is probably well and truly dead. –  Lambart Feb 20 at 0:13
add comment

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.

share|improve this answer
    
You should add any reasons that you'd use this script over autossh, or is it just that it's easier this way? –  kyrias Oct 20 '12 at 17:25
    
This wouldn't help if ssh itself freezes, would it? –  nafg Nov 25 '13 at 23:59
add comment

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).

share|improve this answer
add comment

I solved this problem with this:

Edit

~/.ssh/config

And add

ServerAliveInterval 15
ServerAliveCountMax 4
share|improve this answer
    
Every 15 seconds seems pretty often to ping the server. –  Lambart Feb 20 at 0:08
add comment

I've had a need to maintain an SSH-tunnel long-term. My solution was running from a Linux server, and it's just a small C program that respawns ssh using key-based authentication.

I'm not sure about the hanging, but I've had tunnels die due to timeouts.

I would love to provide the code for the respawner, but I can't seem to find it right now.

share|improve this answer
add comment

while there are tools like autossh that helps to restart ssh session... what i find to be really useful is to run the 'screen' command. It allows you to RESUME your ssh sessions even after you disconnect. Especially useful if your connection is not as reliable as it should be.

...don't forget to mark this is the 'correct' answer if it helps you k! ;-)

share|improve this answer
3  
... but the question was about how to keep SSH tunnels open, not just a terminal session. Screen IS great though! –  akent Sep 8 '09 at 14:15
    
I already use screen, but it doesn't solve my problem :-/ Thanks for your answer, though. –  Peltier Sep 8 '09 at 14:15
add comment

A bit of a hack, but I like to use screen to keep this. I currently have a remote forward that has been running for weeks.

Example, starting locally:

screen
ssh -R ......

When the remote forward is applied, and you have a shell on the remote computer:

screen
Ctrl + a + d

You now have an uninterrupted remote forward. The trick is to run screen on both ends

share|improve this answer
add comment

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 -f -N -o "ServerAliveInterval 180" -R 55002:localhost:22 user@publicip 'sleep 365d'
    

or always use both methods.

share|improve this answer
    
+1 for inline option in case you don't want it for all of your SSH connections –  user1146334 Jul 7 at 14:29
add comment

I have had similar problems with my previous ISP. For me it was the same with any tcp connection, visiting websites or sending mail.

The solution was to configure a VPN connection over UDP(I was using OpenVPN). This connection was more tolerant to whatever caused the disconnections. Then you can run any service through this connection.

There can still be issues with the connection but since the tunnel will be more tolerant any ssh session will feel a short holdup rather than being disconnected.

To do this you will need a VPN service online which you can setup on your own server.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.