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