Monday, 30 June 2014

RPI as secure web proxy

I, like most other people in the modern age, spend a lot of time on the Internet. This time is probably, in order of usage, at work, at home, at other locations like coffee shops or other public WiFi. Like most people my own network is quite secure, but what about everywhere else?

The work WiFi is internal to the office, but how secure is that? To get on the WiFi you just need the password - there could be all kinds of devices connected. And who's to say that those devices don't have malware on them? Clearly I would like my connections to websites and so on to be protected.

Think about staying in a hotel, using the hotel guest WiFi. I'm now sharing a connection with strangers in other rooms, with God knows what intent.

The answer for me was tunneling.

This is the idea - you open a secure connection to a service running on a network you trust - in my case it's my home broadband, but could be a server in AWS if something - it's easier if it's Linux based, but essentially you can do it on anything. I have a Raspberry PI on the network at home, so that's what I went with.

You then use the ssh protocol to "tunnel" all traffic over a secured connection, via your trusted endpoint, out to the internet. The ssh client allows a proxy mode called SOCKS, which allows all network connections to be made by the proxy. So, when I hit facebook.com in my browser what's actually happening is the browser is asking the designated SOCKS proxy to establish that connection, and route traffic back. I've used the ssh command to set up that SOCKS proxy via my home network, so now all traffic is coming from the internet to my home network, and is then encrypted and tunnelled to my machine.

This works for all HTTP and HTTPS traffic, is very easy to set up, and I do it all the time now. I even have a script which sets it up on my mac for me.

The different pieces you need to configure are the PI itself, and the machine you're using. Let's start with the PI:

My home modem allows me to forward traffic from the internet to a specific host, so I have configured this to hit my Raspberry PI, and I bought a domain name for the job. I'm not telling you here what it is - sorry about that, but you know, this is a public blog... 

In the interests of not reinventing the wheel ensure your PI is good to go as an sshd server using the guide here. Note the section on generating keys - this is a really good idea as it negates the need to enter a password when setting up the tunnel.

Once you have it working you *should* be able to ssh to your PI from outside your network, if you've configured your modem correctly. If you have purchased and configured a domain for this, or used one of the dynamic IP services then this will work a treat.

If you can't get this bit working don't carry on, as this next part relies on the fact you can actually make a connection.

In order to create the SOCKS proxy tunnel you enter a command similar to this:

ssh -v -N -D8080 -o ServerAliveInterval=3 pi@yourdomainhere.com

Note the yourdomainhere.com - if you've not set up a domain you'll need the internet IP address of your modem here.

In the call here -v prints verbose information so you can see what's creating connections on the tunnel - leave it out for a quieter life. The -N stops the ssh default behaviour of executing a remote command - typically a shell, and the -D8080 is the magic which creates the tunnel. More on this in a second. The -o ServerAliveInterval=3 is a further optional parameter makes the client send a null packet to the server every 3 seconds, to keep the connection alive. Many ssh daemons kick off connections with no activity after some time, so this just stops that happening.

Now - more on that -D8080. This sets up a Dynamic proxy on port 8080. A dynamic proxy makes new connections as created on the remote host to service the requests on our local machine. SSH also allows the use of specific static routes, where a specific port on the client is routed to a specific port on the server, but we're not using that here.

I actually wrapped the above line into a script as shown here:

#! /bin/bash

scselect "Proxied"
sleep 5;

while [ 1 ]; do
  ssh -v -N -D8080 -o ServerAliveInterval=3 pi@yourdomainhere.com
  echo ssh exited... relaunching...
  sleep 5

done

This script uses the scselect command to automatically switch the Location on my mac to a location called Proxied. I have set this up as shown here in the screenshot below. Note that on a Windows machine I don't know how you'd do this in a system-wide way, but on a Mac this setting is honoured by all browsers in one hit.

The script also reconnects if the connection drops, after a 5s delay.

You can see that I have set up a SOCKS proxy on localhost, on port 8080, which matches the port in our -D parameter to ssh. If you need to use a different port that's fine - just make sure the port you put in your proxy settings match the port in your -D line.

Again, if you're doing this in your browser directly (in Windows, say) you need to find the SOCKS setting and change it in this way, and it should work just the same.

I have this script in a bin folder I can access by running terminal, and then just running ssh-tunnel. It takes over that terminal tab, which I like because I can see what's going on, and to exit it just kill the tab or CTRL-C the script. Easy.

I would strongly recommend if you're going to do this that you also take a look at your SSHD options  on the PI and remove password authentication altogether. I would also strongly recommend that you install fail2ban using this guide here. Fail2ban essentially monitors your access log file and automatically IP blocks failed login attempts. You'll likely never have any, so this means someone is trying to get into your system.

I would also do some googling on securing your PI and either set your modem to only forward port 22, or else bolt your PI down to prevent unauthorised access.

And finally....

Once you have an SSHD server on the internet you can access any of the machines on your internal connection. For instance, check out this bit of script which gives me a VNC client on my iMac INSIDE my home network. This uses the -L parameter to create a specific tunnel (rather than a dynamic one) from port 5900 locally to 5900 on 192.168.0.11. Now, what's this? 192.168 addresses are internal to my home network? That's right - this is in the context of the remote network. You can see the familiar pi@yourdomainhere.com to actually make the remote connection.

The last line is a Mac command to open a connection, but again, having made the connection you just need to open your VNC client and connect to localhost:5900 - like the dynamic proxy shown earlier you are making a LOCAL connection which is tunnelled for you.

Easy, huh! Now, go and be secure. :-)

#! /bin/bash

echo Connecting...
ssh -f -v -N -L5900:192.168.0.11:5900 -o ServerAliveInterval=3 pi@yourdomainhere.com
sleep 2; # Allow connection setup time

open vnc://localhost

No comments:

Post a Comment