blob: 31b675ad35c067c96f26d7da2fe49f49c78ee158 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
import ../make-test-python.nix ({ lib, ... }:
let
snakeoil-keys = import ./snakeoil-keys.nix;
hosts = lib.attrNames snakeoil-keys;
subnetOf = name: config:
let
subnets = config.services.tinc.networks.myNetwork.hostSettings.${name}.subnets;
in
(builtins.head subnets).address;
makeTincHost = name: { subnet, extraConfig ? { } }: lib.mkMerge [
{
subnets = [{ address = subnet; }];
settings = {
Ed25519PublicKey = snakeoil-keys.${name}.ed25519Public;
};
rsaPublicKey = snakeoil-keys.${name}.rsaPublic;
}
extraConfig
];
makeTincNode = { config, ... }: name: extraConfig: lib.mkMerge [
{
services.tinc.networks.myNetwork = {
inherit name;
rsaPrivateKeyFile =
builtins.toFile "rsa.priv" snakeoil-keys.${name}.rsaPrivate;
ed25519PrivateKeyFile =
builtins.toFile "ed25519.priv" snakeoil-keys.${name}.ed25519Private;
hostSettings = lib.mapAttrs makeTincHost {
static = {
subnet = "10.0.0.11";
# Only specify the addresses in the node's vlans, Tinc does not
# seem to try each one, unlike the documentation suggests...
extraConfig.addresses = map
(vlan: { address = "192.168.${toString vlan}.11"; port = 655; })
config.virtualisation.vlans;
};
dynamic1 = { subnet = "10.0.0.21"; };
dynamic2 = { subnet = "10.0.0.22"; };
};
};
networking.useDHCP = false;
networking.interfaces."tinc.myNetwork" = {
virtual = true;
virtualType = "tun";
ipv4.addresses = [{
address = subnetOf name config;
prefixLength = 24;
}];
};
# Prevents race condition between NixOS service and tinc creating the
# interface.
# See: https://github.com/NixOS/nixpkgs/issues/27070
systemd.services."tinc.myNetwork" = {
after = [ "network-addresses-tinc.myNetwork.service" ];
requires = [ "network-addresses-tinc.myNetwork.service" ];
};
networking.firewall.allowedTCPPorts = [ 655 ];
networking.firewall.allowedUDPPorts = [ 655 ];
}
extraConfig
];
in
{
name = "tinc";
meta.maintainers = with lib.maintainers; [ minijackson ];
nodes = {
static = { ... } @ args:
makeTincNode args "static" {
virtualisation.vlans = [ 1 2 ];
networking.interfaces.eth1.ipv4.addresses = [{
address = "192.168.1.11";
prefixLength = 24;
}];
networking.interfaces.eth2.ipv4.addresses = [{
address = "192.168.2.11";
prefixLength = 24;
}];
};
dynamic1 = { ... } @ args:
makeTincNode args "dynamic1" {
virtualisation.vlans = [ 1 ];
};
dynamic2 = { ... } @ args:
makeTincNode args "dynamic2" {
virtualisation.vlans = [ 2 ];
};
};
testScript = ''
start_all()
static.wait_for_unit("tinc.myNetwork.service")
dynamic1.wait_for_unit("tinc.myNetwork.service")
dynamic2.wait_for_unit("tinc.myNetwork.service")
# Static is accessible by the other hosts
dynamic1.succeed("ping -c5 192.168.1.11")
dynamic2.succeed("ping -c5 192.168.2.11")
# The other hosts are in separate vlans
dynamic1.fail("ping -c5 192.168.2.11")
dynamic2.fail("ping -c5 192.168.1.11")
# Each host can ping themselves through Tinc
static.succeed("ping -c5 10.0.0.11")
dynamic1.succeed("ping -c5 10.0.0.21")
dynamic2.succeed("ping -c5 10.0.0.22")
# Static is accessible by the other hosts through Tinc
dynamic1.succeed("ping -c5 10.0.0.11")
dynamic2.succeed("ping -c5 10.0.0.11")
# Static can access the other hosts through Tinc
static.succeed("ping -c5 10.0.0.21")
static.succeed("ping -c5 10.0.0.22")
# The other hosts in separate vlans can access each other through Tinc
dynamic1.succeed("ping -c5 10.0.0.22")
dynamic2.succeed("ping -c5 10.0.0.21")
'';
})
|