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