I’ve got a few Alexa devices around the house, and a few RaspberryPi lying around so I decided it could be interesting to try to make them work together. The first step I could think of was to figure out a way to be able to connect to my RaspberryPi from AWS. I wanted to stay in the Free Tier from AWS, so a lot of options were not available to me. I do have access to a shared server where I can run SSHd and PHP, so I decided to leverage those. Here is how I ended up using a reverse SSH tunnel to access a RaspberryPi.
Why use a reverse SSH Tunnel
When playing with this experiment, I wanted something that was somewhat secure. I did not want to open ports to my personal router and use a service like no-ip. A Reverse SSH Tunnel allows me to not open any ports on my home router.
Basically, a Reverse SSH Tunnel opens a port on the remote host and forwards any traffic on that port to a port on the machine that established the SSH connection. My hosted server’s network configuration prevents all non-HTTP(s) connections to it. This setup allows me to have a small PHP script with some kind of access-key that forwards connections directly to the tunnel.
As always, I posted my code on one of my GitHub repository. In the case of this project, it lives here and is split into two major scripts: ssh_forever.sh and ssh_no_more.sh. Both of these are controlled by environment variables and are explained in sample.env.
Using this script is quite simple:
- Copy the sample.env file somewhere
- Edit the file to put in values that make sense for your setup
- Add the script execution to your crontab
I set up my crontab to run the script every minute. In order to edit the crontab for your current user, simply run crontab -e. Once this is done, your favorite editor will show up. You’ll need to add a line at the end of the file, in my case, I used the following:
*/1 * * * * . /home/someuser/sshforever.env && /home/someuser/bin/ssh_forever.sh > /home/someuser/tunnel.log 2>&1
The first part, */1 * * * *, controls when to run the script. In the current case, it will run the script every minute. The rest of the line is the command to execute. In my case, I want to source the content of a file into my environment, execute the script, and keep a log of what happened.
The command is therefore split into three parts:
- . /home/someuser/sshforever.env: sources the environment file
- /home/someuser/bin/ssh_forever.sh: executes the script
- > /home/someuser/tunnel.log 2>&1: redirects both STDOUT and STDERR to a log file
Doing things this way prevents you from using a password to connect to the SSH server. You should set up your connection using a public/private key pair.