Using a VPN
A common complaint for Linux users goes along the lines of: “I want to make service XYZ available over the internet but only to authorised users. How do I do this securely?” where XYZ could be VNC, NFS, Samba or a local web server. The solution to this problem depends on the exact service you want to forward and what methods it has for authentication and security. Some are better than others, but it still means potentially having to take care of several services and making sure all are secure. You don’t have the same problem on your local network because, unless anyone can use your computers, you have only authenticated users.
An alternative to exposing individual parts of your network to the web at large is to allow authorised users to join the network from outside, as if they were connected to the local network directly. This is what a Virtual Private Network (VPN) does – it sets up a secure, encrypted tunnel between a computer and the network. While the tunnel goes over the public internet, all traffic between your computer and the network stays inside the tunnel, encrypted and secure.
The are a few different VPN implementations, but we will use OpenVPN here. This, as the name implies, is a completely open system that uses the well established OpenSSL for connections. Before you do anything else, set up your router to forward port 1154 to the computer that will be acting as the OpenVPN server on your LAN, or you won’t be able to connect. At its simplest, you can connect a computer to a network by running the first command on a computer on the network, the OpenVPN server, and the second command on the remote computer you want to connect to the network, the client:
sudo openvpn --remote clientaddress --dev tun 1 --ifconfig 10.0.1.1 10.0.1.2 sudo openvpn --remote serveraddress --dev tun 1 --ifconfig 10.0.1.2 10.0.1.1
The --remote option gives the name or IP address of the computer to connect to, while the two addresses given to --ifconfig are allocated to the local and remote computers respectively, which is why they’re reversed in the second command. These addresses should be in one of the reserved private ranges, but on a different subnet to your LAN or horrible things will happen. The VPN is a separate network, with the server acting as a gateway between it and your LAN. If you get an unknown device error about tun on either computer, load the tun module with
sudo modprobe tun
While this works, in so far as it connects to one computer on your network, it’s hardly convenient, as you need someone to run the command at each end of the link, and you need to know IP addresses in advance, which isn’t much help when connecting from a mobile broadband dongle or using wireless hotspots at various caffeine suppliers.
Create your certificates, for the server and clients, using the build scripts provided with OpenVPN.
The solution is to run the server permanently (or at least when it’s likely to be needed) on your LAN, to allow connections from any IP address and use certificates to authenticate any computers that try to connect. Most of the set-up is done on the server, in a terminal as the root user (Ubuntu users prefix everything with sudo). Your OpenVPN installation should include scripts to manage this in /usr/share/openvpn/easy-rsa. We need to edit these, so copy the easy-rsa directory to /etc/openvpn to stop your settings being clobbered by an update. Edit the vars file to set the KEY_* variables – do not leave any of them blank. The next step is to create a master Certificate Authority (CA) certificate with:
source ./vars/ ./clean-all ./build-ca
You will be asked a number of questions, but you can normally press Enter at each one, as the answers are preset in the vars file. This creates a certificate in the keys directory, which is used to sign any server and client certificates we are about to create. Make the server certificate with:
As before, accept the defaults, but set the Common Name to the name of the server, then respond with y when asked if you want to sign and commit the certificate. Now run this command for each client that you want to connect, using the same client name on the command line and in response to the Common Name question.
This script builds a key that is enough to connect to the VPN, so anyone with access to the computer can do so. If this is a laptop and you have no other form of protection against a thief doing this, use build-key-pass instead of build-key to create a key locked with a password. There is one more file to build, with:
Copy ca.crt and that computer’s .crt and .key files to the /etc/openvpn directory of each computer. On the server, you also need to copy ca.key and the dh1024.pem file that the build-dh command created. Do this securely, using either a physical medium or SSH – don’t email them, as anyone with these files can connect to your network. Make sure the permissions on the secret .key file are set to rw-------, copying via a FAT formatted USB key will set them to something more permissive, and unacceptable.
Don't forget to set your router to forward incoming requests to port 1194 to the same port number on the computer running the OpenVPN server.
The server and client each need a configuration file in /etc/openvpn. The sample files, usually installed in /usr/share/doc/openvpn/examples/sample-config-files, are the best starting point. Copy server.conf to /etc/openvpn/openvpn.conf, and on the server edit it. Most of the file is comments, and the default settings are good, but make sure the ca, cert, key and dh settings correspond to the files you created, preferably using full paths.
Copy the client.conf file to /etc/openvpn/openvpn.conf on the client and edit it. Change the remote line to point to the IP address (or hostname) of your server and the port it will listen on (the default is 1194). You can have more than one remote line, in which case they will be tried in turn until a connection is made.
remote gateway.example.com 1194 remote 126.96.36.199 1194
Use the public IP address of your internet connection.
If your gateway is behind a router, forward port 1194 to the gateway server in your router’s configuration. Edit the cert and key lines to contain the names of the client’s certificate and key files. If you changed any of the defaults in the server config, make sure that you change any corresponding settings here. Now you can see how things work by running:
on the server and then on the client. Running ifconfig on each computer should show a tun interface with an address in the 10.8.0.* range (unless you changed this in the configs), and you should be able to ping between them. Once you have verified it’s working, you can use your distro’s services manager to have OpenVPN start at boot on your server.
Start the server and client from a terminal when testing. It will let you know exactly what it is doing.
Reaching the whole network
So far, we’ve connected two computers, but we want the client to be able to access the whole of the local network, not just the server. OpenVPN has altered the routing table on the client to pass all traffic for the 10.8.0.0 network over the VPN. To have the server route traffic for the LAN to the correct destination, add this to its configuration file:
push “route 192.168.1.0 255.255.255.0”
using the appropriate address and netmask for your LAN. This not only sets up routing on the server, but the server uses this to send the correct routing settings to a client when it connects. If you give the route -n command after opening the VPN on the client, it will show something like:
Destination Gateway Genmask Flags Metric Ref Use Iface 192.168.1.0 10.8.0.2 255.255.255.0 UG 0 0 0 tun0
This will work well, providing your OpenVPN server is also the gateway for the network, which means that the other computers on the LAN will send all non-LAN traffic to it anyway. If this is not the case, you have two choices. You can alter the routing tables of any computers on the network that you want to be accessible from the VPN by running this command on them:
route add -net 10.8.0.0 netmask 255.255.255.0 gw 192.168.1.1
or you can alter your router’s configuration to route all traffic to the 10.8.0.0 network via your server – 192.168.1.1 in this example. Some routers support OpenVPN directly, particularly those using the DD-WRT or OpenWrt operating systems. If you have such a router, you can transfer the responsibility to it using the web interface.
The details vary according to the firmware it is running, but it’s basically a case of pasting the contents of your certificate, key and configuration files into text boxes in the router’s web interface.
If you use a router that supports OpenVPN, such as this DD-WRT based device, you can run the server on your router and avoid the need to have one particular computer running all the time.
First published in Linux Format magazine