SSH port forwarding is so useful that sometimes you want to daemonize it, to create encrypted tunnels that never go away. But it’s not trivial to do this. Fortunately it is possible with a little fiddling, and I did it using monit.
I have two servers, let’s call them A and B, and I want to connect via ssh from A to B all the time, reconnecting as needed to deal with network problems, reboots, or other reasons why the connection might drop. A program called autossh does most of this, but doesn’t handle reboots. So since I already have monit set up to watch other daemons and keep them from going crazy, I set up a monit configuration to manage autossh. All of this runs on server A; server B just has sshd and a mail server that’s going to try to deliver mail to localhost:2525 to get mail to server A.
The monit configuration stanza (in monitrc) looks like this:
1 2 3 4 5 6 |
check process mailtunnel with pidfile /var/run/autossh.pid start program = "/root/start_mailtunnel.sh" stop program = "/root/stop_mailtunnel.sh" if changed pid then alert if failed host localhost port 2525 protocol smtp with timeout 30 seconds then alert if 3 restarts within 5 cycles then timeout |
start_mailtunnel.sh looks like this:
1 2 3 |
#!/bin/sh export AUTOSSH_PIDFILE=/var/run/autossh.pid /usr/bin/autossh -N mailtunnel & |
And that -N is the key to making ssh happily connect and not run a remote shell, which would want a tty on stdin. That’s how you tell it to just be a port-forwarding connection.
The ssh mailtunnel config just has some port forwarding rules, and “ExitOnForwardFailure yes”.
Finally, stop_mailtunnel.sh looks like this:
1 2 |
#!/bin/sh test -e /var/run/autossh.pid && kill `cat /var/run/autossh.pid` |
Is this technique intended to guard against the server running autossh rebooting, or the server that is at the other end of the tunnel rebooting?
It looks useful, but I’m not clear how it should be applied. In a test, when the remote server is rebooted, autossh seemed to reestablish the connection. Was this luck or is that what you’d expect?
Autossh will take care of re-establishing an ssh connection to a remote server. Monit is useful on the same host as autossh to make sure that autossh is running, such as after a local reboot.
It’s also useful to have monit alert you when autossh repeatedly fails to establish a connection, as I showed above. So although you could just wrap autossh as an an rc service, I think it’s better to actually use monit (or some similar service monitoring daemon) instead.
Thanks for the article, that saved me some RTFM time :-)