There are many options when it comes to VPN software, the one you may have come across is called
OpenVPN, the one I’m going to cover is the one that I use which is called
tinc.
Why not OpenVPN
OpenVPN has a number of Pro’s, one for example is that it’s fairly cross-platform. But then given it’s all about security, one might ask what’s the point if you’re going to install it on certain other Operating Systems. Con’s however, I can think of many, but the fundamental issue is that it’s a point-to-point protocol, which is to say the least limiting. (caveat; I’ve not used OpenVPN for some time, so if any of this has changed, please update me!)
Why “tinc”
tinc implements a
mesh protocol, which means you’re not just connected to
one server. There is no effective difference between clients and servers, you become a
node and are able to connect to any other node. (which is rather better than point-to-point in terms of resilience) Again in terms of resilience, fail-over / reconnects tend to be transparent. People familiar with OpenVPN will be aware that if your OpenVPN connection drops for any reason, by the time it’s reconnected your SSH sessions may well have expired or decided to drop. With
tinc this typically doesn’t happen unless you suffer a prelonged outage or try to put lots of data over your paused ssh session.
So for example if you’re running a remote system upgrade over a VPN and you’ve forgotten to start it with
screen, OpenVPN is a bit of a worry.
Installing …
Whereas this can be scripted, I’m doing this in detail from
first principles to hopefully demonstrate how it all fits together. This example is using
Ubuntu, it will be the same or similar on other distros.
We’re going to create a VPN between two local machines called
star and
moon, so starting on machine
star; (I’m working as
root, if you want to do this as a
user, insert
sudo’s as required);
apt install tinc
This will create a skeleton setup in
/etc/tinc. Now by default
tinc supports, nay expects you to want to run multiple
vpn’s, so inside this folder you will want to create a sub-folder for your VPN, which we’re going to call
space. Inside this sub-folder we’re then going to want to create a private and public key;
mkdir space
cd space
tincd -K 2048 -c `pwd`
When running
tincd with
-K it will automatically generate the keys for you. 2048 is the size of key to use (you can pick your size so long as it’s at least 512). Then you need to tell it where to put the keys, the long hand is
/etc/tinc/space, however
pwd will generate the current working directory, and back-ticks will evaluate the command in-line.
Next you need a couple of scripts to manage your VPN interface, these are literally templates that I guess
tincd could create for you, but …
file:
tinc-down
#!/bin/sh
ifconfig $INTERFACE down
file:
tinc-up
#!/bin/sh
ifconfig $INTERFACE 192.168.240.1 netmask 255.255.255.0
Note here that we’ve chosen an address range to run our VPN on. If you don’t know much about addresses, all you really need to know is whether you have another network on that address range, and if the answer is that you don’t know, this one is probably Ok.
Note about address ranges;
Anything on 192.168.x.x is a range that is not carried on the Internet, hence is safe to use for your local network. The caveat here is that your local router will probably be using something in this range for your local network and you need to avoid overlapping it. For a BT hub / router the default is typically 192.168.1.0/24, so usually 192.168.2 and up is safe.
Once you’ve created your scripts, make sure the computer can execute them;
chmod +x tinc-down tinc-up
The remaining file we need to look at is the main
tinc configuration file,
tinc.conf, into which we will need to put;
Name=star
Port=8620
PingInterval = 3
PingTimeout = 2
ConnectTo=moon
And we’re done with the basic configuration. Next we need to tell
tinc about the hosts it should expect to hear from, so we’ll need to create a
hosts folder, and into it we can start by adding a file to describe
this host.
mkdir hosts
cd hosts
vi star
We have another choice to make at this point, each different
tinc VPN runs on it’s own
port, and even if you only have one VPN, you still need to allocate a port for it. In this instance we’re going to use
8620. We’re also going to need to know the addresses of the two machines.
In this example both machines are directly addressable via the local area network. The same example can be used if only one machine is directly addressable, for example if one machine is hosted on the Internet. If neither machine is directly addressable (say both machines are behind NAT routers), the example needs a slight modification, but is still relatively easy.
file:
/etc/tinc/space/hosts/star
Address=192.168.1.123
Subnet=192.168.240.1
Port=8620
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEArLeDNz9V/tllDDopJXzuB119Jnpui67sKpHIIhbXn52atXPJnMc7
fz2CsK3ecns377hZyNGfaBFXVihQeQ19GmUQvmp1DdEx3RchtHSg4b9xFL/FywGd
Xw3Snd+R1YfNSl7mxgNLno/CoT6XPgcEDuG4I56G6hfz0sqEFV80IEXimeGRLPQl
cEU5QRR+VMbY1Fxp759IS3C60zf40NtBLhuvAJ6isOBOH8vZDJG9cN1TWjzOcSPn
L3QMTZ8+t3/jbnUxJtbZ3yapxYEEyEAQCzuVJR9gBV1P2xQUqVvL4/1sOzzEstOp
bafWo9aa/GHe5dpWdR7XNDWmIdHFbdzIvwIDAQAB
-----END RSA PUBLIC KEY-----
So
your version of this file will contain the real
address of your
star, the
Subnet will match the address you chose in
tinc-up, and the
port will be your chosen port. The
key section will be the contents of your
/etc/tinc/space/rsa_key.pub which was auto-generated by
tincd -K.
So we’re now pretty much done with
star and you need to repeat this process with
moon. Things that will be different;
- tinc-up will contain a different address (i.e. the address you wish to use to refer to moon)
- tinc.conf the name will be moon and the ConnectTo will be star
- hosts/moon the address will be the actual IP address of moon, the Subnet will be the address from moon’s tinc-up, and the key will be moon’s rsa_key.pub.
So
moon will be identical to
star, except for the few configuration items that are particular to that individual host. There is one remaining task, which is to copy the contents of
hosts between machines. i.e.
star needs the hosts entry for
moon, and
moon needs the hosts entry for
star.
Your folder should now contain files something like this;
$ find . -ls
drwxr-xr-x 3 root root 4096 Sep 5 12:17 .
-rwxr-xr-x 1 root root 35 Sep 5 12:16 ./tinc-down
drwxr-xr-x 2 root root 4096 Sep 5 12:18 ./hosts
-rw-r--r-- 1 root root 480 Sep 5 12:18 ./hosts/moon
-rw-r--r-- 1 root root 481 Sep 5 12:18 ./hosts/star
-rwxr-xr-x 1 root root 66 Sep 5 12:17 ./tinc-up
-rw-r--r-- 1 root root 68 Sep 5 12:17 ./tinc.conf
-rw------- 1 root root 427 Sep 5 12:16 ./rsa_key.pub
-rw------- 1 root root 1676 Sep 5 12:16 ./rsa_key.priv
And assuming you have no firewalls in place to stop communication between the two machines you should now be able to start the VPN on each machine and communicate. So on each machine;
service tinc@space start
Now add a couple of handy references to the VPN addresses you’ve chosen into your
/etc/hosts file;
192.168.240.1 star
192.168.240.2 moon
And from any machine you should be able to ping yourself and the other node;
$ ping -c1 star
PING star (192.168.240.1) 56(84) bytes of data.
64 bytes from star (192.168.240.1): icmp_seq=1 ttl=64 time=0.052 ms
--- star ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.052/0.052/0.052/0.000 ms
$ ping -c1 moon
PING moon (192.168.240.2) 56(84) bytes of data.
64 bytes from moon (192.168.240.2): icmp_seq=1 ttl=64 time=0.742 ms
--- moon ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.742/0.742/0.742/0.000 ms
Adding more nodes …
And this is the beauty of a mesh network, you’ve now seen all the configuration there is. For another node, repeat the above instructions. All you need is to pick a new IP address from the 192.168.240 range (say
3), and when you have a new file for your new node in
hosts, copy it to the other nodes, so they know about it. Then amend
ConnectTo on the nodes you would like to make an initial connection to your new node.
Note on ConnectTo
The mesh network implements a degree of auto-discovery however it effectively needs to be pre-seeded using ConnectTo. So if star connects to moon, then moon connects to new_node, when the connection is up, star will work out that new_node is there and whether it can make a direct connection. The key here is that if the initial connection betweem star and moon fails, it won’t know about new_node, so it’s best to have a couple of ConnectTo’s per node so a single node failure doesn’t stop the pre-seeding process.
Now, I didn’t say the configuration was completely painless (!) however it is relatively straightforward when you have a recipe to follow. The only thing I would add would be to start the VPN when each node starts up, you will need to add;
systemctl enable tinc@space
To each node. If the
@ in the
service command and
systemctl command is new to you, it’s used to manage multiple instances of the same service. So the format is
service @
instance.
If anyone tries this out, do let me know, especially any bits I can improve on. Just a general plug,
tinc is a low-memory high performance secure VPN. Like anything it can be mis-configured or abused, but thus far over the last (10?) years, it’s not given me any cause for concern.
1 post - 1 participant
Read full topic