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!)
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.
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
, 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;
tincd -K 2048 -c `pwd`
When running tincd
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 …
ifconfig $INTERFACE down
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;
PingInterval = 3
PingTimeout = 2
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
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.
-----BEGIN RSA PUBLIC KEY-----
-----END RSA PUBLIC KEY-----
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.
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
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
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