Tinc: Difference between revisions
imported>MrVanDalo A Tutorial to create a simple Tinc VPN network. |
imported>MrVanDalo mNo edit summary |
||
Line 1: | Line 1: | ||
= What is tinc = | = What is tinc = | ||
Line 39: | Line 36: | ||
== Creatie host files == | == Creatie host files == | ||
The hostfile can have a lot of parameters ((here is an overview)[https://www.tinc-vpn.org/documentation/Host-configuration-variables.html]). | The hostfile can have a lot of parameters ( (here is an overview)[https://www.tinc-vpn.org/documentation/Host-configuration-variables.html] ). | ||
But these are the minimum needed for our setup | But these are the minimum needed for our setup | ||
Line 46: | Line 43: | ||
* <code>Subnet</code> : The tinc network IP-Address (the one we want to connect to after the tinc network is setup). | * <code>Subnet</code> : The tinc network IP-Address (the one we want to connect to after the tinc network is setup). | ||
Also the host files need to contain the public keys for this host. | |||
So lets create the two hostfiles. Asuming we have generated keys for the 2 machines and they are stored in the folders <code>heinz</code> and <code>peter</code>. | So lets create the two hostfiles. Asuming we have generated keys for the 2 machines and they are stored in the folders <code>heinz</code> and <code>peter</code>. | ||
Line 113: | Line 110: | ||
Now we have everything we need to configure the <code>services.tinc</code> module in our <code>configuration.nix</code> files on both machines. | Now we have everything we need to configure the <code>services.tinc</code> module in our <code>configuration.nix</code> files on both machines. | ||
You can recognise that the <code>services.tinc."${myMeshName}".hosts</code> have the same content on both machines. | |||
It is also '''''Important''''' that you set <code>services.tinc."${myMeshName}".name</code> to a machine that is contained in the <code>services.tinc."${myMeshName}".hosts</code>. | |||
=== /etc/nixos/tinc.nix on heinz === | === /etc/nixos/tinc.nix on heinz === | ||
Line 140: | Line 141: | ||
services.tinc.networks."${myMeshName}"= { | services.tinc.networks."${myMeshName}"= { | ||
name = "heinz"; # who are we in this network. | |||
name = "heinz"; | |||
debugLevel = 3; # the debug level for journal -u tinc.private | debugLevel = 3; # the debug level for journal -u tinc.private | ||
Line 164: | Line 157: | ||
# if you don't set the path as string, it will import the file in | # if you don't set the path as string, it will import the file in | ||
# in the nix/store where everybody can read it. | # in the nix/store where everybody can read it. | ||
Ed25519PrivateKeyFile = "/root/secrets/ | Ed25519PrivateKeyFile = "/root/secrets/heinz/ed25519_key.priv" | ||
PrivateKeyFile = "/root/secrets/ | PrivateKeyFile = "/root/secrets/heinz/rsa_key.priv" | ||
''; | ''; | ||
hosts = { | hosts = { | ||
# content of hosts_heinz (from above) | |||
heinz = '' | heinz = '' | ||
Address = 192.168.178.25 | Address = 192.168.178.25 | ||
Line 177: | Line 171: | ||
-----END RSA PUBLIC KEY----- | -----END RSA PUBLIC KEY----- | ||
''; | ''; | ||
# content of hosts_peter (from above) | |||
peter = '' | peter = '' | ||
Address = 192.168.178.21 | Address = 192.168.178.21 | ||
Line 216: | Line 211: | ||
services.tinc.networks."${myMeshName}"= { | services.tinc.networks."${myMeshName}"= { | ||
name = "peter"; # who are we in this network. | |||
name = "peter"; | |||
debugLevel = 3; # the debug level for journal -u tinc.private | debugLevel = 3; # the debug level for journal -u tinc.private | ||
Line 235: | Line 222: | ||
# if you don't set the path as string, it will import the file in | # if you don't set the path as string, it will import the file in | ||
# in the nix/store where everybody can read it. | # in the nix/store where everybody can read it. | ||
Ed25519PrivateKeyFile = "/root/secrets/ | Ed25519PrivateKeyFile = "/root/secrets/peter/ed25519_key.priv" | ||
PrivateKeyFile = "/root/secrets/ | PrivateKeyFile = "/root/secrets/peter/rsa_key.priv" | ||
''; | ''; | ||
hosts = { | hosts = { | ||
# content of hosts_heinz (from above) | |||
heinz = '' | heinz = '' | ||
Address = 192.168.178.25 | Address = 192.168.178.25 | ||
Line 248: | Line 236: | ||
-----END RSA PUBLIC KEY----- | -----END RSA PUBLIC KEY----- | ||
''; | ''; | ||
# content of hosts_peter (from above) | |||
peter = '' | peter = '' | ||
Address = 192.168.178.21 | Address = 192.168.178.21 |
Revision as of 16:15, 30 May 2018
What is tinc
Tinc is an awesome vpn mesh.
How peer to peer setup in tinc
The following tutorial will setup a very simple scenario, where you create a tinc vpn between to computers in the same network. In this scenario heinz
will connect to peter
. But this will make heinz
also visible to peter
.
It can easily be improved to a setup with muliple computers involved.
Overview
The following diagram shows the network we want to setup.
network : private +--------------------------+ +--------------------------+ | name : heinz | | name : peter | | real ip : 192.168.178.25 | ---> | real ip : 192.168.178.21 | | tinc ip : 10.1.1.25/24 | | tinc ip : 10.1.1.21/24 | +--------------------------+ +--------------------------+
Generate keys
Tinc clients need to verify themself to each other, is done by keys. There are multiple ways to generate your keys.
Manual
nix-shell -p tinc_pre --run "tinc generate-keys 4096"
The command ask you where to put the keys. If you hit enter a few times it will generate 4 files. (instead of hitting enter you can give it different file path)
/etc/tinc/rsa_key.priv
/etc/tinc/rsa_key.pub
/etc/tinc/ed25519_key.priv
/etc/tinc/ed25519_key.pub
Creatie host files
The hostfile can have a lot of parameters ( (here is an overview)[1] ).
But these are the minimum needed for our setup
Address
: The real world IP-Address of this machineSubnet
: The tinc network IP-Address (the one we want to connect to after the tinc network is setup).
Also the host files need to contain the public keys for this host.
So lets create the two hostfiles. Asuming we have generated keys for the 2 machines and they are stored in the folders heinz
and peter
.
cat >hosts_heinz <<EOF Address = 192.168.178.25 Subnet = 10.1.1.25 EOF cat heinz/rsa_key.pub >> hosts_heinz cat heinz/ed25519_key.pub >> hosts_heinz cat >hosts_peter <<EOF Address = 192.168.178.21 Subnet = 10.1.1.21 EOF cat peter/rsa_key.pub >> hosts_heinz cat peter/ed25519_key.pub >> hosts_heinz
Setup interface
We have to configure the tinc tunel interface.
networking.interfaces
The simplest way is to us the networing module. But it has some minor flaws on package updates.
# for heinz networking.interfaces."tinc.private" = [ { address = 10.1.1.25; } ];
tinc-up/tinc-down
A more robust but more complicated way to configure the interaces is the tinc-up
and tinc-down
scripts.
First we have to create the scripts:
# for heinz environment.etc."tinc/private/tinc-up".source = pkgs.writeScript "tinc-up-private' #!${pkgs.stdenv.shell} ${pkgs.nettools}/bin/ifconfig $INTERFACE 10.1.1.25 netmask 255.255.255.0 ''; environment.etc."tinc/private/tinc-down".source = pkgs.writeScript "tinc-down-private'' #!${pkgs.stdenv.shell} /run/wrappers/bin/sudo ${pkgs.nettools}/bin/ifconfig $INTERFACE down '';
For the tinc-down
we need to use sudo because we the user tinc.private
who starts the service is not able to tear the interface down.
So we have to give make sure this user can call sudo without entering a password.
security.sudo.extraRules = [ { users = [ "tinc.private" ]; commands = [ { command = "${pkgs.nettools}/bin/ifconfig"; options = [ "NOPASSWD" ]; } ]; } ];
Open the Firewall
The computer which you connect to need to open some ports.
networking.firewall.allowedUDPPorts = [ 655 ]; networking.firewall.allowedTCPPorts = [ 655 ];
use service.tinc module
Now we have everything we need to configure the services.tinc
module in our configuration.nix
files on both machines.
You can recognise that the services.tinc."${myMeshName}".hosts
have the same content on both machines.
It is also Important that you set services.tinc."${myMeshName}".name
to a machine that is contained in the services.tinc."${myMeshName}".hosts
.
/etc/nixos/tinc.nix on heinz
{ config, pkgs, ... }: let myMeshIp = "10.1.1.25"; myMeshMask = "255.255.255.0"; myMeshName = "private"; in { # open tinc ports # --------------- networking.firewall.allowedTCPPorts = [ 655 ]; networking.firewall.allowedUDPPorts = [ 655 ]; # simple interface setup # ---------------------- networking.interfaces."tinc.${myMeshName}" = [ { address = myMeshIp; } ]; # configure tinc service # ---------------------- services.tinc.networks."${myMeshName}"= { name = "heinz"; # who are we in this network. debugLevel = 3; # the debug level for journal -u tinc.private chroot = false; # otherwise addresses can't be a DNS interfaceType = "tap"; # tun might also work. extraConfig = '' # connect to peter # ---------------- # check AutoConnect as alternative option. ConnectTo = peter # Keys # ---- # if you don't set the path as string, it will import the file in # in the nix/store where everybody can read it. Ed25519PrivateKeyFile = "/root/secrets/heinz/ed25519_key.priv" PrivateKeyFile = "/root/secrets/heinz/rsa_key.priv" ''; hosts = { # content of hosts_heinz (from above) heinz = '' Address = 192.168.178.25 Subnet = 10.1.1.25 Ed25519PublicKey = asdf ... -----BEGIN RSA PUBLIC KEY----- bla blub ... -----END RSA PUBLIC KEY----- ''; # content of hosts_peter (from above) peter = '' Address = 192.168.178.21 Subnet = 10.1.1.21 Ed25519PublicKey = asdf ... -----BEGIN RSA PUBLIC KEY----- bla blub ... -----END RSA PUBLIC KEY----- ''; }; }; }
/etc/nixos/tinc.nix on peter
{ config, pkgs, ... }: let myMeshIp = "10.1.1.21"; myMeshMask = "255.255.255.0"; myMeshName = "private"; in { # open tinc ports # --------------- networking.firewall.allowedTCPPorts = [ 655 ]; networking.firewall.allowedUDPPorts = [ 655 ]; # simple interface setup # ---------------------- networking.interfaces."tinc.${myMeshName}" = [ { address = myMeshIp; } ]; # configure tinc service # ---------------------- services.tinc.networks."${myMeshName}"= { name = "peter"; # who are we in this network. debugLevel = 3; # the debug level for journal -u tinc.private chroot = false; # otherwise addresses can't be a DNS interfaceType = "tap"; # tun might also work. extraConfig = '' # Keys # ---- # if you don't set the path as string, it will import the file in # in the nix/store where everybody can read it. Ed25519PrivateKeyFile = "/root/secrets/peter/ed25519_key.priv" PrivateKeyFile = "/root/secrets/peter/rsa_key.priv" ''; hosts = { # content of hosts_heinz (from above) heinz = '' Address = 192.168.178.25 Subnet = 10.1.1.25 Ed25519PublicKey = asdf ... -----BEGIN RSA PUBLIC KEY----- bla blub ... -----END RSA PUBLIC KEY----- ''; # content of hosts_peter (from above) peter = '' Address = 192.168.178.21 Subnet = 10.1.1.21 Ed25519PublicKey = asdf ... -----BEGIN RSA PUBLIC KEY----- bla blub ... -----END RSA PUBLIC KEY----- ''; }; }; }