MrRoboto: Part 1— Automatic tunnelling on a Mac

After a hard disk failure that finally rendered MacBook Air #2 unable to boot (or even formatted so as to boot), I’ve set up its replacement MacBook Air, MrRoboto, to be as “automatic” as possible. Things should “just work”. This particular blog post is about automatic tunnelling. If you don’t know what ssh or a local/remote tunnel is, this post is not for you. It’s also aimed at Mac users.

Maybe you need to download some files from a computer behind a firewall or start a remote desktop session on a computer. I use it primarily to tunnel e-mails through the University of Toronto Department of Computer Science’s firewalled network; this saves me having to switch between my ISP’s e-mail server and the CSLab server in my mail client (and allows me to send mail when on other networks) without worrying about where I am. I used to manually start an SSH tunnel (one step up would be putting it in a script that could be executed). Now, things are much simpler thanks to launchctl and automatic login with ssh. Instead, if I connect to port 8025 on my own computer, it automatically creates a brand new tunnel to port 25 on a remote machine.

I have a file called ~/Library/LaunchAgents/smtpTunnel.plist containing the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>edu.toronto.cs.lungj.smtpTunnel</string>
        <key>ServiceDescription</key>
        <string>Automatically create a tunnel for SMTP connections</string>
        <key>ProgramArguments</key>
        <array>
            <string>/usr/bin/ssh</string>
            <string>-T</string>
            <string>-L</string>
            <string>8025:mail.cs.toronto.edu:25</string>
            <string>cs</string>
            <string>nc mail.cs.toronto.edu 25</string>
        </array>
        <key>inetdCompatibility</key>
        <dict>
            <key>Wait</key>
            <false/>
        </dict>
        <key>Sockets</key>
        <dict>
            <key>Listeners</key>
            <array>
                <dict>
                    <key>SockServiceName</key>
                    <string>8025</string>
                    <key>SockType</key>
                    <string>stream</string>
                    <key>SockFamily</key>
                    <string>IPv4</string>
                </dict>
            </array>
        </dict>
    </dict>
</plist>

In SockServiceName, I specify that whenever a connection on my computer is made to port 8025, the program specified in ProgramArguments should be invoked to handle the connection.

/usr/bin/ssh -T -L 8025:mail.cs.toronto.edu:25 cs nc mail.cs.toronto.edu 25

This says to start an SSH tunnel without allocating a TTY (-T) from port 8025 on the local machine (-L) to port 25 of mail.cs.toronto.edu via the computer named cs (this is my shortcut name to apps0.cs.toronto.edu) and then copy all the data sent back and forth through this tunnel using the net cat (nc) command to mail.cs.toronto.edu 25.

This file needs to be loaded using launchctl load filename. If you make changes, you’ll need to unload the file before attempting to load it again. If the files lives in your ~/Library/LaunchAgents directory, the changes will be persistent across reboots.

Leave a Reply

Your email address will not be published. Required fields are marked *