Reverse ssh

Reverse SSH is a term describing a method to connect via SSH to a destination host, when it is actually the host that is initiating the connection to a middle server.

Contents

[edit] Rationale

If your N900 (or any other Linux machine) is hiding behind private IP addresses / firewalls / NATs that you cannot configure - basically unreachable, you can overcome these obstacles with reverse SSH. Further discussion is located in this thread.

[edit] How To

Reverse SSH depends on a common server, a machine that both the client (source) and the host (destination) can reach. The host connects to the common server, waiting for the client to connect, then, the client connects to the common server, which in turn forwards that connection to the host.

[edit] Incentive

My N900 has unlimited 3G data connection, and I wanted to be able to ssh to it, even though it is using a private ip address which is unreachable. Reverse ssh made it possible.

[edit] Installation Steps

The core of this "workaround" is very simple, it consists of :

  • Common server which has an SSH server accessible for both client and host
  • host runs the command:
    ssh -N -C -p <commonServerPort> -R <forwardedPort>:127.0.0.1:<hostPort> commonServerHostname
  • Example:
    ssh -N -C -p 22 -R 2222:127.0.0.1:22 myHostname.no-ip.info
  • After connection has been set up (password is required when running the command above on the host(N900)) you connect to the common server using ssh and run the command (if configured as in the example):
    ssh root@127.0.0.1 -p 2222
  • You are now connected to the HOST.

[edit] Pitfalls

There are a few shortcomings in this setup, most can be worked around.

  • In order to skip the password query on the HOST, one must copy the public SSH key from the host to the authorized_keys folder on the common server. In case your host is the Nokia N900, the file is located at: /root/.ssh/id_dsa.pub
    • Some routers allow you to paste the contents of that file via the web gui of the router. (For example Tomato firmware for wrt routers)
  • If the SSH connection between the host and the common server breaks, for any reason, we want it to be reconnected automatically, we can encapsulate the ssh command inside an infinite loop, using a while command:
    while true; do ssh -N -C -p 22 -R 2222:127.0.0.1:22 myHostname.no-ip.info; sleep 5; done
  • The command should be inserted into a script, for easy dispatch.
  • It is possible to add the command to /etc/network/if-up.d/ - this will cause it to get dispatched every time 3G / wifi are connected, making your phone available immediately.
    • If the above method is used, a matching script must also be added to /etc/network/if-down.d/ to kill the looping ssh command to save some battery.
  • When not used, and idle SSH connection might fail, In order to make the phone close the SSH session and start a new one, and also try to maintain it, we can add 2 values to the ssh configuration of your phone.
    • Open the file /etc/ssh/ssh_config for editing using your favorite editor, mine is vi.
    • Insert the following lines into the file :
      • ExitOnForwardFailure yes
      • ServerAliveInterval 60
    • The lines should be inserted right after the "Host *" line.
    • I am not sure about BW usage for the "ServerAliveInterval" command, but it works for me, if you use it, make sure you monitor your network usage over a few days.

[edit] Scripts & Files

All files need to have executable permissions (chmod +x filename, or chmod 755 filename)

[edit] reverse_ssh.sh

This file should be located in /usr/share, you also need to edit it with the correct ports and hostname.

#!/bin/sh
 
echo "Script starting"
while true; do ssh -N -C -p 22 -R 2222:127.0.0.1:22 myHostname.no-ip.info > /var/log/reverse_ssh.log; sleep 5; done

[edit] reverse_ssh_stop.sh

This file should also be in /usr/share.

#!/bin/sh
 
killall reverse_ssh.sh
 
for i in `ps aux | grep -i "ssh -n" | grep -v grep | awk '{print $1}' ` ; do
        kill -9 $i
done

[edit] reverse_ssh_if_down

This file should be in /etc/network/if-down.d/

#!/bin/sh
 
nohup /usr/share/reverse_ssh_stop.sh > /var/log/reverse_ssh_if_down.log &

[edit] reverse_ssh_if_up

This file should be in /etc/network/if-up.d/

#!/bin/sh
 
echo "Interface went Up"
nohup /usr/share/reverse_ssh.sh > /var/log/reverse_ssh_if_up.log &

[edit] Warnings

  • This may drain your battery.
  • This may cause connectivity problems if you don't do something right.
  • This may compromise your phones security.

[edit] Reliability

  • After using this for about 5 days, I can safely say this is very reliable. My setup: Nokia N900 > Linksys WRT54GL with Tomato firmware.
  • I have been able to connect to my N900 any time I wanted, and it just worked.
  • Tested both when phone was on WIFI, and 3G.
  • Also tested rebooting the router, causing the *.no-ip.info value to change, which also showed the N900 promptly queried for the new value.

[edit] Credits

Special thanks to Spanner for helping me out in this thread, none of this would have been possible for me without him.

Please feel free to edit this page if you have anything to add, I am not a Linux expert, and the directories I chose to put the files are totally random, they may not be the best places, but they are all very small so the impact is little.