at 23.11-pre 5.4 kB view raw
1let 2 aliceIp6 = "202:b70:9b0b:cf34:f93c:8f18:bbfd:7034"; 3 aliceKeys = { 4 PublicKey = "3e91ec9e861960d86e1ce88051f97c435bdf2859640ab681dfa906eb45ad5182"; 5 PrivateKey = "a867f9e078e4ce58d310cf5acd4622d759e2a21df07e1d6fc380a2a26489480d3e91ec9e861960d86e1ce88051f97c435bdf2859640ab681dfa906eb45ad5182"; 6 }; 7 bobIp6 = "202:a483:73a4:9f2d:a559:4a19:bc9:8458"; 8 bobPrefix = "302:a483:73a4:9f2d"; 9 bobConfig = { 10 InterfacePeers = { 11 eth1 = [ "tcp://192.168.1.200:12345" ]; 12 }; 13 MulticastInterfaces = [ { 14 Regex = ".*"; 15 Beacon = true; 16 Listen = true; 17 Port = 54321; 18 Priority = 0; 19 } ]; 20 PublicKey = "2b6f918b6c1a4b54d6bcde86cf74e074fb32ead4ee439b7930df2aa60c825186"; 21 PrivateKey = "0c4a24acd3402722ce9277ed179f4a04b895b49586493c25fbaed60653d857d62b6f918b6c1a4b54d6bcde86cf74e074fb32ead4ee439b7930df2aa60c825186"; 22 }; 23 danIp6 = bobPrefix + "::2"; 24 25in import ./make-test-python.nix ({ pkgs, ...} : { 26 name = "yggdrasil"; 27 meta = with pkgs.lib.maintainers; { 28 maintainers = [ gazally ]; 29 }; 30 31 nodes = rec { 32 # Alice is listening for peerings on a specified port, 33 # but has multicast peering disabled. Alice has part of her 34 # yggdrasil config in Nix and part of it in a file. 35 alice = 36 { ... }: 37 { 38 networking = { 39 interfaces.eth1.ipv4.addresses = [{ 40 address = "192.168.1.200"; 41 prefixLength = 24; 42 }]; 43 firewall.allowedTCPPorts = [ 80 12345 ]; 44 }; 45 services.httpd.enable = true; 46 services.httpd.adminAddr = "foo@example.org"; 47 48 services.yggdrasil = { 49 enable = true; 50 settings = { 51 Listen = ["tcp://0.0.0.0:12345"]; 52 MulticastInterfaces = [ ]; 53 }; 54 configFile = toString (pkgs.writeTextFile { 55 name = "yggdrasil-alice-conf"; 56 text = builtins.toJSON aliceKeys; 57 }); 58 }; 59 }; 60 61 # Bob is set up to peer with Alice, and also to do local multicast 62 # peering. Bob's yggdrasil config is in a file. 63 bob = 64 { ... }: 65 { 66 networking.firewall.allowedTCPPorts = [ 54321 ]; 67 services.yggdrasil = { 68 enable = true; 69 openMulticastPort = true; 70 configFile = toString (pkgs.writeTextFile { 71 name = "yggdrasil-bob-conf"; 72 text = builtins.toJSON bobConfig; 73 }); 74 }; 75 76 boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = 1; 77 78 networking = { 79 bridges.br0.interfaces = [ ]; 80 interfaces.br0 = { 81 ipv6.addresses = [{ 82 address = bobPrefix + "::1"; 83 prefixLength = 64; 84 }]; 85 }; 86 }; 87 88 # dan is a node inside a container running on bob's host. 89 containers.dan = { 90 autoStart = true; 91 privateNetwork = true; 92 hostBridge = "br0"; 93 config = { config, pkgs, ... }: { 94 networking.interfaces.eth0.ipv6 = { 95 addresses = [{ 96 address = bobPrefix + "::2"; 97 prefixLength = 64; 98 }]; 99 routes = [{ 100 address = "200::"; 101 prefixLength = 7; 102 via = bobPrefix + "::1"; 103 }]; 104 }; 105 services.httpd.enable = true; 106 services.httpd.adminAddr = "foo@example.org"; 107 networking.firewall.allowedTCPPorts = [ 80 ]; 108 }; 109 }; 110 }; 111 112 # Carol only does local peering. Carol's yggdrasil config is all Nix. 113 carol = 114 { ... }: 115 { 116 networking.firewall.allowedTCPPorts = [ 43210 ]; 117 services.yggdrasil = { 118 enable = true; 119 denyDhcpcdInterfaces = [ "ygg0" ]; 120 settings = { 121 IfTAPMode = true; 122 IfName = "ygg0"; 123 MulticastInterfaces = [ 124 { 125 Port = 43210; 126 } 127 ]; 128 openMulticastPort = true; 129 }; 130 persistentKeys = true; 131 }; 132 }; 133 }; 134 135 testScript = 136 '' 137 import re 138 139 # Give Alice a head start so she is ready when Bob calls. 140 alice.start() 141 alice.wait_for_unit("yggdrasil.service") 142 143 bob.start() 144 carol.start() 145 bob.wait_for_unit("default.target") 146 carol.wait_for_unit("yggdrasil.service") 147 148 ip_addr_show = "ip -o -6 addr show dev ygg0 scope global" 149 carol.wait_until_succeeds(f"[ `{ip_addr_show} | grep -v tentative | wc -l` -ge 1 ]") 150 carol_ip6 = re.split(" +|/", carol.succeed(ip_addr_show))[3] 151 152 # If Alice can talk to Carol, then Bob's outbound peering and Carol's 153 # local peering have succeeded and everybody is connected. 154 alice.wait_until_succeeds(f"ping -c 1 {carol_ip6}") 155 alice.succeed("ping -c 1 ${bobIp6}") 156 157 bob.succeed("ping -c 1 ${aliceIp6}") 158 bob.succeed(f"ping -c 1 {carol_ip6}") 159 160 carol.succeed("ping -c 1 ${aliceIp6}") 161 carol.succeed("ping -c 1 ${bobIp6}") 162 carol.succeed("ping -c 1 ${bobPrefix}::1") 163 carol.succeed("ping -c 8 ${danIp6}") 164 165 carol.fail("journalctl -u dhcpcd | grep ygg0") 166 167 alice.wait_for_unit("httpd.service") 168 carol.succeed("curl --fail -g http://[${aliceIp6}]") 169 carol.succeed("curl --fail -g http://[${danIp6}]") 170 ''; 171})