at 23.11-beta 7.4 kB view raw
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 = [ 1 2 ]; 48 49 # Enable packet routing 50 boot.kernel.sysctl = { 51 "net.ipv6.conf.all.forwarding" = 1; 52 "net.ipv4.conf.all.forwarding" = 1; 53 }; 54 55 networking.useDHCP = false; 56 networking.interfaces = lib.mkVMOverride { 57 eth1.ipv6.addresses = [ { address = "fd::198.51.100.1"; prefixLength = 120; } ]; 58 eth2.ipv4.addresses = [ { address = "192.0.2.1"; prefixLength = 24; } ]; 59 }; 60 61 networking.jool.enable = true; 62 networking.jool.siit.default.global.pool6 = "fd::/96"; 63 }; 64 65 # IPv6 only node 66 nodes.alice = { 67 imports = [ ipv6Only (webserver 6 "Hello, Bob!") ]; 68 69 virtualisation.vlans = [ 1 ]; 70 networking.interfaces.eth1.ipv6 = { 71 addresses = [ { address = "fd::198.51.100.8"; prefixLength = 120; } ]; 72 routes = [ { address = "fd::192.0.2.0"; prefixLength = 120; 73 via = "fd::198.51.100.1"; } ]; 74 }; 75 }; 76 77 # IPv4 only node 78 nodes.bob = { 79 imports = [ ipv4Only (webserver 4 "Hello, Alice!") ]; 80 81 virtualisation.vlans = [ 2 ]; 82 networking.interfaces.eth1.ipv4 = { 83 addresses = [ { address = "192.0.2.16"; prefixLength = 24; } ]; 84 routes = [ { address = "198.51.100.0"; prefixLength = 24; 85 via = "192.0.2.1"; } ]; 86 }; 87 }; 88 89 testScript = '' 90 start_all() 91 92 relay.wait_for_unit("jool-siit-default.service") 93 alice.wait_for_unit("network-addresses-eth1.service") 94 bob.wait_for_unit("network-addresses-eth1.service") 95 96 with subtest("Alice and Bob can't ping each other"): 97 relay.systemctl("stop jool-siit-default.service") 98 alice.fail("ping -c1 fd::192.0.2.16") 99 bob.fail("ping -c1 198.51.100.8") 100 101 with subtest("Alice and Bob can ping using the relay"): 102 relay.systemctl("start jool-siit-default.service") 103 alice.wait_until_succeeds("ping -c1 fd::192.0.2.16") 104 bob.wait_until_succeeds("ping -c1 198.51.100.8") 105 106 with subtest("Alice can connect to Bob's webserver"): 107 bob.wait_for_open_port(80) 108 alice.succeed("curl -vvv http://[fd::192.0.2.16] >&2") 109 alice.succeed("curl --fail -s http://[fd::192.0.2.16] | grep -q Alice") 110 111 with subtest("Bob can connect to Alices's webserver"): 112 alice.wait_for_open_port(80) 113 bob.succeed("curl --fail -s http://198.51.100.8 | grep -q Bob") 114 ''; 115 }; 116 117 nat64 = runTest { 118 # This test simulates the setup described in [1] with two IPv6-only nodes 119 # (a client and a homeserver) on the LAN subnet and an IPv4 node on the WAN. 120 # The router runs Jool in stateful NAT64 mode, masquarading the LAN and 121 # forwarding ports using static BIB entries. 122 # [1]: https://nicmx.github.io/Jool/en/run-nat64.html 123 name = "jool-nat64"; 124 meta.maintainers = with lib.maintainers; [ rnhmjoj ]; 125 126 # Router 127 nodes.router = { 128 virtualisation.vlans = [ 1 2 ]; 129 130 # Enable packet routing 131 boot.kernel.sysctl = { 132 "net.ipv6.conf.all.forwarding" = 1; 133 "net.ipv4.conf.all.forwarding" = 1; 134 }; 135 136 networking.useDHCP = false; 137 networking.interfaces = lib.mkVMOverride { 138 eth1.ipv6.addresses = [ { address = "2001:db8::1"; prefixLength = 96; } ]; 139 eth2.ipv4.addresses = [ { address = "203.0.113.1"; prefixLength = 24; } ]; 140 }; 141 142 networking.jool.enable = true; 143 networking.jool.nat64.default = { 144 bib = [ 145 { # forward HTTP 203.0.113.1 (router) → 2001:db8::9 (homeserver) 146 "protocol" = "TCP"; 147 "ipv4 address" = "203.0.113.1#80"; 148 "ipv6 address" = "2001:db8::9#80"; 149 } 150 ]; 151 pool4 = [ 152 # Ports for dynamic translation 153 { protocol = "TCP"; prefix = "203.0.113.1/32"; "port range" = "40001-65535"; } 154 { protocol = "UDP"; prefix = "203.0.113.1/32"; "port range" = "40001-65535"; } 155 { protocol = "ICMP"; prefix = "203.0.113.1/32"; "port range" = "40001-65535"; } 156 # Ports for static BIB entries 157 { protocol = "TCP"; prefix = "203.0.113.1/32"; "port range" = "80"; } 158 ]; 159 }; 160 }; 161 162 # LAN client (IPv6 only) 163 nodes.client = { 164 imports = [ ipv6Only ]; 165 virtualisation.vlans = [ 1 ]; 166 167 networking.interfaces.eth1.ipv6 = { 168 addresses = [ { address = "2001:db8::8"; prefixLength = 96; } ]; 169 routes = [ { address = "64:ff9b::"; prefixLength = 96; 170 via = "2001:db8::1"; } ]; 171 }; 172 }; 173 174 # LAN server (IPv6 only) 175 nodes.homeserver = { 176 imports = [ ipv6Only (webserver 6 "Hello from IPv6!") ]; 177 178 virtualisation.vlans = [ 1 ]; 179 networking.interfaces.eth1.ipv6 = { 180 addresses = [ { address = "2001:db8::9"; prefixLength = 96; } ]; 181 routes = [ { address = "64:ff9b::"; prefixLength = 96; 182 via = "2001:db8::1"; } ]; 183 }; 184 }; 185 186 # WAN server (IPv4 only) 187 nodes.server = { 188 imports = [ ipv4Only (webserver 4 "Hello from IPv4!") ]; 189 190 virtualisation.vlans = [ 2 ]; 191 networking.interfaces.eth1.ipv4.addresses = 192 [ { address = "203.0.113.16"; prefixLength = 24; } ]; 193 }; 194 195 testScript = '' 196 start_all() 197 198 for node in [client, homeserver, server]: 199 node.wait_for_unit("network-addresses-eth1.service") 200 201 with subtest("Client can ping the WAN server"): 202 router.wait_for_unit("jool-nat64-default.service") 203 client.succeed("ping -c1 64:ff9b::203.0.113.16") 204 205 with subtest("Client can connect to the WAN webserver"): 206 server.wait_for_open_port(80) 207 client.succeed("curl --fail -s http://[64:ff9b::203.0.113.16] | grep -q IPv4!") 208 209 with subtest("Router BIB entries are correctly populated"): 210 router.succeed("jool bib display | grep -q 'Dynamic TCP.*2001:db8::8'") 211 router.succeed("jool bib display | grep -q 'Static TCP.*2001:db8::9'") 212 213 with subtest("WAN server can reach the LAN server"): 214 homeserver.wait_for_open_port(80) 215 server.succeed("curl --fail -s http://203.0.113.1 | grep -q IPv6!") 216 ''; 217 218 }; 219 220}