Securing your web browsing - part 1
This is a guide to setting up a remote proxy web server. It assumes that you are familiar with using the linux command line, ssh and general configuration of linux machines.
For a political discussion of these issues, please see my blog
What happens when you access a web page?
We are so used to the ease of using the internet, we rarely stop and think about how it all works. So, here is a simplified version of what happens when you access a website on the internet.
The sequence we are interested in is :
- look up the ip address using DNS. eg convert bbc.co.uk into 126.96.36.199
- connect to the server using HTTP or HTTPS
- request the page
All of these can be intercepted and logged. If you are using HTTPS rather than HTTP then the data is encrypted in transit, which helps a lot, but the ISP knows which server you are talking to, because of the DNS lookup. If the remote server's keys have been compromised then the whole traffic can be decoded. All this traffic is now logged by law in the UK.
The system has a number of potential security holes. If someone can intercept your DNS requests, they can send you to the wrong site. This can be used for man-in-the-middle attacks. Any unencrypted data can be snooped or spoofed.
The UK Government also uses the DNS system to censor web sites. UK based service providers will be required to do this. If you avoid the UK based providers you can move the requests in a different regulatory regime. They will not be seen by the UK based ISP.
Protecting your DNS lookups is also a good security measure against hackers. Normally your home router will provide DNS lookups, typically via your ISP. If you router is hacked, it is simple for the attacker to subsitute the DNS servers for ones of their choosing. This allows them to monitor all your requests, and to redirect any of your requests, anywhere they choose. This is a simple way of attacking any machines on your home network, both for man-in-the-middle attacks and general attacks. Many commercially available routers have poor security and are wide open to hacking. My email server gets around 500 attacks every day from just one model of router, the notriously badly designed NetGear WNR2000v4/5 router. This one defective product has spawned a whole industry of spam attacks. If you are using one of these routers, unplug it and throw it away now. It's not just your home router you need to worry about. It is any router anywhere. Yes that free WiFi at the corner cafe may well be exposing you to DNS hijack attacks.
The aim of this tutorial is to show you how you can move all the DNS and connect activity to a remote location.
Get your own server
First you need a remote linux server. A virtual private server, or VPS, is a linux image running on a virtual machine. These can be rented for very little money, in locations across the World.
The two European providers I've been using recently are Aruba Cloud and Ultra VPS. A minimal spec server costs €1 and €2 a month respectively. Aruba have a free €2 introductory account. You can chose from a variety of countries where the servers are located. I must stress that I can't guarantee that these are trustworthy. But I have been using them and they are cheap and seem reliable. I use Ubuntu Server 16.04 LTS because I'm more familiar with it. Pick a provider that provides up to date linux images, otherwise you will expose yourself to hacking.
The server will come with an admin web login, and you will be given the ip address. You need to choose a password for root login. You should change this as soon as you log into the machine.
I must stress that these providers will know who you are. You have to pay them somehow and they may require your phone number to send you passwords, which means that security services could track you. If you really need to hide from well resourced oppressive regimes, this probably isn't the right way to do it. But it does show you how such a system can be configured.
Configuring the server
The initial setup will depend on the provider. You should be able to choose the OS type and version, RAM and disk capacity and the geographical location of the server. The ones I'm using have 1 Gb RAM, 20 GB disk and run Ubuntu Server 16.04 LTS 64 bit. It is the provider's lowest cost VPS. This is more than enough to run your proxy server.
Once you have acquired a server, you need to configure it. You need to add a user, set up secure ssh access, you need a good firewall and you need to run squid, which is a caching proxy server. I'll cover each of these things in turn.
In the following text I use the user name 'dave' and I call the server 'tamara'. You should chose your own names for these.
The various prompts illustrated are '#' : root on the VPS, '$' : user on the VPS, 'dev$' : user on your home machine.
Make a note of your new server's ip address. Add this to your dev machine's /etc/hosts file by name, eg.
I run a dnsmasq server on my home server, so I added the name there. That ensures that the name is recognised across my home network.
From your home machine, login as root using ssh.
dev$ ssh root@tamara
Change the root password.
Add a new user :
# useradd -m dave
The -m will create the /home/dave directory etc.
Set your password
# passwd dave
Get a bash shell by default :
# chsh -s /bin/bash dave
Add yourself to the sudo group
# adduser dave sudo
You can now log in as dave.
dev$ ssh dave@tamara
When you first connect over ssh you will be asked if the server's key signature is correct. How can you be sure?
You are still logged in as root. To see the server's key, do eg :
# ssh-keygen -lf /etc/ssh/ssh_host_ecdsa_key.pub
This will list the key signature. You need to select the correct .pub file. If the two key signatures are the same, you can safely say 'yes' to the 'ssh dave@tamara' connection.
You can now logout from root. You shouldn't need to login as root again. You can do everything else from the user account using sudo. ssh will check the signatures of all future connections and warn you if anyone attempts to interfere with the connection.
Make an ssh config directory in your home directory on the server :
$ cd $ mkdir .ssh $ chmod 700 .ssh
You need to provide a public / private key pair on your home machine for the connection. These are normally stored in the directory ~/.ssh/ See eg. this github article on how to create and add ssh keys.
TLDR : create a key on your home machine using :
dev$ cd ~/.ssh/ dev$ ssh-keygen -t rsa -b 4096 -f webproxy
In this case the key is called 'webproxy'. It is a good idea to password protect it. Use the password to add the ssh key to your key agent as follows :
dev$ ssh-add ~/.ssh/webproxy
Now copy it to the server :
dev$ scp webproxy.pub dave@tamara:~/.ssh/
on the server, copy this key into the authorised key list. This tells the sever to always allow a connection from a client with this key.
$ cd ~/.ssh $ cat webproxy.pub >> authorized_keys
On your dev machine edit or create the ~/.ssh/config file to add an entry that defines the connection details :
Host tamara User dave #Port 443 IdentityFile /home/dave/.ssh/webproxy
We've left the option 'Port 443' commented out for now. The use of Port 443 is a trick to get round corporate firewalls, some of which block outgoing connections to port 22. But the use of port 443 is non-standard and optional.
You should now be able to perform key based login to the server. Try this to see if it works.
dev$ ssh tamara
Now we can lock down the ssh server. Protect it by turning off root login and password login.
We also want to listen on port 443 (normally used by https). Port 443 is problematic to block as it is used by https traffic. Companies can't interfere with https traffic as it would break the certificates and encryption, so corporate proxies are forced to pass traffic on port 443 unaltered.
You need to edit the file /etc/ssh/sshd_config
$ sudo sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config $ sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config $ sudo sed -i 's/Port 22/Port 22\nPort 443/g' /etc/ssh/sshd_config
Verify this with :
$ cat /etc/ssh/sshd_config | grep -v "^[ \t]*#" | grep -v "^[ \t]*$" | egrep "Root|Pass" PermitRootLogin no PermitEmptyPasswords no PasswordAuthentication no
Now restart the ssh server. Also, uncomment the 'Port 443' line we added to the dev machine's ~/.ssh/config earlier.
$ sudo /etc/init.d/ssh restart
You now have an ssh key-only login that prevents root and password logins. This is good for security as hackers will try to attack your server. Reducing their options improves safety.
You may wish to allow access to multiple machines. Simply copy their keys onto the server, and cat them into ~/.ssh/authorized_keys. You will need to do this via your dev machine, as you can no longer use password login from another machine. You can also add / modify their ~/.ssh/config file in the same way. Be carefull to cat append using >>, not >, or you will overwrite existing key authorisations.
It is a good idea to have several machines that can access the server. Otherwise if you lose your computer you won't be able to log back into the server. Though with a VPS you can always wipe the server and start again.
Now for the firewall. Assuming that we are only running an ssh server and an internal squid server on this machine, the firewall rules can be very simple indeed.
Create and edit the file /etc/init.d/firewall
$ sudo vi /etc/init.d/firewall
Add this text :
#!/bin/bash ### BEGIN INIT INFO # Provides: firewall # Required-Start: $local_fs $network # Required-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: firewall # Description: iptables script ### END INIT INFO IPTABLES=/sbin/iptables # Flush all rules $IPTABLES -F # Open ssh $IPTABLES -A INPUT -p tcp --dport 22 -j ACCEPT # Listen on 443 (https) port as well. $IPTABLES -A INPUT -p tcp --dport 443 -j ACCEPT # Allow localhost access for local servers # squid server $IPTABLES -A INPUT -p tcp -s localhost --dport 3128 -j ACCEPT # Allow ESTABLISHED, RELATED $IPTABLES -A INPUT -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT $IPTABLES -A INPUT -p udp -m state --state RELATED,ESTABLISHED -j ACCEPT # Drop everything else $IPTABLES -A INPUT -j DROP # FIN
Make the script executable
$ sudo chmod +x /etc/init.d/firewall
This ensures that all external ports except ssh port 22 are blocked. Only port 3128, the default squid port, is enabled, and only internally.
Make this persistent across reboots :
$ sudo update-rc.d firewall defaults
Now that the machine has a secure firewall and key-only ssh access, make sure it is up to date.
$ sudo apt-get update $ sudo apt-get upgrade
You will probably need a reboot after this :
$ sudo reboot
Now that we have a secure machine, we can install the squid proxy.
$ sudo apt-get install squid
The only config item I changed was the logging output. Edit the file /etc/squid/squid.conf and ensure the log is turned off :
$ sudo sed -i 's/# access_log.*/access_log none/g' /etc/squid/squid.conf
Then restart it so the log directive takes effect :
$ sudo /etc/init.d/squid restart
You should now have a fully configured server with ssh, firewall and squid proxy. You can only access it using ssh . The squid server is only visible internally to the machine.
Accessing the server
I'll cover a better way to do this in part 2.
But having set up a proxy server, you need to access it. You blocked external access to port 3128 so you can only see squid from the server. So you need a way to connect to it.
The solution is to use ssh. ssh is an extraordinary tool. It gives you not just a secure shell, but a file transport mechanism (eg. scp) and a powerful forwarding mechanism. It is the port forwarding that we'll use to access the squid server.
We have a number of options here, depending on how you want to use your proxy. The simplest option is just to use it locally. Run this in a terminal on your home machine :
dev$ ssh -N -L 3128:localhost:3128 tamara
You can now configure your browser to use the proxy. Again, there are a number of ways to do this. The simplest is in Firefox, go to Preferences / Advanced / Network / Connection settings. You can set them to
Manual, proxy: localhost, port: 3128
and press "OK"
Test your connection. This site reads your external ip address, which should be that of your proxy. It then shows a map of where it thinks you are.
In part 2 I'll describe how you can build a router that will manage the proxy connection for you. A router that will isolate you and protect you from the network you use to connect to the internet.