wchisp: remove overuse of with lib (#357239)
[NixPkgs.git] / nixos / tests / tayga.nix
blobe3c57b7d58feb5923e418dfb690dc9edec7b167e
1 # This test verifies that we can ping an IPv4-only server from an IPv6-only
2 # client via a NAT64 router. The hosts and networks are configured as follows:
4 #        +------
5 # Client | eth1    Address: 2001:db8::2/64
6 #        |  |      Route:   64:ff9b::/96 via 2001:db8::1
7 #        +--|---
8 #           | VLAN 3
9 #        +--|---
10 #        | eth2    Address: 2001:db8::1/64
11 # Router |
12 #        | nat64   Address: 64:ff9b::1/128
13 #        |         Route:   64:ff9b::/96
14 #        |         Address: 192.0.2.0/32
15 #        |         Route:   192.0.2.0/24
16 #        |
17 #        | eth1    Address: 100.64.0.1/24
18 #        +--|---
19 #           | VLAN 2
20 #        +--|---
21 # Server | eth1    Address: 100.64.0.2/24
22 #        |         Route:   192.0.2.0/24 via 100.64.0.1
23 #        +------
25 import ./make-test-python.nix ({ pkgs, lib, ... }:
28   name = "tayga";
29   meta = with pkgs.lib.maintainers; {
30     maintainers = [ hax404 ];
31   };
33   nodes = {
34     # The server is configured with static IPv4 addresses. RFC 6052 Section 3.1
35     # disallows the mapping of non-global IPv4 addresses like RFC 1918 into the
36     # Well-Known Prefix 64:ff9b::/96. TAYGA also does not allow the mapping of
37     # documentation space (RFC 5737). To circumvent this, 100.64.0.2/24 from
38     # RFC 6589 (Carrier Grade NAT) is used here.
39     # To reach the IPv4 address pool of the NAT64 gateway, there is a static
40     # route configured. In normal cases, where the router would also source NAT
41     # the pool addresses to one IPv4 addresses, this would not be needed.
42     server = {
43       virtualisation.vlans = [
44         2 # towards router
45       ];
46       networking = {
47         useDHCP = false;
48         interfaces.eth1 = lib.mkForce {};
49       };
50       systemd.network = {
51         enable = true;
52         networks."vlan1" = {
53           matchConfig.Name = "eth1";
54           address = [
55             "100.64.0.2/24"
56           ];
57           routes = [
58             { Destination = "192.0.2.0/24"; Gateway = "100.64.0.1"; }
59           ];
60         };
61       };
62       programs.mtr.enable = true;
63     };
65     # The router is configured with static IPv4 addresses towards the server
66     # and IPv6 addresses towards the client. For NAT64, the Well-Known prefix
67     # 64:ff9b::/96 is used. NAT64 is done with TAYGA which provides the
68     # tun-interface nat64 and does the translation over it. The IPv6 packets
69     # are sent to this interfaces and received as IPv4 packets and vice versa.
70     # As TAYGA only translates IPv6 addresses to dedicated IPv4 addresses, it
71     # needs a pool of IPv4 addresses which must be at least as big as the
72     # expected amount of clients. In this test, the packets from the pool are
73     # directly routed towards the client. In normal cases, there would be a
74     # second source NAT44 to map all clients behind one IPv4 address.
75     router_systemd = {
76       boot.kernel.sysctl = {
77         "net.ipv4.ip_forward" = 1;
78         "net.ipv6.conf.all.forwarding" = 1;
79       };
81       virtualisation.vlans = [
82         2 # towards server
83         3 # towards client
84       ];
86       networking = {
87         useDHCP = false;
88         useNetworkd = true;
89         firewall.enable = false;
90         interfaces.eth1 = lib.mkForce {
91           ipv4 = {
92             addresses = [ { address = "100.64.0.1"; prefixLength = 24; } ];
93           };
94         };
95         interfaces.eth2 = lib.mkForce {
96           ipv6 = {
97             addresses = [ { address = "2001:db8::1"; prefixLength = 64; } ];
98           };
99         };
100       };
102       services.tayga = {
103         enable = true;
104         ipv4 = {
105           address = "192.0.2.0";
106           router = {
107             address = "192.0.2.1";
108           };
109           pool = {
110             address = "192.0.2.0";
111             prefixLength = 24;
112           };
113         };
114         ipv6 = {
115           address = "2001:db8::1";
116           router = {
117             address = "64:ff9b::1";
118           };
119           pool = {
120             address = "64:ff9b::";
121             prefixLength = 96;
122           };
123         };
124         mappings = {
125           "192.0.2.42" = "2001:db8::2";
126         };
127       };
128     };
130     router_nixos = {
131       boot.kernel.sysctl = {
132         "net.ipv4.ip_forward" = 1;
133         "net.ipv6.conf.all.forwarding" = 1;
134       };
136       virtualisation.vlans = [
137         2 # towards server
138         3 # towards client
139       ];
141       networking = {
142         useDHCP = false;
143         firewall.enable = false;
144         interfaces.eth1 = lib.mkForce {
145           ipv4 = {
146             addresses = [ { address = "100.64.0.1"; prefixLength = 24; } ];
147           };
148         };
149         interfaces.eth2 = lib.mkForce {
150           ipv6 = {
151             addresses = [ { address = "2001:db8::1"; prefixLength = 64; } ];
152           };
153         };
154       };
156       services.tayga = {
157         enable = true;
158         ipv4 = {
159           address = "192.0.2.0";
160           router = {
161             address = "192.0.2.1";
162           };
163           pool = {
164             address = "192.0.2.0";
165             prefixLength = 24;
166           };
167         };
168         ipv6 = {
169           address = "2001:db8::1";
170           router = {
171             address = "64:ff9b::1";
172           };
173           pool = {
174             address = "64:ff9b::";
175             prefixLength = 96;
176           };
177         };
178         mappings = {
179           "192.0.2.42" = "2001:db8::2";
180         };
181       };
182     };
184     # The client is configured with static IPv6 addresses. It has also a static
185     # route for the NAT64 IP space where the IPv4 addresses are mapped in. In
186     # normal cases, there would be only a default route.
187     client = {
188       virtualisation.vlans = [
189         3 # towards router
190       ];
192       networking = {
193         useDHCP = false;
194         interfaces.eth1 = lib.mkForce {};
195       };
197       systemd.network = {
198         enable = true;
199         networks."vlan1" = {
200           matchConfig.Name = "eth1";
201           address = [
202             "2001:db8::2/64"
203           ];
204           routes = [
205             { Destination = "64:ff9b::/96"; Gateway = "2001:db8::1"; }
206           ];
207         };
208       };
209       programs.mtr.enable = true;
210     };
211   };
213   testScript = ''
214     # start client and server
215     for machine in client, server:
216       machine.systemctl("start network-online.target")
217       machine.wait_for_unit("network-online.target")
218       machine.log(machine.execute("ip addr")[1])
219       machine.log(machine.execute("ip route")[1])
220       machine.log(machine.execute("ip -6 route")[1])
222     # test systemd-networkd and nixos-scripts based router
223     for router in router_systemd, router_nixos:
224       router.start()
225       router.systemctl("start network-online.target")
226       router.wait_for_unit("network-online.target")
227       router.wait_for_unit("tayga.service")
228       router.log(machine.execute("ip addr")[1])
229       router.log(machine.execute("ip route")[1])
230       router.log(machine.execute("ip -6 route")[1])
232       with subtest("Wait for tayga"):
233         router.wait_for_unit("tayga.service")
235       with subtest("Test ICMP server -> client"):
236         server.wait_until_succeeds("ping -c 3 192.0.2.42 >&2")
238       with subtest("Test ICMP and show a traceroute server -> client"):
239         server.wait_until_succeeds("mtr --show-ips --report-wide 192.0.2.42 >&2")
241       with subtest("Test ICMP client -> server"):
242         client.wait_until_succeeds("ping -c 3 64:ff9b::100.64.0.2 >&2")
244       with subtest("Test ICMP and show a traceroute client -> server"):
245         client.wait_until_succeeds("mtr --show-ips --report-wide 64:ff9b::100.64.0.2 >&2")
247       router.log(router.execute("systemd-analyze security tayga.service")[1])
248       router.shutdown()
249   '';