fork
Configure Feed
Select the types of activity you want to include in your feed.
lol
fork
Configure Feed
Select the types of activity you want to include in your feed.
1{ pkgs, runTest }:
2
3let
4 inherit (pkgs) lib;
5
6 ipv6Only = {
7 networking.useDHCP = false;
8 networking.interfaces.eth1.ipv4.addresses = lib.mkVMOverride [ ];
9 };
10
11 ipv4Only = {
12 networking.useDHCP = false;
13 networking.interfaces.eth1.ipv6.addresses = lib.mkVMOverride [ ];
14 };
15
16 webserver = ip: msg: {
17 systemd.services.webserver = {
18 description = "Mock webserver";
19 wants = [ "network-online.target" ];
20 wantedBy = [ "multi-user.target" ];
21 script = ''
22 while true; do
23 {
24 printf 'HTTP/1.0 200 OK\n'
25 printf 'Content-Length: ${toString (1 + builtins.stringLength msg)}\n'
26 printf '\n${msg}\n\n'
27 } | ${pkgs.libressl.nc}/bin/nc -${toString ip}nvl 80
28 done
29 '';
30 };
31 networking.firewall.allowedTCPPorts = [ 80 ];
32 };
33
34in
35
36{
37 siit = runTest {
38 # This test simulates the setup described in [1] with two IPv6 and
39 # IPv4-only devices on different subnets communicating through a border
40 # relay running Jool in SIIT mode.
41 # [1]: https://nicmx.github.io/Jool/en/run-vanilla.html
42 name = "jool-siit";
43 meta.maintainers = with lib.maintainers; [ rnhmjoj ];
44
45 # Border relay
46 nodes.relay = {
47 virtualisation.vlans = [
48 1
49 2
50 ];
51
52 # Enable packet routing
53 boot.kernel.sysctl = {
54 "net.ipv6.conf.all.forwarding" = 1;
55 "net.ipv4.conf.all.forwarding" = 1;
56 };
57
58 networking.useDHCP = false;
59 networking.interfaces = lib.mkVMOverride {
60 eth1.ipv6.addresses = [
61 {
62 address = "fd::198.51.100.1";
63 prefixLength = 120;
64 }
65 ];
66 eth2.ipv4.addresses = [
67 {
68 address = "192.0.2.1";
69 prefixLength = 24;
70 }
71 ];
72 };
73
74 networking.jool.enable = true;
75 networking.jool.siit.default.global.pool6 = "fd::/96";
76 };
77
78 # IPv6 only node
79 nodes.alice = {
80 imports = [
81 ipv6Only
82 (webserver 6 "Hello, Bob!")
83 ];
84
85 virtualisation.vlans = [ 1 ];
86 networking.interfaces.eth1.ipv6 = {
87 addresses = [
88 {
89 address = "fd::198.51.100.8";
90 prefixLength = 120;
91 }
92 ];
93 routes = [
94 {
95 address = "fd::192.0.2.0";
96 prefixLength = 120;
97 via = "fd::198.51.100.1";
98 }
99 ];
100 };
101 };
102
103 # IPv4 only node
104 nodes.bob = {
105 imports = [
106 ipv4Only
107 (webserver 4 "Hello, Alice!")
108 ];
109
110 virtualisation.vlans = [ 2 ];
111 networking.interfaces.eth1.ipv4 = {
112 addresses = [
113 {
114 address = "192.0.2.16";
115 prefixLength = 24;
116 }
117 ];
118 routes = [
119 {
120 address = "198.51.100.0";
121 prefixLength = 24;
122 via = "192.0.2.1";
123 }
124 ];
125 };
126 };
127
128 testScript = ''
129 start_all()
130
131 relay.wait_for_unit("jool-siit-default.service")
132 alice.wait_for_unit("network-addresses-eth1.service")
133 bob.wait_for_unit("network-addresses-eth1.service")
134
135 with subtest("Alice and Bob can't ping each other"):
136 relay.systemctl("stop jool-siit-default.service")
137 alice.fail("ping -c1 fd::192.0.2.16")
138 bob.fail("ping -c1 198.51.100.8")
139
140 with subtest("Alice and Bob can ping using the relay"):
141 relay.systemctl("start jool-siit-default.service")
142 alice.wait_until_succeeds("ping -c1 fd::192.0.2.16")
143 bob.wait_until_succeeds("ping -c1 198.51.100.8")
144
145 with subtest("Alice can connect to Bob's webserver"):
146 bob.wait_for_open_port(80)
147 alice.succeed("curl -vvv http://[fd::192.0.2.16] >&2")
148 alice.succeed("curl --fail -s http://[fd::192.0.2.16] | grep -q Alice")
149
150 with subtest("Bob can connect to Alices's webserver"):
151 alice.wait_for_open_port(80)
152 bob.succeed("curl --fail -s http://198.51.100.8 | grep -q Bob")
153 '';
154 };
155
156 nat64 = runTest {
157 # This test simulates the setup described in [1] with two IPv6-only nodes
158 # (a client and a homeserver) on the LAN subnet and an IPv4 node on the WAN.
159 # The router runs Jool in stateful NAT64 mode, masquarading the LAN and
160 # forwarding ports using static BIB entries.
161 # [1]: https://nicmx.github.io/Jool/en/run-nat64.html
162 name = "jool-nat64";
163 meta.maintainers = with lib.maintainers; [ rnhmjoj ];
164
165 # Router
166 nodes.router = {
167 virtualisation.vlans = [
168 1
169 2
170 ];
171
172 # Enable packet routing
173 boot.kernel.sysctl = {
174 "net.ipv6.conf.all.forwarding" = 1;
175 "net.ipv4.conf.all.forwarding" = 1;
176 };
177
178 networking.useDHCP = false;
179 networking.interfaces = lib.mkVMOverride {
180 eth1.ipv6.addresses = [
181 {
182 address = "2001:db8::1";
183 prefixLength = 96;
184 }
185 ];
186 eth2.ipv4.addresses = [
187 {
188 address = "203.0.113.1";
189 prefixLength = 24;
190 }
191 ];
192 };
193
194 networking.jool.enable = true;
195 networking.jool.nat64.default = {
196 bib = [
197 {
198 # forward HTTP 203.0.113.1 (router) → 2001:db8::9 (homeserver)
199 "protocol" = "TCP";
200 "ipv4 address" = "203.0.113.1#80";
201 "ipv6 address" = "2001:db8::9#80";
202 }
203 ];
204 pool4 = [
205 # Ports for dynamic translation
206 {
207 protocol = "TCP";
208 prefix = "203.0.113.1/32";
209 "port range" = "40001-65535";
210 }
211 {
212 protocol = "UDP";
213 prefix = "203.0.113.1/32";
214 "port range" = "40001-65535";
215 }
216 {
217 protocol = "ICMP";
218 prefix = "203.0.113.1/32";
219 "port range" = "40001-65535";
220 }
221 # Ports for static BIB entries
222 {
223 protocol = "TCP";
224 prefix = "203.0.113.1/32";
225 "port range" = "80";
226 }
227 ];
228 };
229 };
230
231 # LAN client (IPv6 only)
232 nodes.client = {
233 imports = [ ipv6Only ];
234 virtualisation.vlans = [ 1 ];
235
236 networking.interfaces.eth1.ipv6 = {
237 addresses = lib.mkForce [
238 {
239 address = "2001:db8::8";
240 prefixLength = 96;
241 }
242 ];
243 routes = lib.mkForce [
244 {
245 address = "64:ff9b::";
246 prefixLength = 96;
247 via = "2001:db8::1";
248 }
249 ];
250 };
251 };
252
253 # LAN server (IPv6 only)
254 nodes.homeserver = {
255 imports = [
256 ipv6Only
257 (webserver 6 "Hello from IPv6!")
258 ];
259
260 virtualisation.vlans = [ 1 ];
261 networking.interfaces.eth1.ipv6 = {
262 addresses = lib.mkForce [
263 {
264 address = "2001:db8::9";
265 prefixLength = 96;
266 }
267 ];
268 routes = lib.mkForce [
269 {
270 address = "64:ff9b::";
271 prefixLength = 96;
272 via = "2001:db8::1";
273 }
274 ];
275 };
276 };
277
278 # WAN server (IPv4 only)
279 nodes.server = {
280 imports = [
281 ipv4Only
282 (webserver 4 "Hello from IPv4!")
283 ];
284
285 virtualisation.vlans = [ 2 ];
286 networking.interfaces.eth1.ipv4.addresses = [
287 {
288 address = "203.0.113.16";
289 prefixLength = 24;
290 }
291 ];
292 };
293
294 testScript = ''
295 start_all()
296
297 for node in [client, homeserver, server]:
298 node.wait_for_unit("network-addresses-eth1.service")
299
300 with subtest("Client can ping the WAN server"):
301 router.wait_for_unit("jool-nat64-default.service")
302 client.succeed("ping -c1 64:ff9b::203.0.113.16")
303
304 with subtest("Client can connect to the WAN webserver"):
305 server.wait_for_open_port(80)
306 client.succeed("curl --fail -s http://[64:ff9b::203.0.113.16] | grep -q IPv4!")
307
308 with subtest("Router BIB entries are correctly populated"):
309 router.succeed("jool bib display | grep -q 'Dynamic TCP.*2001:db8::8'")
310 router.succeed("jool bib display | grep -q 'Static TCP.*2001:db8::9'")
311
312 with subtest("WAN server can reach the LAN server"):
313 homeserver.wait_for_open_port(80)
314 server.succeed("curl --fail -s http://203.0.113.1 | grep -q IPv6!")
315 '';
316
317 };
318
319}