I want to start off by saying that this is my very first time writing an article of any sort. Thanks to Rosen for letting me write as a guest on his awesome website. Anyhow, I hope you find the information below useful and practical as much as I have. Enjoy!
Several months ago, I quit Tech Support and started working as a Sys Admin for a storage company (still learning, there’s a looong way to go…). I knew about the power of SSH before, but on several occasions, I found out that creating SSH tunnels can be super useful and it gives you the freedom to quickly access devices from anywhere you want.
In my particular situation, I have a Raspberry Pi 3 sitting at home, up and running all the time, which I use for pretty much anything that I want to experiment with, whenever I get the chance… That last part is key: I want to be able to access the little gadget whenever I feel like it, and not be restricted by my location or the computer I’m accessing it from.
After I set up proper port forwarding in my home router (check the web if you don’t know how to do that yet, it’s very useful), I had to SSH to my external IP address and the specific port, which would in turn forward that to port 22 on my Raspberry Pi, allowing me to type my password at the prompt. Pretty basic procedure but I wasn’t really happy with the fact that I have to specify and address, a port, and type a password. I wanted to create some sort of an alias which would include all that information. I wanted the process to be as automated as possible, and after quite some time digging around on the web, here are the possible solutions that I found:
Simple SSH with an SSH key
You can always use sshpass and use the -p flag to give the password in the command itself, but this is not very safe, as anybody with access can check the CLI history or the current SSH session process (ps aux | grep ssh) and see the password.
- Bro tip: if you type a space (literal space character) before any command on the CLI, it won’t go in the command line history ;). A more secure way to establish the connection is throught the use of SSH keys.
First you generate a pair of private and public SSH keys on both ends (using ssh-keygen). Then you have to place the public key of each machine (located in /home/$USER/.ssh/) to /home/$USER/.ssh/authorized_keys of the other one. If the file doesn’t already exist, you should create it.
After that, you can create an alias on each machine (add alias=’$YOUR_ALIAS’ to the .bashrc file located in your home directory) for your convenience so that you don’t have to type the full command every time, e.g.:
$ alias pi=’ssh pi@$IP_ADDRESS -p 1234′ # -p to specify the port
The last thing to do is to source your .bashrc file in order to refresh it ( source /home/$USER/.bashrc ) and… voilá!
Now every time you type your alias in your terminal, you will be instantly logged into the remote machine (except the very first time when you need to type “yes” to accept the remote machine into the known_hosts file).
This tool is very useful when you want to take things a little further. The program starts an SHH tunnel, goes in the background (if you tell it to), and monitors it while restarting the session as necessary. Like all SSH tools it has many options, but here is the command that I personally use:
$ autossh -M 20000 -q -f -N -o “ServerAliveInterval 60” -o “ServerAliveCountMax 3” -R 55000:localhost:22 -C pi@$IP_ADDRESS -p 2222
# -M specifies the base monitoring port to use.
# -q for quiet mode, supressing most warning and diagnostic messages.
# -f requests ssh to go in the background just before command execution.
# -N for not executing remote commands; useful for just forwarding ports.
# -o “ServerAliveInterval 60” for checking every 60 seconds for connectivity, if the session dies
# -o “ServerAliveCountMax 3” for setting the limit of sending messages to the remote side without any response back; when this limit is reached, the session will be terminated. (autossh will restart it again immediately)
# -R for forwarding a certain remote port to a certain local port (in this case port 55000 on the remote side will be tunneled to localhost port 22)
# -C for compression of all data flowing through the session (compression algorithm is the same one used by gzip(1))
# -p to specify the remote port for the ssh connection itself
If you have previously set up your SSH keys properly (see above) it won’t even prompt you for a password. At this point you would think “But why do I need this long and complicated command for keeping an SSH tunnel alive?”. Well, I will share with you my exeperience.
I wanted to have permanent access to my working station from anywhere, if I happen to need to access it and do some work (there are lab machines and customers’ clusters that I cannot access from outside of the office network).
Since I know my Raspberry Pi’s password I can always SHH with agent forwarding (-A flag) from anywhere to it (even from someone’s Windows PC using a Putty session for example). Once I am connected to my Pi, and I have made sure that I have my public key loaded into my SSH agent (ssh-add -l to check) I can then SSH to my working machine through that very tunnel that is always running thanks to autossh (you can add an alias for that if you like):
$ alias work=’ssh -A $USER@localhost -p 55000′ # make sure to specify the proper local port that is listening on port 22 on the remote side
And voilá! Now I can quickly connect to my working station every time I type my alias (Again, the very first time you need to type “yes” to accept the remote machine into the known_hosts file).
- Bro tip: if you want autossh to start automatically after a reboot, just add the full command to your startup applications 😉 (usually located at System → Preferences → Personal → Startup Applications)
You can always take things even a step further and create other SSH tunnels through the already existing one (tunnelception, lol). For example, I created another autossh session but this time from the Raspberry Pi to my working station. I forwarded port 80 of the Pi to port 25000 on my working machine so I can access the WordPress setup page on the Pi from my web browser at work. I did this by autossh-ing to port 55000 on the Pi’s localhost (the existing tunnel). Here is the command:
$ autossh -M 20000 -q -N -o “ServerAliveInterval 60” -o “ServerAliveCountMax 3” -R 25000:localhost:80 -C $USER@localhost -p 55000
The SSH shuttle (sshuttle) client is particularly useful when you want to gain access to a whole remote network locally. Basically you’re establishing a VPN connection from your local machine to any remote server via SSH, but you need to have root access on the local machine (you can have a normal account on the remote server). Here is the command:
$ sshuttle -r $USER@$IP_ADDRESS:$PORT 192.168.0.0/24
# syntax: sshuttle [options] [-r [username@]sshserver[:port]] <subnets …>
It will first prompt you for the local sudo password, then the remote user’s password (if you don’t have ssh keys configured), and after that the client is connected. It is best to keep the client in a separate terminal tab, as sshuttle doesn’t have quiet mode and is flooding your terminal screen with some warning and diagnostic messages every now and then.
My personal practical example: I wanted to be able to remotely manage the small WordPress website I am hosting on my Raspberry Pi from its dashboard. I did an sshuttle connection from my working station to my Pi at home. With the connection present, I simply typed my Pi’s internal IP address into the web browser of my working machine, and I logged into the WordPress Dashboard of my website.
I hope this helps. Peace out!