51

Related question: initiate ssh connection from server to client

Answer from there helped me a lot, this command does what I need:

ssh -R 2225:localhost:22 loginOfServerWithPublicIP@publicIP

So I wrote the script to reconnect all the time:

 #!/bin/bash

 while true; do
    echo "try to connect..."
    ssh -o ServerAliveInterval=240 -R 2225:localhost:22 user@host
    echo "restarting in 5 seconds.."
    sleep 5
 done

And added it to the /etc/crontab. But I found out that works if only I execute it "by hand" from shell, but if it is called by cron, ssh connects and immediately finishes. (so, the script above reconnects all the time)

From man ssh, I found that for background connections I should call it with -n key, but it didn't help. Then, I just looked around for similar scripts and I found that it works if I call tail -f something, i.e. some "neverending" command, so I just created empty file /tmp/dummy_file and now my ssh command looks like this:

ssh -o ServerAliveInterval=240 -R 2225:localhost:22 -n user@host tail -f /tmp/dummy_file

It works now! But, this solution seems a bit ugly, plus I don't really understand actual reasons of that behavior. Just by chance, I tried to call bash instead of tail -f (bash seems to me "neverending" command, too), but it doesn't work.

So, could anyone please explain this behavior, and what is the correct way to create background ssh connection to keep reverse ssh tunnel up?

Dmitry Frank
  • 2,738
  • what about using & at the end of your ssh command: ssh -o ServerAliveInterval=240 -R 2225:localhost:22 user@host & – Nidal May 31 '14 at 16:36
  • But then my while loop will run again and again, starting new background ssh connection every 5 seconds, right? This isn't what I need. – Dmitry Frank May 31 '14 at 18:57

3 Answers3

48

It sounds like you want the -N option to ssh.

 -N      Do not execute a remote command.  This is useful for just forwarding ports
         (protocol version 2 only).
phemmer
  • 71,831
23

I would strongly suggest you consider autossh. It has certain heuristics that will allow it to determine if connection loss is the underlying reason and will lower the frequency of reconnection attempts. In addition it monitors the connection using extra tunnels, which makes it highly useful for scenarios like the one you are asking about.

If you are on Ubuntu, for example, you can do a web search for autossh upstart to find some useful examples on how to configure Ubuntu so that the tunnel is kept up in a persistent fashion.

I am using this to keep a tunneled connection open to my server at all times for certain services.

0xC0000022L
  • 16,593
  • I actually tried autossh, I've read this article: http://goo.gl/jVuuSR , but it only worked for me if I have Internet connection right away on system boot; but if the connection is established later, it didn't work. Not sure, maybe I did something wrong, but even in this article author has sleep 10 in his /etc/rc.local, in order to be sure internet connection is already ready when autossh is called. – Dmitry Frank May 31 '14 at 18:04
  • 2
    @DmitryFrank: kind of unfair to not mention that in your question, if you've tried. I still recommend it. With upstart and other init replacements you can tie the starting of the tunnel to one or more network devices being up. The best of the solutions (IMO) on the web is this one: http://erik.torgesta.com/tag/ssh-upstart/ ... and no sleep 10 won't help a thing in some edge cases anyway. – 0xC0000022L May 31 '14 at 18:10
  • I'm sorry about not mentioning that, to be honest when it didn't work for me I decided to do that just "by hand" and completely forgot about autossh. Thanks for ssh-upstart, I'll take a look at it! – Dmitry Frank May 31 '14 at 18:51
  • late to the party but I wanted to add I could not reliably get autossh to maintain a reverse tunnel. if the reverse tunnel failed for some reason autossh wouldnt notice and wouldnt rebuild the connection. I need multiple tunnels from multiple servers and this complicates matters – DeveloperChris Mar 16 '16 at 00:45
  • @DeveloperChris: Well, I am running exactly this scenario - and reliably. Unless the remote server literally goes down and you'd need to switch it back on, the tunnel always gets reestablished. Perhaps you should write your own question and provide details. Certainly this can be done. I have used this to work around VPN problems for months. – 0xC0000022L Mar 16 '16 at 13:43
  • Using autossh was doubly complicated by trying to get multiple tunnels to reliably start using systemd. I gave up. I have resolved the issue by using bacula's "run before job" command to create the tunnels and "after job run" to tear them down again. it seems more reliable... – DeveloperChris Mar 17 '16 at 00:25
  • @DeveloperChris: wasn't systemd conceived to make things easier? :) ... well if your workaround works for you, I won't argue. Just saying that I got this working perfectly fine and reliably with multiple tunnels from multiple servers using modern OpenSSH and autossh as shipped with Ubuntu 14.04. – 0xC0000022L Mar 17 '16 at 07:57
15

I'll second @0xC0000022L's suggestion and use autossh as well. I use it to maintain a SSH connection from my laptop as I take it from place to place and it just works. I use this connection to tunnel back ports 25 and 2143 for access to my personal SMTP and IMAP servers.

Here's the script that I use:

$ more /home/saml/bin/autossh_mail.sh
#!/bin/bash

autossh -M 0 -f -N -L 2025:localhost:25 -L 2143:localhost:143 sam@imap-o

I then maintain a Host entry in my $HOME/.ssh/config file for host imap-o.

$ more $HOME/.ssh/config
ServerAliveInterval 15
ForwardX11 yes
ForwardAgent yes
ForwardX11Trusted yes

GatewayPorts yes

Host *
ControlMaster auto
ControlPath ~/.ssh/master-%r@%h:%p
IdentityFile ~/.ssh/id_dsa

Host imap-o
    User sam
    ProxyCommand ssh sam@mygw.mydom.com nc `echo %h|sed 's/-o//'` %p

The autossh_mail.sh script is run as part of my desktop when I log in. You can access it via gnome-session-properties.

       ss #1

                                          ss #2

slm
  • 369,824