Introducing Kevin

One of my Raspberry Pi minions tends to lead quite a nomadic existence. Its name is Kevin and he likes to roam around. Kevin is a so called headless machine, which means that there's no monitor or keyboard attached to it. And yet I need to be able to control Kevin over ssh, no matter where I am or where Kevin is. And Kevin runs a web server, which needs to be accessible too. It's not really a public server, it's for private use only, but it also has to be accessible, no matter how far we are separated from each other.

Setting up a system like that in your home network is a piece of cake. Or should I say a banana, as minions tend to go crazy about them. You don't need to do anything when both you and Kevin are in the same network. And setting up some port forwarding rules in your router will allow you to connect to your Kevin from all over the world.
However I usually do not have access to the router settings on the networks where Kevin is connected to. So I can't open any ports. And even if I could, most ISP's still use dynamic IP addresses, which require some more tweaking to make Kevin accessible from the internet. And sometimes I don't want to leave any ports open on Kevin when I leave him on an untrusted network, just for security reasons,.

Connecting To Kevin, Anywhere From Anywhere

How can we accomplish this? One way to do this is to use reverse tunneling. Kevin could automatically try to dig a tunnel to another machine. And then it can mirror his own ssh and web server on to that machine. Although this is a viable option, I don't go take that route now. Once I heard about ssh over TOR I knew that was what I needed. My Kevin now runs 2 TOR services. One is the ssh server, the other is the web server. Both these services have a separate .onion address. And I can simply connect to these services through any TOR enabled system.
On this page I'll explain how to set up your own Kevin in a few easy to follow steps. You can expand your setup as far as you like, with multiple web servers for instance.

But isn't TOR used by criminals? It probably is. And so are our roads. We don't go about closing our roads, just because criminals use them. Then why can't we use TOR to our advantage then, without feeling guilty about it?

What Do We Need?

For starters we need a Raspberry Pi. A simple model B should do it, although it will also work on a B+, a Pi2 or a Pi3.
You may also want a Wifi dongle which is compatible with the Raspberry Pi, unless you've got a Pi3, which has built in Wifi.
One or more Linux systems which can connect to a TOR network. This can be a second Raspberry Pi, or a virtual machine, or your VPS, or your desktop computer. From here you can ssh into your Kevin in order to maintain it. If you don't have such a system a Tails live USB stick will also do the trick. And for the rest we just need a couple of easy to install programs.

Kevin's Hardware

I've put Kevin in a simple plastic box. The bottom of this box is covered with a piece of pad board, which holds a step down voltage converter. This allows Kevin to be supplied by any voltage between 7 to 24V DC. The pad board also holds a few connectors. A DC-in barrel type connector and a couple of 3.5 mm jack plugs. These jack plugs are used to connect some DS18B20 thermometers to the system.
USB port wrapped Other than that no connectors are exposed to the outside. This is for security reasons as I need to leave Kevin unattended in uncontrolled locations.
I have added a piggyback USB connector, which basically folds around the existing USB connector. This allows me to include a USB flash drive. Otherwise only very short flash drives would be able to fit into this relatively small plastic box.
The plastic box can be closed completely. So no one can easily access any of Kevin's hardware. I also deliberately locked the SD card fully inside the box, so it can't be removed without opening the box.
Keep in mind that Kevin holds a few secrets on its SD card. Any Linux machine can simply access these secrets when you insert the SD card into your computer. So if security is important to you, make sure that Kevin can't be opened easily. And if it is opened anyway, make sure you will know about it. For instance by looking at the damage to the casing. You may also want to put a phone number or address on the box, so people can identify the owner of the system. You can't be too careful with unattended gadgets these days. You don't want anyone to call the bomb squad when they find your suspicious looking contraption.

Kevin's Software

I use my Raspbian Lite image to start with. Needless to say that I will at least update the system first, extend the SD card file system to its maximum size and change at least the password. You may also change the default user and hostname. If you want to change the default user, do that now, as we're going to need its home directory in a minute.

For the setup procedure I connected my Kevin to my network using an ethernet cable. You can also use a monitor and keyboard to do the initial setup if you like.

Then you need to install some software:

sudo apt-get install ufw tor

UWF is an Uncomplicated Firewall. It is used to close all the network ports from the outside. Yes, this is not a mistake. All ports will be closed, so no one can break into Kevin from the host network.
TOR is the package we need in order to create .onion services on our machine.

You may also want to install other software. For instance a web server. It doesn't matter what web server you install. You pick one. On the rest of this page I assume that you have a web server running, listening on the default port 80. Although it is perfectly acceptable for the web server to listen on any other port you like.

Setting Up TOR

Let's setup the TOR services first. The first thing to do is create some directories which have to be secured so that not everyone can read what's in them. Basically you need one directory per TOR service and you can name them anything you like. We want to start 2 TOR services, ssh and web, so we need two directories here. These directories can be anywhere you want them to be, as long as they are readable by the debian-tor user. I simply put them in the main user's home directory.

This is how you do that:

cd
mkdir -p tor/ssh
mkdir -p tor/web
chmod 700 tor
chmod 700 tor/ssh
chmod 700 tor/web
sudo chown debian-tor:debian-tor tor
sudo chown debian-tor:debian-tor tor/ssh
sudo chown debian-tor:debian-tor tor/web

Now you have to edit the file /etc/tor/torrc (as sudo of course). Find the line which contains the text "This section is just for location-hidden services". A bit further down in this block you'll find two examples of how to set up a hidden service. Let's add our two hidden service details here.

HiddenServiceDir /home/pi/tor/web
HiddenServicePort 80 127.0.0.1:80

HiddenServiceDir /home/pi/tor/ssh
HiddenServicePort 22 127.0.0.1:22

Then save the file and exit your editor. That's all there's to it really. What you did here is tell the tor daemon where it can store the hidden service information and to what service it has to connect. For the web server it connects to port 80, the default HTTP port, of the local host. And for ssh it connects to port 22, the default ssh port, of the local host.

TIP: With this setup you get two separate .onion addresses, one for the hidden web service and one for ssh. This is good security practice, because a web visitor can't possible know what .onion address he should use to ssh into your machine. But as always security is not convenient. If you can live with the fact that you give up some of the security you can combine the web and ssh services under one .onion address. You can use these settings instead:

HiddenServiceDir /home/pi/tor/web
HiddenServicePort 80 127.0.0.1:80
HiddenServicePort 22 127.0.0.1:22

That way you only have to remember one .onion URL

TIP: In a minute we're going to restart the TOR daemon. And because our tor directories, which we have created above, are empty a new private/public key pair will be generated for each of the hidden services. But what if I already have a private key? For instance from a previous installation of an old and discarded Kevin? Or what if I want to use a so called vanity .onion address?
Simple, place the private_key file in the dedicated tor directory and change its owner and privilege flags before you restart the TOR daemon. Then it will only generate the hostname for you.

Enough tips now. Let's restart the tor daemon:

sudo service tor restart

Needless to say that you‘ll have to treat your private_key files private. Be aware that with these keys anyone can impersonate your server. And if you want to hang on to your host names be sure to make backup copies of the private_key files.

Let's See If It Works

sudo cat tor/ssh/hostname

Now it should say something like this (your onion address will be different of course):

yqgq2gekdwr2n4le7gq4mnbaxysu3dp3qrj3la2av32rijnsu27p4rid.onion

And the same applies for our web service:

sudo cat tor/ssh/hostname

This should say something like this:

q4mnbyqgq2gekdwr3dp3qrraans4le7gaxysuj3l2na2av32u27p4rid.onion

Let's test the web server, because it's easy. You can simply enter the web address into the TOR browser. But if you don't want to download that, you can simply add .to behind the .onion addressbar of your regular browser to view the page, thanks to the good people from tor2web. So in my example I would enter q4mnbyqgq2gekdwr3dp3qrraans4le7gaxysuj3l2na2av32u27p4rid.onion.to into my web browser. It may not work immediately because your new hidden service has to be announced to the TOR system, which can take about a minute, or two. I don't know if that time is specified somewhere, but it has never taken more that 5 minutes in my experience.
If everything is OK you should get the same page as you would get if you browsed to the normal IP address of your Kevin.

Testing your ssh setup is a little bit more complicated, because there is no direct connection between the normal internet and the TOR network. The easiest way to test your ssh connection is to restart a computer (or a virtual machine) from a Tails live USB stick. Once it's running you can simply open a terminal screen there and enter ssh yqgq2gekdwr2n4le7gq4mnbaxysu3dp3qrj3la2av32rijnsu27p4rid.onion. Uhm, do I really need to point out that you'll have to use your hostname instead of mine here?

OK, now you should be able to login to your Kevin or browse to his web server, over the TOR network, from anywhere in the world, no matter where Kevin is, without having to open any ports in your or anyone's router. That's exactly what we wanted.
But we're only halfway home. So far we have to connect Kevin through an ethernet cable. We want him to connect over Wifi. And we'll have to use Tails to ssh into Kevin. Oh, and I haven't enabled the firewall yet. But let's do that at the end. We need to make sure that everything works first, before we lock ourselves out.

SSH Over TOR

Let's cover the ssh issue first. For that we need a Linux machine. It may also work on a Windows machine, but I'm not going to bother about how to do that. This Linux machine we're going to use may be your desktop computer, your laptop, another Raspberry Pi, or perhaps a virtual machine. It may also be a combination of machines. Any Linux machine which is prepared in the way described below can be used to ssh into Kevin.

On the (debian based) Linux machine of your choice install the following packages:

sudo apt-get install tor

Then edit or create the file ~/.ssh/config and add the following text to it: and save the file.

host kevin
    Hostname yqgq2gekdwr2n4le7gq4mnbaxysu3dp3qrj3la2av32rijnsu27p4rid.onion
    User pi
    ProxyCommand nc -X 5 -x 127.0.0.1:9050 %h %p

Now you can simply connect to Kevin by using the command below, no matter where you or Kevin are in the world, again without opening a single port on your router.

ssh kevin

PS: There appear to be different implementations of netcat. The one used in Raspbian works. In Debian Jessie it appears that netcat-traditional is installed per default. This version doesn't understand the -X option. This is easily solved by installing netcat-openbsd , by typing sudo apt-get install netcat-openbsd .
And if that doesn't work either, you can install the package connect-proxy and replace the last line of the .ssh/config block to:

proxyCommand connect -S localhost:9050 %h %p

There are other ways. For instance when you don't want to setup a new config rule. Simply run torsocks ssh yqgq2gekdwr2n4le7gq4mnbaxysu3dp3qrj3la2av32rijnsu27p4rid.onion. Or you could get a new TOR enabled shell with torsocks --shell.

Setup Wifi

Now let's setup the Wifi. We want Kevin to automatically connect to any predefined network which is within range. That means that we have to tell Kevin to what networks it can connect to. And we want that list to be extendable. Here's how I've done that for my Kevin.

Edit the file /etc/wpa_supplicant/wpa_supplicant.conf and add as many networks as you want to. Below you'll see the format you have to use:

network={
    ssid="NameOfYourNetwork"
    scan_ssid=0
    key_mgmt=WPA-PSK
    psk="WPA-Secret-Of-Your-Network"
    id_str="UniqueNetworkName"
}

It goes without saying that you'll have to change the text behind ssid, psk and id_str for each of your networks.

By the way, in that file you may want to change the country too. Not that it is that important. It merely tells the system what channels are allowed in your country.

That's really all you have to do to make your Wifi work. By the way, are you sure your Wifi works? You can check that by running this command:

sudo iwlist wlan0 scan|grep SSID

It should show you a list of the available networks around you. If not, chances are that your Wifi is not working. It may be that your adapter is not Raspberry Pi compatible.

Enter all the known networks to the above file and your Kevin will be able to connect to the internet whenever one of these networks is within range. Couldn't be simpler.
But what if there's only a new network around, one which is not known to Kevin yet. You can't login now to set it up because Kevin is not connected to the internet yet. Easy. I'm sure you've got a smartphone, don't you? Setup a mobile hotspot on that phone and tell Kevin about its details. So whenever you're in the middle of nowhere and need to configure Kevin, simply switch your mobile hotspot on and Kevin will log in to that. Do the configuration for the new network, after which you can switch off your mobile hotspot again.

Build The Firewall

The only thing left to be done is to set up the firewall. I've chosen to close all external ports to Kevin, including the ssh port. So the only way to login to Kevin will be over TOR after that. Be aware that you can lock yourself out if you don't have TOR working correctly yet. So be sure everything works up until here before you take this step. You can also decide to keep the ssh port open if you're afraid of locking yourself out. It's not that I'm afraid someone will hack into Kevin, but I can't ssh into Kevin over TCP anyway because I'm not likely connected to the network where Kevin is connected to. So what's the point in having the port open if can't reach it?

The easiest thing to do is to copy the text below into a file and make the file executable as a script (chmod u+x scriptname). Then run the script, as sudo. That will take care of the firewall for you.

#! /bin/bash
# Firewall rules will prohibit all external access
# Run this script as sudo

# Set default policy for incoming and outgoing traffic
ufw default deny incoming
ufw default allow outgoing

# ssh connections may be allowed if you want to
# Simply uncomment the line below and re-run this script
# ufw limit proto tcp from any to any port 22

# Enable these rules and auto enable at boot
ufw enable

That should keep prying eyes on the local network out of your Kevin.

One more encore: While we're at it, let's disable ping echoes too. So even if someone on the local network finds a strange IP address being used, Kevin won't reply to ping requests. It will be just as if he's not there :-)

Edit the file /etc/ufw/rules.before and place a # symbol in front of the line containing the text:

-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT

Then you may have to restart ufw, or simply reboot your Kevin in order to make the change effective.

An Important Warning!

Warning! Never, ever just update your system with a casual sudo apt-get upgrade! If the tor package requires an update your connection will break, causing the upgrade to abort, leaving you with a broken tor package. Your Kevin will not come back online again after that. You will have to get your Kevin in for maintenance by connecting a keyboard and monitor to it in order to fix this.
Always run the upgrade from within a screen or tmux session. That way the connection to your ssh session may break temporarily, but the upgrade process will continue.

Be Patient With TOR

TOR is not a fast network. And your internet speed depends on the slowest relay it is currently using. Relays are changed just about every 10 minutes or so. So you may experience lots of changes in your internet speed.
This speed will also reflect on the responsiveness of your ssh connection. You may sometimes notice that keys you press are not registered immediately. This can be annoying, but it is the price you'll have to pay by using TOR.

It may also take some time before your services become available after a reboot or a change of network. Kevin's services will have to be announced to the TOR infrastructure, and that may take a while. So be patient. Don't go resetting your Kevin if things don't work immediately after a reboot. Give it some time. If it doesn't work after about 15 minutes it may be time to take some action yourself.

TIP: Always use screen or tmux when you intend to use ssh over a longer period of time. Sometimes the connection may freeze up on you, or break down entirely. You don't want that to happen while you're in the middle of making massive changes to a file. When you use screen or tmux you can simply reconnect to your session after you're able to login again and continue where you left off.

If you are in a hurry, or if you want to exchange large amounts of data you may consider setting up a reverse tunnel to your computer. For that you simply login to your Kevin over the TOR network. And then enter the following command, preferably within screen or tmux, so the tunnel won't die when your TOR connection breaks:

ssh desktopuser@yourdesktopcomputer -R2222:127.0.0.1:22

Your desktop computer should be accessible over the internet for this to work of course. So you will probably have to add some port forwarding rules in your router or open some IPv6 ports in your firewall.

Once you've opened the reverse tunnel you can give the following command on your desktop computer in order to make a direct ssh connection at full speed to Kevin, bypassing the slow TOR network.

ssh [email protected] -p2222

How Anonymous Am I?

Personally I use Kevin to do some measurements, while it's connected to networks which are not under my control. And I use TOR to control and monitor Kevin, without having to make any changes to the networks I do not own. It never was my intention to make Kevin super duper secret and anonymous.
However if that is your intention be sure to erase all your traces. Kevin will be relatively anonymous, thanks to TOR. But if your Kevin gets compromised in any way, you're doomed. Chances are slim, but Kevin may be hacked. And once people have access to some sort of shell they can try to get clues of your true identity. If people have physical access to your Kevin they can simply take the SD card out and read everything that's on it. Including all the history and log files. Also think about mail accounts and the times Kevin has "phoned" home.
So if you want your Kevin to be super secret and anonymous you'll have to take many more precautions. I won't go in more detail about that here.