ReverseSshTunnels

From Wiki

Jump to: navigation, search

So you have a linux box at home which is behind a NAT router, so that it doesn't have a publicly addressable IP address. This prevents you from being able to ssh into it remotely. However, if you have another machine which *is* publicly addressable (ie, a machine at work), you can set up a reverse-ssh tunnel to it, so that you can ssh into it from the publicly addressable machine.

So, assuming your home machine is named 'home' and your work machine is named 'work' and your username on 'work' is 'workuser', you'd run this from 'home':

ssh -R 12345:localhost:22 -N work -l workuser

This will forward port 22 on 'home' to port 12345 on 'work'. If you have problems with idle connections being dropped, you can have ssh send a 'keep-alive' packet every 30 seconds:

ssh -R 12345:localhost:22 -N work -l workuser -o ServerAliveInterval=30

Now, to ssh into 'home', first log into 'work' and run this:

ssh -p 12345 localhost

if your username on 'home' were 'homeuser', you'd run this:

ssh -p 12345 homeuser@localhost

if you want the connection to be reestablished automatically, you can put this in a script. let's call it 'reverse-ssh.sh':

#!/bin/sh

set -x

TARGET_HOST=${1}
if test -n "${2}"
then
    TARGET_PORT=${2}
else
    TARGET_PORT=12345
fi
TARGET_USER='workuser'

while true
do
    echo "establishing reverse ssh tunnel to ${TARGET_HOST}:${TARGET_PORT}"
    ssh -R ${TARGET_PORT}:localhost:22 -N ${TARGET_HOST} -l ${TARGET_USER} -o ServerAliveInterval=30
    sleep 1
done

now, you'd run:

./reverse-ssh.sh work

however, you'll quickly run into a problem: the script prompts you for your password everytime it tries to re-establish the connection. we can get around this by setting up an ssh key-pair, which allows password-less authentication.

on 'home', run this:

ssh-keygen

when it prompts you for a password for the key, just hit enter to create a password-less key. the key will be created as ~/.ssh/id_rsa, and the corresponding public key will be created as ~/.ssh/id_rsa.pub.

now, on 'work', you need to append the public key to your 'authorized_keys' file. I typically do this by cat'ing the public key, highlighting its contents with my mouse, then running 'cat >> ~/.ssh/known_hosts' on 'work' and middle-clicking the mouse to paste the contents, then hit CTRL+D to close 'cat'.

if you want this script to run automatically on boot, put it in /usr/local/bin and append this to /etc/rc.local:

nohup /usr/local/bin/reverse-ssh.sh work >/tmp/reverse-ssh.out &

(FIXME: what about redirecting stderr as well?)

this will fork the script off into the background on boot. the output of the script will be appended to /tmp/reverse-ssh.out.

note, however, that this could have security implications if your 'home' machine ever gets hacked (the attacker would have a free ticket to wreak havoc on 'work' as well!). there are options for making 'single-purpose' keys which will restrict what can be done with the key-pair. for more on this, see the article 'HOWTO: set up ssh keys' by Paul Keck (http://pkeck.myweb.uga.edu/ssh/).

update: rather than using the nohup method, lately I've been doing things like this by starting a screen session. this is very useful for processes which you wish to re-attach to later. try putting this in rc.local:

{{{ screen -S revssh /usr/local/bin/reverse-ssh.sh work }}}

to attach to that session later, run this:

{{{ screen -r revssh }}}

Personal tools