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 am doing a permanent port forwarding via SSH. It is basically

while true; do
        ssh <somewhere> \
                -R <dst-port>:localhost:<src-port> \
                -N -n -o ExitOnForwardFailure=yes
        sleep 10
done

However, that is not very reliable. Sometimes, the port is not forwarded at all (I'm not sure if the connection is correctly alive but I can see the process on the client and it is running already for several hours), sometimes the connection is surely not alive anymore (because the network interface is down) but it takes very long (sometimes up to 30-60 minutes) to timeout.

How can I make that more reliable? I want to have a timeout of maybe a minute.


I just found this very related/similar question. However, the first answer indicates that ExitOnForwardFailure should solve it but I already have that and it does not (I can see right now the running ssh process with this option but the port is not forwarded).

share|improve this question
add comment

4 Answers

I use autossh like this on my work machine to setup for remote web development:

autossh -M0 -N -R \*:8080:localhost:80 -R \*:5051:localhost:22 home

autossh is a program that keeps restarting ssh if it crashes or stops for any reason other than "kill -9". The above command sets up two tunnels: one for forwarding port 80 on my work machine to 8080 on my home machine, the other tunnels the ssh server on my work machine to my home machine. The * in front of the port makes this work with any hostname, not just localhost. You might need to set "GatewayPorts yes" on your sshd_config for that to work though. I have hosts in ~/.ssh/config and /etc/hosts on my home machine to make this even more transparent. For other systems it's necessary to use ProxyCommand (http://sshmenu.sourceforge.net/articles/transparent-mulithop.html), but I don't have the host I use this command with powered on at the moment to grab it.

~/.ssh/config:

Host work
    hostname localhost
    port 5051

Then it's just

autossh -M0 -t home 'ssh work'

from any host to connect.

share|improve this answer
    
I read already about autossh before. However, I still have exactly the same problems as before. The connection still dies but autossh doesn't recognize it. –  Albert Aug 9 '12 at 20:25
add comment

SSH has a built in alive ping mechanism, so there is no need for hacky traffic-generating loops.

I put these in the SSH client config file:

ServerAliveInterval = 60
ServerAliveCountMax = 3

Alternatively, these options can be passed on the ssh command line via -o.

share|improve this answer
add comment

You could try changing your SSH command to:

ssh SOMEWHERE -R DSTPORT:localhost:SRCPORT -n -o ExitOnForwardFailure=yes \
    "while true; do echo ping; sleep 10; done" >/dev/null

This causes a small amount of data to be sent over the TCP connection every 10 seconds (feel free to change that period). That may be sufficient to keep the connection alive.

share|improve this answer
    
Have you actually tried that? I was thinking about some similar hack, though I couldn't really believe that there would be no timeout otherwise, so I haven't even tried yet. –  Albert Aug 8 '12 at 2:34
    
Yes, I've used that trick to positive effect. –  Fran Aug 8 '12 at 15:02
    
I tried it now. It doesn't work, the connection still dies silently and it doesn't recognize it. –  Albert Aug 10 '12 at 10:10
    
Then something other than a TCP timeout is causing the connection to fail. If you SSH into the machine normally, and run that while loop from the shell prompt, will it still disconnect? If so, you have a network problem. –  Fran Aug 10 '12 at 13:46
    
How should the client now if the server is not sending anything anymore that the connection has died? I have now made a slightly different variant where the client is constantly sending something (and the SSH protocol requires to get some form of ack), so if that fails at some point, the client knows that the connection has died. See my own answer. –  Albert Aug 13 '12 at 3:19
show 4 more comments
up vote 0 down vote accepted

This version sends frequently some data to the server. If the connection has died, the pipe should break sooner or later.

while true; do
        { while true; do echo echo ping; sleep 10; done } | \
        ssh <somewhere> \
                -R <something> \
                -o ExitOnForwardFailure=yes \
                >/dev/null
        sleep 10
done
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.