This is just a quick guide for my friend Gonza to describe how SSH tunnelling can let you connect to a Raspberry Pi (or any other box running a unix-like OS) from anywhere even if it's behind an internet connection with a dynamic IP. This lets you avoid bothering to set up dyndns or similar. What you need is:
- RPi on home network (we'll call this rpi)
- remote box running linux, with a known IP address (we'll call this remote)
What we're going to do is establish an SSH connection between rpi and remote that will remain up at all times, and which will re-establish the connection without any user intervention. We'll be authenticating using an SSH key, so if you don't already have one run the following, I think the defaults are ok:
me@rpi~ $ ssh-keygen -t rsa
And upload it to your remote server, and test it works nicely:
me@rpi~ $ ssh-copy-id me@remote-server.com me@rpi~ $ ssh remote-server.com me@remote~ $
Next we'll make sure the remote has sshd configured so that as a client connecting via SSH you can specify the ports involved - so open up /etc/ssh/sshd_conf in your favourite editor:
me@remote~ $ sudo emacs -nw /etc/ssh/sshd_conf
GatewayPorts clientspecified
type | rpi port | remote port |
---|---|---|
ssh | 40022 | 22 |
http | 40080 | 8080 |
This will mean that not only can I SSH to rpi, but there's another one I can use for running, say, some web site or service. To do this we'll use autossh which is responsible for establishing the connection and keeping it up:
me@rpi~ $ sudo apt-get install autossh me@rpi~ $ sudo autossh -Nf -M 40980 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40080:localhost:8080 me@remote-server.com me@rpi~ $ sudo autossh -Nf -M 40922 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40022:localhost:22 me@remote-server.com
To test this out, we can run a simple server on our rpi using nc:
me@rpi~ $ while true; do { echo -e "HTTP/1.1 200 OK\r\n"; date ; uname -a ; echo; echo; } | nc -l 8080; done
And we can cURL the IP address of remote, which will forward the request/response between your laptop and rpi - I've used xxx.yyy.zzz.www in place of the actual IP address:
me@laptop~ $ curl xxx.yyy.zzz.www:40080 Sun May 1 13:36:14 UTC 2016 Linux rpi 3.2.0-4-amd64 #1 SMP Debian 3.2.41-2+deb7u2 x86_64 GNU/Linux
me@laptop~ $ ssh me@xxx.yyy.zzz.www -p 40020 me@rpi~ $
To get this command to run after we reboot we can muck around with systemd, or we could create a cron job - the latter is easier, so let's do that:
$ crontab -eAnd enter
@reboot autossh -Nf -M 40980 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40080:localhost:8080 me@remote-server.com @reboot autossh -Nf -M 40922 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40022:localhost:22 me@remote-server.com
And if you want things to be a little easier you could add the following to your ~/.ssh/config:
Host rpi HostName xxx.yyy.zzz.www Port 40020
me@laptop ~$ ssh me@rpi me@rpi ~$
Update, 2016-09-08: There's actually an even simpler way to do this if you don't have a remote machine and a domain, you can expose a tor hidden service. The caveat is that you're only able to access it from within the tor network, which means you won't be able to access it from your iPhone.