using launchd to create "on demand" ssh tunnel

Hello,

I've setup 2 LaunchAgents in my ~/Library/LaunchAgents/ directory, in order to provide 2 apps with an ssh tunnel connectivity "on demand".

One of the plist is like this :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Debug</key>
<false/>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>my.ssh.tunnel</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/ssh</string>
<string>-l</string>
<string>mylogin</string>
<string>-N</string>
<string>-L</string>
<string>port:final-server:port</string>
<string>mylogin@ssh-gateway</string>
</array>
<key>Sockets</key>
<dict>
<key>Listeners</key>
<dict>
<key>Bonjour</key>
<false/>
<key>SockServiceName</key>
<string>port</string>
<key>SockType</key>
<string>stream</string>
</dict>
</dict>
<key>StandardErrorPath</key>
<string>/tmp/mytunnel.err</string>
<key>StandardOutPath</key>
<string>/tmp/mytunnel.out</string>
<key>inetdCompatibility</key>
<dict>
<key>Wait</key>
<false/>
</dict>
<key>onDemand</key>
<true/>
</dict>
</plist>


When I launch the application that makes a tcp request on localhost:port, the tunnel is created, this part is OK. But, the application is unable to use it. I have to quit and restart it so that it can use the ssh tunnel.

Any idea why it behaves like this ? Any workaround ?



PowerMac G5 2*2GHz Mac OS X (10.4.6)

Posted on May 2, 2006 2:23 PM

Reply
5 replies

May 3, 2006 10:44 PM in response to Nils C. Anderson

Well, there is definitely a race condition here, and there is no particular error message. The race condition is different from the one occurring if I don't use launchd to open the tunnel and do it by hand. By creating the tunnel by hand, and launching my app too soon (ie. before the tunnel is created) I would receive an error like "unable to connect to localhost blahblah...". But off course, the same tunnel, created manually works great if I wait 2 seconds before launching my app.
With launchd, the tunnel appears to be always open because launchd "register" the local port as open (can see it in netstat) exactly like (x)inetd would do. So, the local part of the tunnel always exists, and the app gets fooled : it hangs, waiting for the remote connexion (at the other end of the tunnel) to occur.

I can't see any workaround, it's very frustrating. How can I use "on demand" tunnel creation, if "on demand" is too late or too slow ? 🙂

May 4, 2006 5:16 AM in response to Patrick Proniewski

another argument for ssh.

-o TCPKeepAlive


have you considered putting a wrapper script around you application, that does a check to see if the port is still open on the remote side? On way that he may be able to do this is by using telnet.

echo "^]quit" | telnet localhost <forwarded portnumber>

then parse to output, to determine if it succeeded or failed. and based on
that either start your application. or exit with a meaningful error message.

just my 2 cents worth of thought on this one.

Andy

May 4, 2006 5:47 AM in response to Nils C. Anderson

In fact, the idea of a wrapper script is not very appealing to me. The apps I launch use GUI. I could design an Applescript to "init" the tunnel then launch the true application, but I find it quite complicated and very unsatisfactory.

Your telnet command succeed in activating the launchd item, but it returns nothing :

$ echo "^]quit" | telnet localhost 1190
Trying ::1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
$

then, a `ps` shows the launchproxy process while it's opening the tunnel. This steps last for few seconds, the tunnel seems to be unavailable while launchproxy runs (in fact, launchproxy seems to run until the tunnel is fully established).

The TCPKeepAlive option is not interesting in my context, I've monitored the ssh tunnel, once it's established, it won't close, even if the application supposed to be using it is not launched.

I think my problem has no elegant solution. Such a solution could be for launchd/launchproxy to store the application queries, and to feed them into the tunnel once it is open. So, the app would just hang waiting for the tunnel to be fully established, and would get it's response after that. For now, the application hangs for ever. I have to force it to reissue it's network request so that it can reach the remote end of the tunnel.

May 20, 2006 2:08 AM in response to Patrick Proniewski

After some extensive research, it appears that it's impossible to create an on-demand ssh tunnel that will be able to catch the initial connection attempt.

The best way to achieve a similar result is to create on-demand ssh connection (not true ssh tunnel), and to issue a remote connection with `nc` (for example). Then everything you feed into the local end of your ssh connection goes thru the ssh socket, and is handled by `nc` on the remote end.

details in french on my blog : http://www.patpro.net/blog/index.php/2006/05/12/30-tunnel-ssh-a-la-demande-grace -a-launchd

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

using launchd to create "on demand" ssh tunnel

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.