Monday, February 29, 2016

Protecting privacy with personal VPN

There are more and more examples of privacy violation in the Internet. Even in supposedly democratic countries, the governments want to know what the citizens are up to, "just in case". For example, in my country the police have recently been given the power to eavesdrop phone calls and intercept any forms of electronic transmission, without prior permission from the court.
Thinking that you have nothing to worry about if you do nothing wrong is naive. Any information gathered about you can be sooner or later used against you. It can also leak, be stolen, or even sold by a corrupted police officer. Remember, that your home network consists of many devices, not only your personal computer (or computers). Your phones, tablets, TV boxes, and sometimes even your refrigerator as well as other home appliances, constantly transmit various data over the network. Many of them use RESTful APIs over unsecured HTTP channels, because it's simpler and helps keeping the costs low. But this is only part of the problem. Even if you make sure you use only encrypted HTTPS protocol, your software still needs to perform unencrypted DNS queries to translate domain names to IP addresses. This way anyone eavesdropping your network traffic can gather information about the sites you visted, how often and for how long. This so called "metadata" can reveal much more information about you than the actual content you view with your Internet browser. Metadata can tell a lot about your interests, habits, in which banks you keep your money (because you visit their sites often), what you buy and where you do your shopping, even where you plan to spend next weekend (because you just checked weather forecast for this place with your mobile phone). It can even be used to check if you are at home and whether it can be safely robbed. You can be profiled quickly and without much effort, just by intercepting transmission from you home router. Moreover, your traffic can be redirected (through DNS spoofing) to false web servers, to make you reveal some sensitive data, like logins and passwords. Also, your devices automatically synchronizing time over the Internet can be tricked into using a particular timestamp. The timestamp is a crucial element of digital cryptography: controlling the clock of your computer will make it generate predictable cryptographic keys, which then can be easily broken.

So, how can you protect yourself? My solution was to built a personal Virtual Private Network. I have a VPN server hosted in the cloud, and a home router configured as VPN client, passing all my Internet traffic through that server over an encrypted "tunnel". Of course it makes my Internet connection a little slower, because every data packet, including metadata queries (like DNS and NTP), must be encrypted and transferred to the cloud, where it "jumps out" and begins its regular way through the network, but this way my network traffic cannot be eavesdropped. The server is hosted in another country, so the government can no longer watch me "just in case", because they need a court permission to claim my data from a foreign cloud provider.

How is this better than TOR, or any other peer-to-peer network? - you may ask. With TOR, the idea is that your data travels around the world through other people's computers, but also other people's data travels through yours, and you have no control over it. Frankly speaking, I don't feel comfortable knowing that my computer can be indirectly used by criminal offenders for their illegal activities.

I used tinc to build the VPN. It's fairly easy to configure and available for many operating systems. I used Ubuntu for the server, and OpenWRT router for the client, but you can use a different configuration (for example an old PC with Linux as a router).

1. Server configuration.

First, you need to set up a server. Tinc has very minimal hardware requirements (a few megabytes of disk space and memory), and I use it successfully with Ubuntu 14.04 installed on a virtual server with 512MB RAM. First, you need to be root to perform all necessary tasks. Swith to user root with:
sudo bash
Then install the tinc package:
apt-get install tinc
Next, create a proper directory tree and configuration files using the following commands:
mkdir -p /etc/tinc/vpn/hosts
echo 'vpn' > /etc/tinc/nets.boot
echo 'ifconfig $INTERFACE netmask' > /etc/tinc/vpn/tinc-up
chmod +x /etc/tinc/vpn/tinc-up
echo 'ifconfig $INTERFACE down' > /etc/tinc/vpn/tinc-down
chmod +x /etc/tinc/vpn/tinc-down
echo 'Name=server' > /etc/tinc/vpn/tinc.conf
echo -e 'Subnet=\nMode=switch' > /etc/tinc/vpn/hosts/server
This makes the basic scaffolding of your VPN server configuration. Now you must add the server's public IP address to the /etc/tinc/vpn/hosts/server configuration file (replace "" with the public IP address of the server):
echo '' >> /etc/tinc/vpn/hosts/server
Notice ">>" instead of ">" when using this command!
The file /etc/tinc/vpn/hosts/server should now have the following content:
Where, again, "Address=" field contains the public IP address of your server.
Now you need to generate an encryption key used to protected data transmission over the VPN tunnel:
tincd -n vpn -K
Confirm the defaults pressing Enter. After this operation you will see a new file /etc/tinc/vpn/rsa_key.priv containing the private key, and a new section in /etc/tinc/vpn/hosts/server file containing the public key. As their names state, the public key can be visible to anyone, and the private key must remain secret and cannot be revealed.

You can now start tinc server (as user root) with:
tinc -n vpn
Now you should be able to list the new network interface with:
ifconfig vpn
And it sould have a section saying "inet addr:". You can turn it off for now with:
tincd -n vpn -k
Notice lower case "-k", not uppercase "-K", which was used to generate the key.

2. Client configuration.

Now for the router (client) configuration, you also need to install tinc package. With OpenWRT you can do it either through the web interface or via the command line with the following command:
opkg update && opkg install tinc
With Ubuntu as the client the procedure is the same as with the server:
sudo apt-get install tinc
Now you need to configure the client. On the router (or the computer acting as a router) switch to user root with:
sudo bash
Then run the following set of commands:
mkdir -p /etc/tinc/vpn/hosts
echo 'vpn' > /etc/tinc/nets.boot
echo 'ifconfig $INTERFACE netmask' > /etc/tinc/vpn/tinc-up
chmod +x /etc/tinc/vpn/tinc-up
echo 'ifconfig $INTERFACE down' > /etc/tinc/vpn/tinc-down
chmod +x /etc/tinc/vpn/tinc-down
echo -e 'Name=client\nConnectTo=server' > /etc/tinc/vpn/tinc.conf
echo -e 'Subnet=\nMode=switch' > /etc/tinc/vpn/hosts/client
tincd -n vpn -K
You are almost done. Your router is now the client of the VPN network, and you need to make sure that the server and the client know about each other, so they can communicate. To achieve this, you need to copy /etc/tinc/vpn/hosts/server file to the client, and /etc/tinc/vpn/hosts/client to the server, so that the contents of the /etc/tinc/vpn/hosts directory is the same on both hosts and contains both client and server files.
Now start tinc both on the client and the server (again, as user root) with:
tincd -n vpn
After a short while the connection should be established and you should be able to ping the server ( from the client ( and vice versa. If something goes wrong, you can start tinc with debugger to see what's going on:
tincd -n vpn -d -D
The messages are elaborate enough to allow you quickly locate the source of the problem.

3. Routing setup.

You are almost done here. The client and the server can see each other, but you want to pass all your traffic through this connection, right? So there are two more things to be done.

First, you need to configure the server to forward the traffic between the VPN and the outside world:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -s -j ACCEPT
iptables -t nat -A POSTROUTING -s -j MASQUERADE
The above commands should be run every time you start the server, so you can add them to /etc.rc.local startup script (along with the command to start tinc).

Second, on the client side, you need to modify the routing table to make the VPN server a default gateway for all the internet traffic passing through the client (i.e. your router), except the VPN server itself. So, check the routing table on your VPN client with:
route -n
You should see something similar to this:
Destination  Gateway   Genmask       Flags Metric Iface U     0      br-lan U     0      eth0.1       UG    0      eth0.1
Look at the Gateway column in the line where the Destination says (meaning: any address) - it's the default gateway. In this case it's and it's the address of you nearest outside world neighbour, probably your Internet provider's modem or router. You need to make sure that you leave this route open for the connection between your client and your server to work.
Do the following magic commands (replacing with your own default gateway, and with the public IP of your VPN server):
route add gw
route del default gw
route add default gw
What happens here is that you leave the traffic to your VPN server via the old route, and replace the gateway for all other traffic with the encrypted VPN. If you did it properly, you should now be able to ping any Internet address from your client. Also, the traceroute (or any other similar utility) should show your traffic going first through the tunnel:
root@OpenWrt:~# traceroute
traceroute to (, 30 hops max, 38 byte packets
 1 (  107.456 ms  106.969 ms  114.178 ms
 2  ...
If you don't want to modify the routing table by hand every time you start the router, you can add the commands to /etc/tinc/vpn/tinc-up script. Don't add them to /etc/rc.local, because that script is executed early on startup, when address may not yet be available, and the commands will fail.

Now the last step. You need to allow traffic between your local network and the VPN, similar to what you did on the server side. Assuming your router's (the VPN client's) LAN address is (it's a common default for most routers), you need to run the following commands:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -s -j ACCEPT
iptables -t nat -A POSTROUTING -s -j MASQUERADE
You can safely add them to /etc/rc.local startup sequence.

Now connect to your router and go to any address from You should see the public IP of your VPN server, not your home router. It indicates that all your Internet traffic now goes through the VPN.

And finally, one more thing. If you haven't done it yet, change the primary DNS server on your router to and secondary to (they are Google DNS servers). Otherwise all your DNS queries will go through the VPN server back to your Internet provider, and you don't want that to happen, do you?

No comments: