aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2020-02-13 13:05:40 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2020-02-13 13:05:40 +0100
commitea9c6fe8041faab128391a0c03ec3bde25e29fa3 (patch)
tree065d038b07b39c031139830378f3d55224096648
parent8a304ef46e1ad221253f883a8a296a12018e3d30 (diff)
downloadNix-ea9c6fe8041faab128391a0c03ec3bde25e29fa3.tar.gz
Nix-ea9c6fe8041faab128391a0c03ec3bde25e29fa3.tar.zst
Nix-ea9c6fe8041faab128391a0c03ec3bde25e29fa3.zip
Add Tinc VPN
-rw-r--r--modules/private/default.nix2
-rw-r--r--modules/private/environment.nix10
-rw-r--r--modules/private/system/eldiron.nix1
-rw-r--r--modules/private/vpn/default.nix62
-rwxr-xr-xmodules/private/vpn/tinc/host-down7
-rwxr-xr-xmodules/private/vpn/tinc/host-up11
-rwxr-xr-xmodules/private/vpn/tinc/tinc-down12
-rwxr-xr-xmodules/private/vpn/tinc/tinc-up14
-rw-r--r--modules/private/vpn/tinc/tinc.conf11
-rw-r--r--modules/private/websites/tools/tools/default.nix3
-rw-r--r--modules/private/websites/tools/vpn/default.nix15
-rw-r--r--modules/private/websites/tools/vpn/www/index.html91
-rw-r--r--modules/private/websites/tools/vpn/www/style.css61
13 files changed, 300 insertions, 0 deletions
diff --git a/modules/private/default.nix b/modules/private/default.nix
index 945a799..3996eac 100644
--- a/modules/private/default.nix
+++ b/modules/private/default.nix
@@ -46,6 +46,7 @@ set = {
46 46
47 cloudTool = ./websites/tools/cloud; 47 cloudTool = ./websites/tools/cloud;
48 davTool = ./websites/tools/dav; 48 davTool = ./websites/tools/dav;
49 vpnTool = ./websites/tools/vpn;
49 dbTool = ./websites/tools/db; 50 dbTool = ./websites/tools/db;
50 diasporaTool = ./websites/tools/diaspora; 51 diasporaTool = ./websites/tools/diaspora;
51 etherTool = ./websites/tools/ether; 52 etherTool = ./websites/tools/ether;
@@ -72,6 +73,7 @@ set = {
72 ssh = ./ssh; 73 ssh = ./ssh;
73 monitoring = ./monitoring; 74 monitoring = ./monitoring;
74 status = ./monitoring/status.nix; 75 status = ./monitoring/status.nix;
76 vpn = ./vpn;
75 77
76 environment = ./environment.nix; 78 environment = ./environment.nix;
77 system = ./system.nix; 79 system = ./system.nix;
diff --git a/modules/private/environment.nix b/modules/private/environment.nix
index 3b51f37..2cecc6d 100644
--- a/modules/private/environment.nix
+++ b/modules/private/environment.nix
@@ -536,6 +536,16 @@ in
536 }; 536 };
537 }; 537 };
538 }; 538 };
539 vpn = mkOption {
540 description = "VPN configuration";
541 type = attrsOf (submodule {
542 options = {
543 prefix = mkOption { type = str; description = "ipv6 prefix for the vpn subnet"; };
544 privateKey = mkOption { type = str; description = "Private key for the host"; };
545 publicKey = mkOption { type = str; description = "Public key for the host"; };
546 };
547 });
548 };
539 mail = mkOption { 549 mail = mkOption {
540 description = "Mail configuration"; 550 description = "Mail configuration";
541 type = submodule { 551 type = submodule {
diff --git a/modules/private/system/eldiron.nix b/modules/private/system/eldiron.nix
index 0ff9963..5e3d45c 100644
--- a/modules/private/system/eldiron.nix
+++ b/modules/private/system/eldiron.nix
@@ -34,6 +34,7 @@
34 myServices.websites.enable = true; 34 myServices.websites.enable = true;
35 myServices.mail.enable = true; 35 myServices.mail.enable = true;
36 myServices.ejabberd.enable = true; 36 myServices.ejabberd.enable = true;
37 myServices.vpn.enable = true;
37 services.pure-ftpd.enable = true; 38 services.pure-ftpd.enable = true;
38 services.duplyBackup.enable = true; 39 services.duplyBackup.enable = true;
39 services.duplyBackup.profiles.oldies.rootDir = "/var/lib/oldies"; 40 services.duplyBackup.profiles.oldies.rootDir = "/var/lib/oldies";
diff --git a/modules/private/vpn/default.nix b/modules/private/vpn/default.nix
new file mode 100644
index 0000000..fbcba2f
--- /dev/null
+++ b/modules/private/vpn/default.nix
@@ -0,0 +1,62 @@
1{ config, pkgs, lib, ... }:
2let
3 cfg = config.myServices.vpn;
4in
5{
6 options.myServices = {
7 vpn.enable = lib.mkEnableOption "Enable vpn service";
8 };
9
10 config = lib.mkIf cfg.enable {
11 secrets.keys = [
12 {
13 dest = "tinc/key.priv";
14 user = "root";
15 group = "root";
16 permissions = "0400";
17 text = config.myEnv.vpn.eldiron.privateKey;
18 }
19 {
20 dest = "tinc/key.pub";
21 user = "root";
22 group = "root";
23 permissions = "0400";
24 text = config.myEnv.vpn.eldiron.publicKey;
25 }
26 ];
27 networking.firewall.allowedTCPPorts = [ 655 1194 ];
28 system.activationScripts.tinc = let
29 configFiles = pkgs.runCommand "tinc-files" {
30 mainInterface = "eth0";
31 hostName = "ImmaeEu";
32 network = "Immae";
33 keyFile = config.secrets.fullPaths."tinc/key.priv";
34 } ''
35 mkdir -p $out
36 for i in ${./tinc}/*; do
37 substituteAll $i $out/$(basename $i)
38 done
39 '';
40 in ''
41 install -m750 -o root -g root -d /var/lib/tinc/ /var/lib/tinc/Immae
42 install -m700 -o root -g root -t /var/lib/tinc/Immae ${configFiles}/{host-*,tinc-*}
43 install -m400 -o root -g root -t /var/lib/tinc/Immae ${configFiles}/tinc.conf
44 if [ ! -d /var/lib/tinc/Immae/hosts ]; then
45 ${pkgs.git}/bin/git clone -b master https://git.immae.eu/perso/Immae/Config/tinc/hosts /var/lib/tinc/Immae/hosts
46 fi
47 '';
48
49 systemd.services.tinc-Immae = {
50 description = "Tinc Daemon - Immae";
51 wantedBy = [ "multi-user.target" ];
52 after = [ "network.target" ];
53 path = [ pkgs.tinc pkgs.bashInteractive pkgs.iproute pkgs.gnused pkgs.gawk pkgs.git pkgs.glibc ];
54 serviceConfig = {
55 Type = "simple";
56 Restart = "always";
57 RestartSec = "3";
58 ExecStart = "${pkgs.tinc}/bin/tincd -d1 -D -c /var/lib/tinc/Immae --pidfile /run/tinc.Immae.pid";
59 };
60 };
61 };
62}
diff --git a/modules/private/vpn/tinc/host-down b/modules/private/vpn/tinc/host-down
new file mode 100755
index 0000000..1e79bd3
--- /dev/null
+++ b/modules/private/vpn/tinc/host-down
@@ -0,0 +1,7 @@
1#!/usr/bin/env bash
2
3SUBDOMAIN=$(echo "$NODE" | sed -e "s/\([A-Z][a-z0-9]*\)/\L\1 /g;" | awk '{ for (i=NF; i>1; i--) printf("%s.",$i); print $1; }')
4NODEIPS=`getent hosts ${SUBDOMAIN}.immae.eu | cut -d' ' -f1 | tr "\\n" ' '`
5for NODEIP in $NODEIPS; do
6 ip neigh del proxy $NODEIP dev @mainInterface@
7done
diff --git a/modules/private/vpn/tinc/host-up b/modules/private/vpn/tinc/host-up
new file mode 100755
index 0000000..2f7cee2
--- /dev/null
+++ b/modules/private/vpn/tinc/host-up
@@ -0,0 +1,11 @@
1#!/usr/bin/env bash
2
3SUBDOMAIN=$(echo "$NODE" | sed -e "s/\([A-Z][a-z0-9]*\)/\L\1 /g;" | awk '{ for (i=NF; i>1; i--) printf("%s.",$i); print $1; }')
4while [ -z "$NODEIPS" ]; do
5 NODEIPS=`getent hosts ${SUBDOMAIN}.immae.eu | cut -d' ' -f1 | tr "\\n" ' '`
6 sleep 5
7done
8for NODEIP in $NODEIPS; do
9 ip neigh add proxy $NODEIP dev @mainInterface@
10done
11(cd /var/lib/tinc/@network@/hosts && git pull -q origin master) || true
diff --git a/modules/private/vpn/tinc/tinc-down b/modules/private/vpn/tinc/tinc-down
new file mode 100755
index 0000000..1cc45c0
--- /dev/null
+++ b/modules/private/vpn/tinc/tinc-down
@@ -0,0 +1,12 @@
1#!/bin/sh
2# This file closes down the tap device.
3
4echo 0 > /proc/sys/net/ipv6/conf/@mainInterface@/proxy_ndp
5echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
6
7GWIP=`getent hosts gw.vpn.immae.eu | head -n1 | cut -d' ' -f1`
8
9ip neigh del proxy $GWIP dev eth0
10
11ip -6 addr del $GWIP/96 dev $INTERFACE
12ip -6 link set $INTERFACE down
diff --git a/modules/private/vpn/tinc/tinc-up b/modules/private/vpn/tinc/tinc-up
new file mode 100755
index 0000000..26c1ec3
--- /dev/null
+++ b/modules/private/vpn/tinc/tinc-up
@@ -0,0 +1,14 @@
1#!/usr/bin/env bash
2
3echo 1 > /proc/sys/net/ipv6/conf/@mainInterface@/proxy_ndp
4echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
5
6SUBNET=`getent hosts sn.vpn.immae.eu | head -n1 | cut -d' ' -f1`
7GWIP=`getent hosts gw.vpn.immae.eu | head -n1 | cut -d' ' -f1`
8
9ip -6 link set $INTERFACE up mtu 1280 txqueuelen 1000
10
11ip -6 addr add $GWIP/96 dev $INTERFACE
12ip -6 route add $SUBNET/80 dev $INTERFACE
13
14ip neigh add proxy $GWIP dev @mainInterface@
diff --git a/modules/private/vpn/tinc/tinc.conf b/modules/private/vpn/tinc/tinc.conf
new file mode 100644
index 0000000..7a4f103
--- /dev/null
+++ b/modules/private/vpn/tinc/tinc.conf
@@ -0,0 +1,11 @@
1BindToAddress = * 655
2BindToAddress = * 1194
3
4Name = @hostName@
5Interface = vpn6
6
7Mode = switch
8
9Device = /dev/net/tun
10GraphDumpFile = /var/lib/tinc/@network@/tinc_graph
11PrivateKeyFile = @keyFile@
diff --git a/modules/private/websites/tools/tools/default.nix b/modules/private/websites/tools/tools/default.nix
index f88cf06..9fb2d03 100644
--- a/modules/private/websites/tools/tools/default.nix
+++ b/modules/private/websites/tools/tools/default.nix
@@ -102,6 +102,7 @@ in {
102 root = "/var/lib/ftp/tools.immae.eu"; 102 root = "/var/lib/ftp/tools.immae.eu";
103 extraConfig = [ 103 extraConfig = [
104 '' 104 ''
105 RedirectMatch 301 ^/vpn(.*)$ https://vpn.immae.eu$1
105 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1 106 RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
106 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse 107 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
107 108
@@ -152,6 +153,8 @@ in {
152 153
153 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse 154 RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
154 155
156 RedirectMatch 301 ^/vpn(.*)$ https://vpn.immae.eu$1
157
155 RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1 158 RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1
156 '' 159 ''
157 ]; 160 ];
diff --git a/modules/private/websites/tools/vpn/default.nix b/modules/private/websites/tools/vpn/default.nix
new file mode 100644
index 0000000..cfe010c
--- /dev/null
+++ b/modules/private/websites/tools/vpn/default.nix
@@ -0,0 +1,15 @@
1{ lib, pkgs, config, ... }:
2let
3 cfg = config.myServices.vpn;
4in {
5 config = lib.mkIf cfg.enable {
6 services.websites.env.tools.vhostConfs.vpn = {
7 certName = "eldiron";
8 addToCerts = true;
9 hosts = [ "vpn.immae.eu" ];
10 root = "/run/current-system/webapps/_vpn";
11 };
12
13 myServices.websites.webappDirs._vpn = ./www;
14 };
15}
diff --git a/modules/private/websites/tools/vpn/www/index.html b/modules/private/websites/tools/vpn/www/index.html
new file mode 100644
index 0000000..08199fb
--- /dev/null
+++ b/modules/private/websites/tools/vpn/www/index.html
@@ -0,0 +1,91 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3<html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <title>VPN configuration</title>
6 <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'>
7 <link rel="stylesheet" href="style.css" type="text/css" />
8 <meta name="viewport" content="width=device-width, initial-scale=1" />
9 </head>
10 <body>
11 <div class="instructions">
12 <h2>Installation</h2>
13 <ul>
14 <li>Installer tinc</li>
15 <li>Créer un fichier /etc/tinc/Immae/tinc.conf sur ce modèle, en remplaçant la ligne <code>A choisir</code> par un nom de la forme DomaineMachine. La machine sera accessible par <code>machine.domaine.immae.eu</code> par la suite
16 <pre>
17Name = A choisir
18Mode = switch
19Interface = vpn6
20ConnectTo = ImmaeEu
21
22# The tap device tinc will use.
23# Default is /dev/tap0 for ethertap or FreeBSD,
24# /dev/tun0 for Solaris and OpenBSD,
25# and /dev/net/tun for Linux tun/tap device.
26Device = /dev/net/tun
27LocalDiscovery = yes
28 </pre>
29 </li>
30 <li>Vérifier l'existence du device indiqué à la ligne "<code>Device</code>" dans le système.
31 <pre>ls /dev/net/tun</pre>
32 </li>
33 <li><em class="important">Si tinc tourne déjà, l'arrêter !!</em></li>
34 <li>Générer les clés&nbsp;:
35 <pre>tincd -K -n Immae</pre>
36 Stocker la clé privée dans <code>/etc/tinc/Immae/rsa_key.priv</code> et la clé publique dans un autre dossier<br />
37 (<em>pas <code>/etc/tinc/Immae/hosts/</code> comme proposé par défaut</em>).<br />
38 L'endroit importe peu, elle ne sera pas conservée.</li>
39 <li>M'envoyer le nom choisi dans <code>tinc.conf</code>, et la clé publique</li>
40 <li>Cloner le dépôt des hôtes du réseau
41 <pre>
42cd /etc/tinc/Immae
43git clone https://git.immae.eu/perso/Immae/Config/tinc/hosts
44 </pre>
45 </li>
46 <li>Une fois que j'ai confirmé avoir reçu la clé&nbsp;:
47 <pre>
48cd /etc/tinc/Immae/hosts
49git pull origin master
50 </pre>
51 </li>
52 <li>Uniquement pour Debian/Ubuntu: Ajouter <code>Immae</code> dans <code>/etc/tinc/nets.boot</code> (créer le fichier si nécessaire).</li>
53 <li>Selon le système, démarrer tinc&nbsp;:
54 <pre>
55/etc/init.d/tinc start
56 </pre>
57 ou
58 <pre>
59systemctl enable tincd@Immae.service
60systemctl start tincd@Immae.service
61 </pre>
62 </li>
63 </ul>
64
65 <h2>Choix d'ip</h2>
66 <ul>
67 <li>Choisir une ip : <code>2001:aaaa:b:cccc:d::xxxx:yyyy/96</code> (le préfixe <code>2001:aaaa:b:cccc:d</code> est imposé). Choix uniquement sur le <code>yyyy</code> (n'importe quel nombre entre <code>1</code> et <code>ffff</code>), le <code>xxxx</code> est dépendant du domaine</li>
68 <li>M'envoyer le choix de l'ip</li>
69
70 <li>Si on veut éviter de passer systématiquement par le serveur immae.eu (Par
71 défaut linux préfère l'ipv6 dès qu'il en a possibilité), modifier le fichier
72 <code>/etc/gai.conf</code>. Quelques lignes à décommenter, tout est déjà dans le fichier :
73 <pre>
74(...)
75#
76precedence ::1/128 50
77precedence ::/0 40
78precedence 2002::/16 30
79precedence ::/96 20
80#precedence ::ffff:0:0/96 10
81#
82# For sites which prefer IPv4 connections change the last line to
83#
84precedence ::ffff:0:0/96 100
85(...)
86 </pre>
87 </li>
88 </ul>
89 </div>
90 </body>
91</html>
diff --git a/modules/private/websites/tools/vpn/www/style.css b/modules/private/websites/tools/vpn/www/style.css
new file mode 100644
index 0000000..b177fec
--- /dev/null
+++ b/modules/private/websites/tools/vpn/www/style.css
@@ -0,0 +1,61 @@
1* {
2 margin:0;
3 padding:0;
4 -webkit-box-sizing:border-box;
5 -moz-box-sizing:border-box;
6 box-sizing: border-box;
7}
8
9html {
10 min-height:100%;
11 border-top:10px solid #ECEEF1;
12 border-bottom:10px solid #ECEEF1;
13 color:#61666c;
14 font-weight:400;
15 font-size:1em;
16 font-family:'Open Sans', sans-serif;
17 line-height:2em;
18}
19body {
20 padding:20px;
21 -webkit-backface-visibility:hidden;
22}
23code {
24 font-family:consolas,monospace;
25}
26a {
27 color:#61666c;
28 text-decoration:none;
29}
30a, img {
31 border:none;
32 outline:none
33}
34a:hover {
35 color:#2a2a2a;
36}
37
38.instructions {
39 margin:0 auto;
40 padding-top:20px;
41 max-width:80%;
42}
43
44.instructions a {
45 text-decoration: underline;
46}
47
48.instructions h2 {
49 margin-top: 10px;
50}
51.instructions em.important:before {
52 content: "⚠ Important ⚠ ";
53 color: red;
54}
55.instructions pre {
56 width: 50em;
57 padding: 10px 15px;
58 display: table;
59 border: 1px inset black;
60 line-height: 1em;
61}