Sunday, February 27, 2011

Setting up a permanent ubuntu SSH tunnel

My home system is behind a router I do not control (yet :). This means port forwarding so I can remotely reach my machine might seem impossible. Or not....
All you really need is a good (trustworthy) friend with his own server, and a little ssh tunneling magic.

Today I'll make a permanent password less (auto)ssh tunnel that binds local port 22 (ssh) to 11122 on a remote machine, so that when i login to the remote machine from anywhere, all i have to do is ssh to port 11122 and voila, i'm on my own supposedly unreachable server.

First of all you need to make sure to be able to do a password less login to machine B (the friends server).
For this you'll need to generate public keyfiles and tell machine B to trust them.

So on your own machine generate the files (while logged in under the user you want to connect to machine B):
When it asks for a passphrase, just hit enter for both times it asks.

This will generate ~/.ssh/id_rsa and ~/.ssh/ If it doesn't your probably running an older version of openssh which still generates id_dsa which is the old form, use ssh-keygen -t rsa in that case.

Now we have to copy the ~/.ssh/ file to the remote machine, which for this exercise is on port 443.
  scp  -P 443 ~/.ssh/

Now login to the remote server, create the .ssh directory (in case it doesn't exist) and make that file trusted, and then delete the transferred public key we'll no longer need.
  ssh -p 443
  mkdir ~/.ssh
  cat ~/ >> ~/.ssh/authorized_keys2
  rm ~/
Now logout from the remote machine, and try to login to it again, this time without password.
After this is working we can setup our permanent tunnel.

Back on your local machine, let's start installing & configuring the permanent tunnel.
  apt-get install autossh
  pico /etc/init.d/ssh_tunnel

and put the following in /etc/init.d/ssh_tunnel:

# Example script to start up tunnel with autossh.
# This script will tunnel 22 from the local host
# to 11122 on the remote host.
autossh -p 443 -2 -fN -M 20000 -R 11122:localhost:22 ${ID}@${HOST}

Then save and exit this file (ctrl-o/x), and make it executable. 
  chmod +x /etc/init.d/ssh_tunnel
Then all we need to this is let it start up when your network starts up, and we're done.
  pico /etc/network/interfaces
Depending on through what interface you make your tunnel, add the following to an eth0 or wlan0 or such:
post-up /etc/init.d/ssh_tunnel

For clarity I'll post my own setup here:
my home setup, where autossh activates on post-up of the wireless
We should now have a permanent tunnel we will activate and test:
  ssh -p 443
  ssh -p 11122 jeroen@localhost
Now you should be tunneling back to your local machine through our port forwarded autossh tunnel. Done!

For debug purposes I'd like to add that I didn't change the default autossh logging path, which means all logging goes to the normal system log at /var/log/syslog.

Of course you can tunnel much more through setup's like these. Play around with it, just make sure your not using ports that might actually be in use. To check which ports are already used on a server, run:
  netstat -plntu    


  1. excellent post, thanks for the effort. can you enlighten a newb as to where shall I put the up script in 11.10? my /etc/network/interfaces file only has lo in it.

  2. figured it out... put it in /etc/networks/if-up.d/

  3. Nice guide! I am using NetworkManager on Ubuntu 11.10, and found that I can just put the script in /etc/network/if-up.d/ and it will get started automatically by the /etc/NetworkManager/dispatcher.d/01ifupdown

  4. Good idea with the "post-up" in the network interface definition file. I wrote a startup script for autossh instead that supports multiple tunnels, etc.


  5. Your write up is without a doubt the easiest and most straight forward that I have found Thank You. I do have one issue it seems every time I add post-up /etc/init.d/ssh_tunnel into my /etc/network/interfaces file it seems to stop my DNS from working.