Setting up a VPN can seem like a daunting task. There are some high-priced options out there, but most of those are closed source, and therefore not to be trusted. Instead, the internet has a variety of open source and free VPN server solutions. OpenVPN is a good one, but does not offer a distrbuted style “mesh network”. It requires a dedicated server, which may or may not be in your budget or scope. But, tinc-vpn offers “point to point” VPN as well as server style and everything in between.
As stated on the project homepage , tinc is a Virtual Private Network (VPN) daemon that uses tunnelling and encryption to create a secure private network between hosts on the Internet. It’s is an excellent way to create connections to servers and workstations over the internet. In particular, I came across it while looking for free alternatives to logmein.com. While tinc does not provide any sort of interface, it can be used to solve the problem of “permanent” remote access.
There are not a lot of great tutorials on the internet for tinc. So, we are going to take an in-depth look at exactly how to set-up a “server” and a client.
For starters, let’s build out our network on paper before we attempt to get it working in real life. In order to get around firewalls on remote networks, we have “punch through” by initiating a connection from within those remote networks. Routers assume that connections made by computers on the “inside” of their networks have permission to do so, and let those connections be made. Additionally, those same routers allow the return traffic through the firewall because: “what good is a request of we don’t allow the response back through to the requester?”
Thus, we need a centralized VPN “server” that all our remote nodes can connect to. Once we have that set-up, we can connect other computers (like a management workstation and a remote file server that we need to manage) to the VPN via the central node.
Setting up a VPN: the tinc VPN Basics
Up until now, I have been referring to a “server” for the central node. tinc does not have a “server”mode because all nodes are configured the same. For our purposes, the “server” we are configuring is a regular node that doesn’t connect to anyone else (pro-actively). Instead, it’s the place where “everyone else” connects to the network.
With that piece of information out of the way, let’s get back to the basics.
Order of Operations: How tinc reads configuration files (and in what order).
When tincd is started, the first thing it does is check /etc/tinc/nets.boot. Each line in that configuration file can contain the name of a network to join. For this tutorial, we are just going to use a single network, but you could set-up as many networks for your server as you wanted to.
After reading /etc/tinc/nets.boot, tinc goes to each network folder looking for a tinc.conf file. So, if your nets.boot file has a single entry: myvpn, tincd will look in /etc/tinc/myvpn/ for a tinc.conf file. (It will look for /etc/tinc/myvpn/tinc.conf).
Once it finds the tinc.conf file for this network, it will read it, and access information under the hosts directory for that network. So, if we use the “ConnectTo” directive to tell tincd that it should connect to a given server, it will look in /etc/tinc/myvpn/hosts/ for the value of that directive.
So, for example, if we are configuring a client (node) to ConnectTo a server that we have nicknamed “MainServer”, we’d use a directive like this:
Once tincd sees the value of that ConnectTo directive is “MainServer” it will immediately look in /etc/tinc/myvpn/hosts for the MainServer file. (It will want /etc/tinc/myvpn/hosts/MainServer). Once it finds that file, it will load configuration information about that host (node) from that file.
But, it also looks in the hosts directory to find information about itself! So, to get two computers to connect to one another, you must (at minimum) have two files in the hosts/ directory for your connections. One for the “server” and one for the “client”
But, tinc also uses the files in the hosts/ directory to get information about itself! As you’ll see in our example, we will create a file in hosts/ for machines each node will connect to as well as the node itself.
Authentication: How Each Node Knows It’s OK To Grant Access to the VPN Network.
tinc uses RSA authentication to authenticate nodes. If you’re not sure how RSA works, take a look at our RSA authentication primer. But for now, let’s suffice it to say that this is a key exchange. Each end of the node has to provide a key to be accepted by the other nodes
This means that each node has to have its own public / private RSA key pair. But don’t let that intimidate you, we’ll show you had to make these without having a Ph.D. in mathematics.
Preparing Your Computer
Whether you are running a server or a workstation, you have to make sure you have fulfileld the system requirements for tinc. They are:
- A kernel that supports tun/tap. If you are using a modern version of any Debian based system, you’re already set here. (This includes Debian, Ubuntu, Mint, and other flavors). Most other modern Linux systems support this right out of the box. Except those distros that require you compile the kernel in order to install… but then again, if you’re using one of those experts-only distros, you won’t need much help installing this feature.
- Make sure you have the following packages installed and available:
How to Install tinc-VPN
In Debian based systems, this is easy. Just use:
apt-get install tinc
Do this for all the machines that will be participating in the VPN.
Setting up the Network
Do it on Paper First! Write down:
- Public IP of the “server”.
- VPN IP of the “server”.
- VPN IP of the “client(s)”
In our case, we are going to assume:
- Public IP of the “server”: 12.345.67.89.
- VPN IP of the “server”: 192.168.100.1
- VPN IP of the client: 192.168.100.2
How To: Setting up the tincd “Server”
Setting up the “server” simply means we need to setup the files tinc uses in the order that it uses them:
- the network directory
- tinc.conf in the network directory
- the hosts directory for the network
- the individual host files for hosts on the network.
First, change to the /etc/tinc/ directory, and edit the nets.boot file. We are going to add a single line to the end of the file: myvpn.
echo 'myvpn' >> nets.boot
Next, create the myvpn folder under /etc/tinc because tincd is going to look in that folder after it discovers that nets.boot has “myvpn” as one of the entries.
Next, create the tinc.conf file, which tells tincd how to setup its own node. Using your favorite Linux text editor (vim!), create tinc.conf with these two lines in the file:
Save the file.
This, of course, assumes you are running a Debian based system that has a device at /dev/net/tun. Most do. But, if your distro doesn’t, you can change this to something like /dev/tap0 of you have tunctl installed. But for our example, we’re going to leave it likeÂ this.
Now, if you remember from our order of operations above, as soon as tincd finds this file, it’s going to look for mycpn in the hosts directory. So, we need to create that directory so we can create the file.
But we don’t create the myvpn file that goes in hosts/! That will be created for us when we generate the RSA keys for this system. So, let’s generate the keys:
tincd -n myvpn -K
If you haven’t set-up the tinc.conf file correctly (or yet), This command will generate two keys: rsa_key.priv and rsa_key.pub. Both of these will appear in your /etc/tinc/myvpn/ directory (because we specified -n myvpn in the command above). These two keys represent the keys to THIS system. So, we’ll keep the private key whereÂ it is, but let’s move the public key into hosts:
mv /etc/tinc/myvpn/rsa_key.pub /etc/tinc/myvpn/hosts/vpnserver
If you DID correctly set-up your tinc.conf file, tincd will read that file, and find the name of this computer and use it to put the public key in the correct spot. So, instead of creating the public key as /etc/tinc/myvpn/rsa_key.pub, it should read Name=vpnserver, and put the public key in /etc/tinc/myvpn/hosts/vpnserver.
Right now, that file (/etc/tinc/myvpn/hosts/vpnserver) only contains the RSA public key, but we need to add some more information about this node to that file. So, let’s edit that file:
and add some lines to it to identify the node both to itself, and later, to the other nodes on the network. We’ll add two lines: Subnet and Address.
Subnet identifies the IP address this node will have on the VPN network. Address identifies (to other nodes) what IP address they should use to connect to this server.
-----BEGIN RSA PUBLIC KEY-----
-----END RSA PUBLIC KEY-----
Lastly, we need to set-up the tinc-up and tinc-down scripts. These scripts execute automatically when the VPN network comes up and when the VPN network goes down (respectively).
Essentially, we need these scripts to create the interface that the computer will use to talk to the VPN network when the VPN comes up, and then remove it when the VPN service stops.
Create a file called /etc/tinc/myvpn/tinc-up, and put the following lines of code in it:
ifconfig $INTERFACE 192.168.100.1 netmask 255.255.255.0
Because tincd runs in router mode by default, we do not need to put any other configurations (or routes) in this file because tincd will build and maintain routing tables for us.
Now for tinc-down, which will execute when we shut down tinc and disconnect from the VPN. Create a file: /etc/tinc/myvpn/tinc-down, and add this content.
ifconfig $INTERFACE down
This removes the vpn adapter from the system when the vpn service is shut down.
Once you have created those two files, you have to grant them permission to execute:
chmod +x /etc/init.d/myvpn/tinc-*
Now, you’re ready to start the tinc vpn server:
If all goes well, you should see the following in syslog:
tincd 1.0.19 (Apr 22 2013 21:45:36) starting, debug level 9
/dev/net/tun is a Linux tun/tap device (tun mode)
Executing script tinc-up
Listening on 0.0.0.0 port 655
Listening on :: port 655
If you see any errors, google them, fix them, and then restart tinc until the errors resolve.
Setting up the VPN Clients
Because a “server” and a “client” have just ONE difference (the Server doesn’t use a ConnectTo directive in tinc.conf), The basic setup is exactly the same. So, follow the steps above to setup your client(s), but note these differences in /etc/tinc/myvpn/tinc.conf:
- Clients will use a “ConnectTo” directive.
- Clients need to be uniquely named. The server uses Name=vpnserver, but the clients should have their own individual (unique) network names. Name=Client01 would work, so would Name=George.
There is two major differences for clients in the public rsa key, which is stored in hosts/ for the network:
- The Name directive must be unique
- The subnet must be a different IP for the client than the server has.
Here is an example tinc.conf for a client:
Notice the Name is unique (this is for “George’s computer”) and it also uses the ConnectTo directive to tell this client node to connect to the main vpn server node.
Here is an example /etc/tinc/myvpn/hosts/George01 file:
-----BEGIN RSA PUBLIC KEY-----
-----END RSA PUBLIC KEY-----
- the file name matches the Name directive in the /etc/tinc/myvpn/tinc.conf file.
- The Subnet is different than the server. In this case, it is the next available address, but it doesn’t half to be. It could be any address on the 192.168.100.0/24 network.
Now, your client is setup! Start the tincd service and watch /var/log/syslog for errors that need correcting:
The Last Step: Exchanging Keys
As mentioned in the introduction as well as in our RSA Authentication Primer, both sides of the VPN need to exchange public keys so that the “conversation” can actually take place.
So, let’s use secure copy to copy the vpnserver public key to the client. From the client:
scp email@example.com:/etc/tinc/myvpn/hosts/vpnserver .
If (when) prompted to enter your password, enter the password for the VPN server’s root account.
Now, let’s send the client public key to the vpn server:
scp George01 firstname.lastname@example.org:/etc/tinc/myvpn/hosts
Testing Your Connection
If all has gone well, you’ll now be able to ping the machines over the vpn network. From the “client” node:
ping -c4 192.168.100.1
should give you:
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_req=1 ttl=64 time=1.15 ms
64 bytes from 192.168.100.1: icmp_req=2 ttl=64 time=0.905 ms
64 bytes from 192.168.100.1: icmp_req=3 ttl=64 time=0.979 ms
64 bytes from 192.168.100.1: icmp_req=4 ttl=64 time=0.943 ms
Form the server node, you should be able to execute:
ping -c4 192.168.100.2
PING 192.168.100.2 (192.168.100.2) 56(84) bytes of data.
64 bytes from 192.168.100.2: icmp_req=1 ttl=64 time=1.15 ms
64 bytes from 192.168.100.2: icmp_req=2 ttl=64 time=0.905 ms
64 bytes from 192.168.100.2: icmp_req=3 ttl=64 time=0.979 ms
64 bytes from 192.168.100.2: icmp_req=4 ttl=64 time=0.943 ms
Special thanks to Guus Sliepen, who not only developed tinc-vpn, but also generously provides support via his tinc-vpn mailing list