Lock Down Your Network with Tinc

Tutorials – Tinc

Article from Issue 197/2017

Block attackers from all your machines with a virtual mesh network.

We'll be honest, computer security is something we'd rather not have to deal with. It'd be much nicer if we lived in a world where we didn't have to remember different complex passwords for every service we used, or have to carefully configure every network-facing service to ensure it remains secure against attack, but we have to live with the reality of the world we live in.

Attacks are commonplace and getting more sophisticated every day. Weak passwords will be broken sooner or later, and any open port on the Internet is under a constant bombardment from scanners trying to find vulnerabilities (just take a look at your logfiles if you don't believe us). Network security is usually dealt with on a service-by-service basis, but we're going to look at a way of locking everything down with a single bit of software.

Where most secure protocols (e.g., SSH or HTTPS) are designed to bring two computers together securely, Tinc brings the same technology to groups of computers. It allows you to create a mesh network between multiple machines regardless of where they're physically located where all communication between the machines is encrypted and authenticated. (See the "A Whirlwind Guide to Communications Protocols" box for more information.)

A Whirlwind Guide to Communications Protocols

There are loads of different ways computers communicate with each other. Here's the information you need to know about the security of some of the most popular:

  • HTTP – When most people think of computers communicating over the internet, they think of the Hypertext Transfer Protocol (HTTP) that serves up web pages. It has essentially no security features.
  • HTTPS – With the web becoming more important, HTTPS was developed to improve on the shortcomings of HTTP. By pushing plain HTTP over Secure Socket Layer (SSL) and more recently Transport Layer Security (TLS), the same functionality is retained, but the browser can be reasonably sure that the web server is who they say they are. HTTPS relies on trusted certificate authorities to verify the identity of websites; if one of these authorities is compromised, then the entire authentication of HTTPS is in question.
  • RCP – Rarely seen these days, Remote Copy (RCP) is the traditional way of moving files between machines on a network. It has no security.
  • SCP – Like RCP, SCP copies files between machines via a network; however it adds the security afforded by SSH, which includes some authentication and strong encryption (provided it is set up).
  • Rsync – Rsync builds on SCP with more features for deciding which files to copy. While the security aspects are similar, Rsync is more powerful.
  • FTP – File Transfer Protocol is a communications protocol optimized for downloading large files. Like HTTP, it was designed in a simpler time when computer security wasn't seen as a significant problem and should be avoided if security is a concern.
  • SFTP – By wrapping a secure layer over FTP, SFTP gives the user more security guarantees than the original protocol.
  • Gopher – A protocol for retrieving documents stored in a hierarchical structure that was briefly popular during the mid-nineties. Nowadays, the protocol's main purpose seems to be eliciting nostalgia from aging geeks. It is unsecure.
  • Email – Although it's not a protocol on its own, the global email system works using a range of protocols including SMTP, IMAP, and POP. The major problem with email from a security perspective is that it's impossible to know exactly how your message is transmitted once it leaves your computer. It may be secure; it may not be.
  • PGP/GPG – Pretty Good Privacy (also implemented by Gnu Privacy Guard) is a protocol for encrypting data that is to be sent over another protocol. It's most commonly used for email, but also works on any system that allows you to send text. It can be technical to use but offers strong encryption and authentication even over channels that don't normally have such protections.
  • Telnet – A remote access protocol that allows you to log into a terminal session via a network connection. It has no encryption and should not be deployed. Treat any Telnet system you encounter with deep suspicion.
  • SSH – Secure Shell is a remote access protocol that's more advanced than Telnet both in terms of features and security. Care should be taken when configuring an SSH server as it is possible to configure insecurely, and SSH ports on the Internet are heavily attacked.
  • Signal – An instant messaging protocol developed by Whisper Systems for instant messaging. It's used in the app of the same name and WhatsApp to provide strong end-to-end encryption. It's our recommended protocol for instant messaging.

We're all familiar with encryption – where data is obfuscated so that only the people who should have access to it do – but authentication is a different aspect of security entirely. Authentication means knowing that you're really communicating with who you think you are. For example, the HTTPS protocol for secure web traffic is authenticated, but only at one end. This means that when you go to https://www.linuxvoice.com, you can be confident that you're really communicating with the Linux Voice server, but the Linux Voice server doesn't know who you are unless it goes through some additional steps (such as a password login).

Regular SSH is what we would term slightly authenticated. When you connect to a server for the first time, you're shown the fingerprint of the server to verify (but honestly, who does?), and you should see a warning any time this changes. With Tinc, every machine has a public key, and both sides of any communication are verified to be who they really claim to be.

You might find Tinc in your software repositories, or you can install it from source fairly easily (Figure 1). For example, to install on a CentOS machine, you first need to grab the dependencies (which are just the gcc compiler and some header files for the libraries used).

Figure 1: Tinc isn't only for your Linux machines; there are clients for most desktop OSs (including OS X and Windows) and Android as shown here.
sudo yum install gcc zlib-devel lzo-devel openssl-devel

Grab the source code from the website [1]. The latest version at the time of writing was 1.0.30. Then unzip it and open a terminal in the new directory. Building the software is then a case of running the three classic build commands

sudo make install.

You can check that it's worked by entering tincd at the command line. You should get a message telling you about the various options you need to run the network successfully.

Configuring Tinc is quite easy, but there are a few things that you have to get in place. Before any of that, though, you need to decide on how to allocate your IP addresses. Tinc doesn't do this automatically, so you need to make the decision for yourself. There are several private IP address ranges that you can choose from including 192.168.x.x (but this is often used for physical networks), and 10.x.x.x (each x can be between 1 and 255).

The most important thing to decide when picking an IP address range is which other networks your machines are connected to. You can use the ip addr command to show what IPs are currently associated with a machine and then pick an entirely different range. For our network, we're going to use to (or at least we would if we had enough machines to fill this range). It's not too difficult to change the IP in this range that a particular machine has, but it's best to get it right the first time. If your machines are already ordered in some way, give them IPs ordered in the same way.

There's no distinction between the server and client in Tinc. Every machine is just a part of the network. However, for all the machines to connect together, some machines need to act as points of contact that the others reach out to when the network is first established. The most important thing to think about here is which machines are reachable from which other machines.

For example, you might be using a cluster of cloud servers to provide services for each other and want them to connect securely. If they're all in the same hosting provider, then they probably all have private IP addresses (or a private DNS hostname) that they can use to communicate. In this case, any or all of them could be the hosts to connect to. However, if you want to connect to this network from outside, you'll need at least one machine with a public IP address that you can connect to. Once you're connected to one machine, Tinc will route traffic to other machines even if you can't connect directly to their main network interfaces. For this reason, it's a great way of securing machines spanning multiple physical networks.

Each machine requires five bits of configuration: a conf file, a tinc-up script, a tinc-down script, a private key, and a set of hosts files. Let's look at them in this order. First, the configuration file. This should look something like the following:

Name = machine1
AddressFamily = ipv4
Interface = tun0
ConnectTo = MainMachine

In this example, machine1 is the name of the current computer and MainMachine is the name of the computer that this should connect to when Tinc starts. You can have multiple ConnectTo lines, so your network is resilient if one or more machines go down. Tinc can have multiple networks on the same machine, so all the configuration files are separated out by network. As such, this file should go in the configuration for the network you're building (which we'll call LinuxVoiceNet, but you can replace this with your own name).

Installing from source puts the configuration files in /usr/local/etc/tinc, but if you've installed via a package manager, this might be /etc/tinc. Whichever, put the above file inside this configuration root as LinuxVoiceNet/tinc.conf.

The next thing we need to consider is tinc-up, which is a script that runs when the network is started and just makes sure the interface is configured properly. This might sound a little scary, but it's actually really simple. The following is all we need for this machine:

ifconfig $INTERFACE

This will assign the machine the IP The netmask of means that anything matching an IP like 10.0.0.x can be found on this network. The $INTERFACE part isn't a typo on our part. Tinc will insert the correct network interface here when it runs the script.

Tinc-down is even simpler and just needs to contain the following:

ifconfig $INTERFACE down

Both of these should live in the LinuxVoiceNet folder (as tinc-up and tinc-down, respectively).

So far, we've just been configuring the network, but now we need to look at security, and this comes down to keys. You can generate a good, strong key with:

sudo tincd -n LinuxVoiceNet -K4096

This will put the appropriate files in the appropriate places. You should have a private key in the main configuration directory and a file at LinuxVoiceNet/hosts/machine1 (or whatever you called this machine). In this hosts directory, we'll keep a copy of the public keys of all the machines we connect to, but we'll deal with that in a minute. First, we need to edit the newly created machine1 file to include a bit more information. Open it up in a text editor and add the following lines to the top of it:

Address = <main IP or domain>
Subnet =

Here we need to tell the other machines how they can contact this machine in order to make a Tinc connection. This could be a public IP, a private IP on the same network as the other machines, or a domain name. Strictly speaking, this is only necessary on machines that others connect to, but it's best to have it on as many machines on your Tinc network as possible, as this can ease congestion on the network.

You need to follow all of the above steps on all of your machines (this is a great candidate for automating via a configuration management tool, such as Ansible). Once you've done that, gather all the files from the hosts directory (there should be one named after each machine) and copy them so that every machine has a copy of every other machine in the hosts folder. Once that's done, you can start the network with a simple:

tincd -n LinuxVoiceNet -D d3

Remember that you need to do this on the machine that the others connect to first.

This will run the network daemon in the current terminal, which makes it easy to see where any problems are. However, for normal running, you'll want a way of starting the service in the background. This varies a little between distros, particularly at the moment as most modern distros use systemd (Figure 2), but many older (but still supported) distros are using sys-v init. It's easy to tell if you're using systemd. Just run the following command:

cd /etc/systemd
Figure 2: Systemd caused a lot of controversy when it first came out, but it's been adopted by most major distros and makes services easy to create.

If you get an error saying that this folder doesn't exist, then you're not running systemd and you need to create a script. If you move into the directory, then you're running systemd, and you need to create a unit file.

The start scripts and unit files only define how Tinc starts and not how it runs, so there's absolutely no problem running a network with some machines using unit files and some using startup scripts. You can also launch Tinc manually on some machines as well if you want (Figure 3).

Figure 3: Launching Tinc will create a new network interface (tun0), which has its own IP address. This interface is only for traffic on the virtual network.

Let's look at systemd unit files, as this covers most modern distros.

Description=tinc vpn
ExecStart=/usr/local/sbin/tincd -n LinuxVoiceNet

If you're using sys-v init, however, you'll need to write a shell script that's run at the appropriate time to start and stop the service. These scripts are rather big, so we can't fit the whole thing in here, but you can follow the example online [2] to quickly get one running (Figure 4).

Figure 4: Take a look at the Tinc website for inspiration on more advanced configurations.

Whichever option you choose, you're ready to get started. First, stop the Tinc process running if you haven't already with Ctrl+/, then run

service tincd start

to start tincd.

You can configure your system to automatically start Tinc on boot with either

systemctl enable tincd.service

if you used a systemd unit file, or the following if you've used a sys-v init script:

chkconfig tincd on

That really is all it takes to lock down a distributed network of machines. With Tinc running, you can share whatever you need safely and secure in the knowledge that prying eyes can't see what you're doing. Using Tinc isn't an excuse to ignore good security practices, but it does give you an extra layer of protection against the hordes of attackers roaming the Internet.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95