hosaka

⊕ a tessier-ashpool subsidiary

tinc 1.1 overview

⊕ 2016-01-01

tinc (there is no cabal) is an encrypted, compressed, and open-source mesh networking VPN. Simply put, it allows for indirect connections to hosts. With version 1.1 being in alpha for a long time, it is always good to take another look at why it is so interesting and why it offers so much. I also wanted to write about, specifically, version 1.1 instead of the other tutorials for tinc on the internet (which seem to completely ignore the tinc manuals and try and hack everything together) that focus only on 1.0.

I am going to attempt to stay as close to the man pages as possible, and if I stray at all from tinc standards feel free to contact me

tinc's advantage

tinc is very unique in many ways, but one of the ways to make it clear is to show a quick situational example that we will use for the rest of the write-up:

You have 3 hosts.

An important concept with tinc is that there is no difference between client and server, just whom to make connections with. Since tinc is meshing that would allow denver.int and ny.int to communicate through dallas even though they are both behind a firewall or are in a NAT configuration. tinc also has the ability to do UDP hole punching. In fact, in our example there is a good chance that with the help of dallas and hole punching denver.int and ny.int will be able to communicate directly. This of course depends on the firewall rules that ny.int has in place.

tinc 1.1 vs tinc 1.0

tinc 1.1 (which has been available for years, but is considered in alpha) adds very real world cryptographic and usability benefits, choosing to adopt:

usage

As always, before beginning our setup I highly recommend a good dose of RTFM. tinc is very easy to use and configure and leaves very little to guess work. After compiling and installing tinc 1.1 from http://www.tinc-vpn.org/download/ on all of the hosts it is time to create a network. For our fictional example we want to create a network with the name sprawl. We will begin by logging into dallas.

We will first initialize the sprawl and the dallas host:

dallas:~$ sudo tinc -n sprawl init dallas

This will initialize the network config, host config, and host keys. As a note the tinc name does not have to be the hostname, dallas in this case, but is required to be unique within the tinc network. tinc will place these files in either /etc/tinc/sprawl/ or /usr/local/etc/tinc/sprawl/ and a quick peek into the directory should look something like this:

dallas:~$ sudo ls -l1hp /usr/share/etc/tinc/sprawl
-rw-------    1     200 Dec 31 17:34 ed25519_key.priv
drwxr-xr-x    2    4.0K Dec 31 22:31 hosts/
-rw-------    1    1.6K Dec 31 17:34 rsa_key.priv
-rwxr-xr-x    1      62 Dec 31 20:49 tinc-up
-rw-r--r--    1      12 Dec 31 17:34 tinc.conf

Now we are not configuring tinc in switch mode so we just want each of these hosts to get a single assigned ip in the network. To do this we do the following:

dallas:~$ sudo tinc -n sprawl add Subnet 10.0.1.1/32

We then want to expose the public address of the dallas node to the tinc network:

dallas:~$ sudo tinc -n sprawl add Address 31.3.3.7

Now it's time to look at what the configuration looks like, this can be done in two ways. By using tinc directly:

dallas:~$ sudo tinc -n sprawl edit dallas

Or just looking at the file directly:

dallas:~$ sudo cat /usr/local/etc/tinc/sprawl/hosts/dallas

So far the configuration should look similar to the following, which has the host public keys (RSA and Ed25519) and the configuration options we set.

Name = dallas
-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAw0+bVYL/FVnooIFWboCIJDxX5CeOPfkckjQGAgoNJScD+9lIgChT
SPfNOdgrIqCk8+Aq4rurgUZOHKxLRgLtNdiH6f2w1cpkNlpSxWdHvVoZns43vMe+
mMeS6XcD8jkUp9hp8kQaJbseA5PgIYU/YAKcYrxfuGuf+UtbYA3TYu+J/Gk4JxBm
GALKk7XcPxuTKm8H8HJTzJPBi9BumADaDQpPApLf4+Yc8HqGrH3WREtzb0ev/gbj
9Rr0AjA/4msoX1x4MYyX4ZUTeIFaWp1qmAF7zrdamLI3e17jTeQeGwRAXbl0iEaL
CjYCIE7U8wXr/ttp4qzstBhjuIEWaOenwQIDAQAB
-----END RSA PUBLIC KEY-----
Ed25519PublicKey = Ur44MHR17plJjpqdnNHE5ZiBLmIOsB3ZRxYlrVIbJxH
Subnet = 10.0.1.1/32
Address = 31.3.3.7

tinc itself is very simple and doesn't actually handle any of the host configuration for interface management, instead you have to manually set up the tinc-up script that gets run when tinc creates its virtual interface. I will explain some of the other scripts and their usages later.

dallas:~$ sudo tinc -n sprawl edit tinc-up
#!/bin/sh
ifconfig $INTERFACE 10.0.1.1 netmask 255.255.255.0

At this point dallas is ready to start up and begin taking connections. But first, lets get the other sites setup and their configs shared to the other hosts. The initial setup is very similar except we want to change the Subnet option and make a few other changes to fit the host:

denver.int:~$ sudo tinc -n sprawl init denver
denver.int:~$ sudo tinc -n sprawl add Subnet 10.0.1.2/32

Now in order to connect to dallas we need to use the tinc ConnectTo option instead of Address:

denver.int:~$ sudo tinc -n sprawl add ConnectTo dallas

Edit the tinc-up script and change it to the address used in the previous Subnet option.

denver.int:~$ sudo tinc -n sprawl edit tinc-up

Now we need to distribute the client configurations to all the hosts, this can be done manually by using the tinc options export and import or if you have ssh access you can use those in combination with exchange-all to update all the configs on both hosts as follows:

denver.int:~$ sudo tinc -n sprawl export | \
ssh dallas.example.org -t "sudo tinc -n sprawl exchange-all" | \
sudo tinc -n sprawl import

Now both hosts should have the same configuration files in hosts. While it is not 100% necessary to have configs for every host due to tinc's meta-connection model, I like to keep everything tidy and not throwing any warnings, so I will often run the previous one-liner across all the machines when I add a new host (tinc+ansible is very handy or even cron). As for the final host ny.int do the exact same configuration we did for denver.int except with Subnet giving it's own ip for the network (and in tinc-up). I used 10.0.1.3 for ny.int and ny as it's Name variable for init. After that is complete it is time to get everything up and running, connect to dallas and simply run tincd in non-daemonizing mode so we can see any errors that are produced:

dallas:~$ sudo tinc -n sprawl start -D
denver.int:~$ sudo tinc -n sprawl start -D
ny.int:~$ sudo tinc -n sprawl start -D

Now we can finally test out our configuration and make sure everything is running. From denver.int simply try and connect to ny.int

denver.int:~$ ping -c 3 -q 10.0.1.3
PING 10.0.1.3 (10.0.1.3) 56(84) bytes of data.

--- 10.0.1.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 91.487/91.856/92.397/0.462 ms

Congratulations you now have a very simple tinc setup. It is important to note that most people are used to VPNs that route all their traffic through as the default gateway, tinc does not do that by default. If this behavior is desired see http://www.tinc-vpn.org/examples/redirect-gateway/

scripts and variables

tinc has a collection of scripts that if created will be run at certain points of VPN events. You have already used the tinc-up which runs when tinc starts up. This is incredibly useful and makes tinc even more powerful, some of the available scripts are:

It should also be pointed out that tinc inherits environmental variables, which means that you can use shell variables inside of configuration files. The best example is the Name variable. If you set Name to $HOST it will resolve that variable for tincs use (Name is also unique in that if $HOST is not set it also gets resolved through a call to gethostname();).

files

For a full list of commands used on each host in the example see the following files: