at master 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 25{ pkgs, lib, ... }: 26 27{ 28 name = "tayga"; 29 meta = with pkgs.lib.maintainers; { 30 maintainers = [ hax404 ]; 31 }; 32 33 nodes = { 34 # The server is configured with static IPv4 addresses. We have to disable the 35 # well-known prefix restrictions (as required by RFC 6052 Section 3.1) because 36 # we're using private space (TAYGA also considers documentation space non-global, 37 # unfortunately). 38 # To reach the IPv4 address pool of the NAT64 gateway, there is a static 39 # route configured. In normal cases, where the router would also source NAT 40 # the pool addresses to one IPv4 addresses, this would not be needed. 41 server = { 42 virtualisation.vlans = [ 43 2 # towards router 44 ]; 45 networking = { 46 useDHCP = false; 47 interfaces.eth1 = lib.mkForce { }; 48 }; 49 systemd.network = { 50 enable = true; 51 networks."vlan1" = { 52 matchConfig.Name = "eth1"; 53 address = [ 54 "100.64.0.2/24" 55 ]; 56 routes = [ 57 { 58 Destination = "192.0.2.0/24"; 59 Gateway = "100.64.0.1"; 60 } 61 ]; 62 }; 63 }; 64 programs.mtr.enable = true; 65 environment.systemPackages = [ pkgs.tcpdump ]; 66 }; 67 68 # The router is configured with static IPv4 addresses towards the server 69 # and IPv6 addresses towards the client. For NAT64, the Well-Known prefix 70 # 64:ff9b::/96 is used. NAT64 is done with TAYGA which provides the 71 # tun-interface nat64 and does the translation over it. The IPv6 packets 72 # are sent to this interfaces and received as IPv4 packets and vice versa. 73 # As TAYGA only translates IPv6 addresses to dedicated IPv4 addresses, it 74 # needs a pool of IPv4 addresses which must be at least as big as the 75 # expected amount of clients. In this test, the packets from the pool are 76 # directly routed towards the client. In normal cases, there would be a 77 # second source NAT44 to map all clients behind one IPv4 address. 78 router_systemd = { 79 boot.kernel.sysctl = { 80 "net.ipv4.ip_forward" = 1; 81 "net.ipv6.conf.all.forwarding" = 1; 82 }; 83 84 virtualisation.vlans = [ 85 2 # towards server 86 3 # towards client 87 ]; 88 89 networking = { 90 hostName = "router-systemd"; 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 log = [ 142 "drop" 143 "reject" 144 "icmp" 145 "self" 146 ]; 147 wkpfStrict = false; 148 }; 149 environment.systemPackages = [ pkgs.tcpdump ]; 150 }; 151 152 router_nixos = { 153 boot.kernel.sysctl = { 154 "net.ipv4.ip_forward" = 1; 155 "net.ipv6.conf.all.forwarding" = 1; 156 }; 157 158 virtualisation.vlans = [ 159 2 # towards server 160 3 # towards client 161 ]; 162 163 networking = { 164 hostName = "router-nixos"; 165 useDHCP = false; 166 firewall.enable = false; 167 interfaces.eth1 = lib.mkForce { 168 ipv4 = { 169 addresses = [ 170 { 171 address = "100.64.0.1"; 172 prefixLength = 24; 173 } 174 ]; 175 }; 176 }; 177 interfaces.eth2 = lib.mkForce { 178 ipv6 = { 179 addresses = [ 180 { 181 address = "2001:db8::1"; 182 prefixLength = 64; 183 } 184 ]; 185 }; 186 }; 187 }; 188 189 services.tayga = { 190 enable = true; 191 ipv4 = { 192 address = "192.0.2.0"; 193 router = { 194 address = "192.0.2.1"; 195 }; 196 pool = { 197 address = "192.0.2.0"; 198 prefixLength = 24; 199 }; 200 }; 201 ipv6 = { 202 address = "2001:db8::1"; 203 router = { 204 address = "64:ff9b::1"; 205 }; 206 pool = { 207 address = "64:ff9b::"; 208 prefixLength = 96; 209 }; 210 }; 211 mappings = { 212 "192.0.2.42" = "2001:db8::2"; 213 }; 214 log = [ 215 "drop" 216 "reject" 217 "icmp" 218 "self" 219 ]; 220 wkpfStrict = false; 221 }; 222 environment.systemPackages = [ pkgs.tcpdump ]; 223 }; 224 225 # The client is configured with static IPv6 addresses. It has also a static 226 # route for the NAT64 IP space where the IPv4 addresses are mapped in. In 227 # normal cases, there would be only a default route. 228 client = { 229 virtualisation.vlans = [ 230 3 # towards router 231 ]; 232 233 networking = { 234 useDHCP = false; 235 interfaces.eth1 = lib.mkForce { }; 236 }; 237 238 systemd.network = { 239 enable = true; 240 networks."vlan1" = { 241 matchConfig.Name = "eth1"; 242 address = [ 243 "2001:db8::2/64" 244 ]; 245 routes = [ 246 { 247 Destination = "64:ff9b::/96"; 248 Gateway = "2001:db8::1"; 249 } 250 ]; 251 }; 252 }; 253 programs.mtr.enable = true; 254 environment.systemPackages = [ pkgs.tcpdump ]; 255 }; 256 }; 257 258 testScript = '' 259 # start client and server 260 for machine in client, server: 261 machine.systemctl("start network-online.target") 262 machine.wait_for_unit("network-online.target") 263 machine.log(machine.execute("ip addr")[1]) 264 machine.log(machine.execute("ip route")[1]) 265 machine.log(machine.execute("ip -6 route")[1]) 266 267 # test systemd-networkd and nixos-scripts based router 268 for router in router_systemd, router_nixos: 269 router.start() 270 router.systemctl("start network-online.target") 271 router.wait_for_unit("network-online.target") 272 router.wait_for_unit("tayga.service") 273 router.log(machine.execute("ip addr")[1]) 274 router.log(machine.execute("ip route")[1]) 275 router.log(machine.execute("ip -6 route")[1]) 276 277 with subtest("Wait for tayga"): 278 router.wait_for_unit("tayga.service") 279 280 with subtest("Test ICMP server -> client"): 281 server.wait_until_succeeds("ping -c 3 192.0.2.42 >&2") 282 283 with subtest("Test ICMP and show a traceroute server -> client"): 284 server.wait_until_succeeds("mtr --show-ips --report-wide 192.0.2.42 >&2") 285 286 with subtest("Test ICMP client -> server"): 287 client.wait_until_succeeds("ping -c 3 64:ff9b::100.64.0.2 >&2") 288 289 with subtest("Test ICMP and show a traceroute client -> server"): 290 client.wait_until_succeeds("mtr --show-ips --report-wide 64:ff9b::100.64.0.2 >&2") 291 292 router.log(router.execute("systemd-analyze security tayga.service")[1]) 293 router.shutdown() 294 ''; 295}