Tinc: Difference between revisions

imported>MrVanDalo
mNo edit summary
imported>Aforemny
m Add missing quotes around `address`'s value
 
(9 intermediate revisions by 5 users not shown)
Line 7: Line 7:
The following tutorial will setup a very simple scenario, where you create a tinc vpn between two computers in the same network. In this scenario <code>heinz</code> will connect to <code>peter</code>. But this will make <code>heinz</code> also visible to <code>peter</code>.
The following tutorial will setup a very simple scenario, where you create a tinc vpn between two computers in the same network. In this scenario <code>heinz</code> will connect to <code>peter</code>. But this will make <code>heinz</code> also visible to <code>peter</code>.


It can easily be [https://www.tinc-vpn.org/examples/ improved to a setup with muliple computers] involved.
It can easily be [https://www.tinc-vpn.org/examples/ improved to a setup with multiple computers] involved.


== Overview ==
== Overview ==
Line 22: Line 22:
== Generate keys ==
== Generate keys ==


Tinc clients need to verify themself to each other, which is done by keys. There are multiple ways to generate your keys. Here is one.
Tinc clients need to verify themselves to each other, which is done by keys. There are multiple ways to generate your keys. Here is one.


<pre>nix-shell -p tinc_pre --run &quot;tinc generate-keys 4096&quot;</pre>
<pre>nix-shell -p tinc_pre --run "tinc generate-keys 4096"</pre>
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)
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)


Line 32: Line 32:
* <code>/etc/tinc/ed25519_key.pub</code>
* <code>/etc/tinc/ed25519_key.pub</code>


== Creatie host files ==
== Create host files ==


The hostfile can have a lot of parameters ([https://www.tinc-vpn.org/documentation/Host-configuration-variables.html here is an overview]).
The hostfile can have a lot of parameters ([https://www.tinc-vpn.org/documentation/Host-configuration-variables.html here is an overview]).
Line 43: Line 43:
Also the host files need to contain the public keys for this host.
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. Assuming we have generated keys for the 2 machines and they are stored in the folders <code>heinz</code> and <code>peter</code>.


<pre>cat &gt;hosts_heinz &lt;&lt;EOF
<pre>cat &gt;hosts_heinz &lt;&lt;EOF
Line 60: Line 60:
== Setup interface ==
== Setup interface ==


We have to configure the tinc tunel interface.
We have to configure the tinc tunnel interface.


=== networking.interfaces ===
=== networking.interfaces ===
NOTE: There are changes proposed to nix configuration, for using networkd based configuration instead of the current fragile scripted configuration, that will hopefully make the following section obsolete.


The simplest way is to us the networing module. But it has some minor flaws on package updates.
The simplest way is to use the networking module. But it has some minor flaws on package updates.
 
<syntaxHighlight lang=nix># for heinz
networking.interfaces."tinc.${networkName}".ipv4.addresses = [ { address = "10.1.1.25"; prefixLength = 24; } ];
</syntaxHighlight>
 
Another author has experienced problems with the network failing to restart when using the above to configure interfaces.
The following snippet '''seems''' to fix that (until perhaps a more proper fix is upstreamed?):
<syntaxHighlight lang=nix>
  # Start the unit for adding addresses if Tinc is started
  systemd.services."tinc.${networkName}".wants = [ "network-addresses-tinc.${networkName}.service" ];
  # Stop the unit for adding addresses if Tinc is stopped or restarted
  systemd.services."network-addresses-tinc.${networkName}".partOf = [ "tinc.${networkName}.service" ];
  # Start the unit for adding addresses after the Tinc device is added
  systemd.services."network-addresses-tinc.${networkName}".after = [ "sys-subsystem-net-devices-tinc.${networkName}.device" ];
</syntaxHighlight>


<pre># for heinz
networking.interfaces.&quot;tinc.private&quot; = [ { address = 10.1.1.25; } ];
</pre>
=== tinc-up/tinc-down ===
=== tinc-up/tinc-down ===


Line 75: Line 88:
First we have to create the scripts:
First we have to create the scripts:


<pre># for heinz
<syntaxHighlight lang=nix># for heinz
environment.etc.&quot;tinc/private/tinc-up&quot;.source = pkgs.writeScript &quot;tinc-up-private'
environment.etc = {
  #!${pkgs.stdenv.shell}
    "tinc/private/tinc-up".source = pkgs.writeScript "tinc-up-private" ''
  ${pkgs.nettools}/bin/ifconfig $INTERFACE 10.1.1.25 netmask 255.255.255.0
        #!${pkgs.stdenv.shell}
'';
        ${pkgs.nettools}/bin/ifconfig $INTERFACE 10.1.1.25 netmask 255.255.255.0
environment.etc.&quot;tinc/private/tinc-down&quot;.source = pkgs.writeScript &quot;tinc-down-private''
    '';
  #!${pkgs.stdenv.shell}
    "tinc/private/tinc-down".source = pkgs.writeScript "tinc-down-private" ''
  /run/wrappers/bin/sudo ${pkgs.nettools}/bin/ifconfig $INTERFACE down
        #!${pkgs.stdenv.shell}
'';</pre>
        /run/wrappers/bin/sudo ${pkgs.nettools}/bin/ifconfig $INTERFACE down
    '';
};</syntaxHighlight>
For the <code>tinc-down</code> we need to use sudo, because the user <code>tinc.private</code> who starts the service is not able to tear down the interface.
For the <code>tinc-down</code> we need to use sudo, because the user <code>tinc.private</code> who starts the service is not able to tear down the interface.


So we have to make sure this user can call sudo without entering a password.
So we have to make sure this user can call sudo without entering a password.


<pre> security.sudo.extraRules = [
<syntaxHighlight lang=nix> security.sudo.extraRules = [
     {
     {
       users    = [ &quot;tinc.private&quot; ];
       users    = [ "tinc.private" ];
       commands = [
       commands = [
         {
         {
           command  = &quot;${pkgs.nettools}/bin/ifconfig&quot;;
           command  = "${pkgs.nettools}/bin/ifconfig";
           options  = [ &quot;NOPASSWD&quot; ];
           options  = [ "NOPASSWD" ];
         }
         }
       ];
       ];
     }
     }
   ];</pre>
   ];</syntaxHighlight>
== Open the Firewall ==
== Open the Firewall ==


The computer which you connect to needs to open some ports.
The computer which you connect to needs to open some ports.


<pre>networking.firewall.allowedUDPPorts = [ 655 ];
<syntaxHighlight lang=nix>networking.firewall.allowedUDPPorts = [ 655 ];
networking.firewall.allowedTCPPorts = [ 655 ];</pre>
networking.firewall.allowedTCPPorts = [ 655 ];</syntaxHighlight>
== use service.tinc module ==
== use service.tinc module ==


Line 115: Line 130:
=== /etc/nixos/tinc.nix on heinz ===
=== /etc/nixos/tinc.nix on heinz ===


<pre>{ config, pkgs, ... }:
<syntaxHighlight lang=nix>{ config, pkgs, ... }:


let
let


   myMeshIp  = &quot;10.1.1.25&quot;;
   myMeshIp  = "10.1.1.25";
   myMeshMask = &quot;255.255.255.0&quot;;
   myMeshMask = "255.255.255.0";
   myMeshName = &quot;private&quot;;
   myMeshName = "private";


in {
in {
Line 127: Line 142:
   # simple interface setup
   # simple interface setup
   # ----------------------
   # ----------------------
   networking.interfaces.&quot;tinc.${myMeshName}&quot; = [ { address = myMeshIp; } ];
   networking.interfaces."tinc.${myMeshName}" = [ { address = myMeshIp; } ];




   # configure tinc service
   # configure tinc service
   # ----------------------
   # ----------------------
   services.tinc.networks.&quot;${myMeshName}&quot;= {
   services.tinc.networks."${myMeshName}"= {


     name          = &quot;heinz&quot;;      # who are we in this network.
     name          = "heinz";      # who are we in this network.


     debugLevel    = 3;            # the debug level for journal -u tinc.private
     debugLevel    = 3;            # the debug level for journal -u tinc.private
     chroot        = false;        # otherwise addresses can't be a DNS
     chroot        = false;        # otherwise addresses can't be a DNS
     interfaceType = &quot;tap&quot;;        # tun might also work.
     interfaceType = "tap";        # tun might also work.


     extraConfig  = ''
     extraConfig  = ''
Line 150: Line 165:
       # 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 = &quot;/root/secrets/heinz/ed25519_key.priv&quot;
       Ed25519PrivateKeyFile = "/root/secrets/heinz/ed25519_key.priv"
       PrivateKeyFile        = &quot;/root/secrets/heinz/rsa_key.priv&quot;
       PrivateKeyFile        = "/root/secrets/heinz/rsa_key.priv"
     '';
     '';
     hosts = {
     hosts = {
Line 177: Line 192:
   };
   };
}
}
</pre>
</syntaxHighlight>
=== /etc/nixos/tinc.nix on peter ===
=== /etc/nixos/tinc.nix on peter ===


<pre>{ config, pkgs, ... }:
<syntaxHighlight lang=nix>{ config, pkgs, ... }:


let
let


   myMeshIp  = &quot;10.1.1.21&quot;;
   myMeshIp  = "10.1.1.21";
   myMeshMask = &quot;255.255.255.0&quot;;
   myMeshMask = "255.255.255.0";
   myMeshName = &quot;private&quot;;
   myMeshName = "private";


in {
in {
Line 197: Line 212:
   # simple interface setup
   # simple interface setup
   # ----------------------
   # ----------------------
   networking.interfaces.&quot;tinc.${myMeshName}&quot; = [ { address = myMeshIp; } ];
   networking.interfaces."tinc.${myMeshName}" = [ { address = myMeshIp; } ];




   # configure tinc service
   # configure tinc service
   # ----------------------
   # ----------------------
   services.tinc.networks.&quot;${myMeshName}&quot;= {
   services.tinc.networks."${myMeshName}"= {


     name          = &quot;peter&quot;;      # who are we in this network.
     name          = "peter";      # who are we in this network.


     debugLevel    = 3;            # the debug level for journal -u tinc.private
     debugLevel    = 3;            # the debug level for journal -u tinc.private
     chroot        = false;        # otherwise addresses can't be a DNS
     chroot        = false;        # otherwise addresses can't be a DNS
     interfaceType = &quot;tap&quot;;        # tun might also work.
     interfaceType = "tap";        # tun might also work.


     extraConfig  = ''
     extraConfig  = ''
Line 215: Line 230:
       # 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 = &quot;/root/secrets/peter/ed25519_key.priv&quot;
       Ed25519PrivateKeyFile = "/root/secrets/peter/ed25519_key.priv"
       PrivateKeyFile        = &quot;/root/secrets/peter/rsa_key.priv&quot;
       PrivateKeyFile        = "/root/secrets/peter/rsa_key.priv"
     '';
     '';
     hosts = {
     hosts = {
Line 241: Line 256:
     };
     };
   };
   };
}</pre>
}</syntaxHighlight>