at 23.05-pre 4.3 kB view raw
1import ../make-test-python.nix ({ lib, ... }: 2 let 3 snakeoil-keys = import ./snakeoil-keys.nix; 4 5 hosts = lib.attrNames snakeoil-keys; 6 7 subnetOf = name: config: 8 let 9 subnets = config.services.tinc.networks.myNetwork.hostSettings.${name}.subnets; 10 in 11 (builtins.head subnets).address; 12 13 makeTincHost = name: { subnet, extraConfig ? { } }: lib.mkMerge [ 14 { 15 subnets = [{ address = subnet; }]; 16 settings = { 17 Ed25519PublicKey = snakeoil-keys.${name}.ed25519Public; 18 }; 19 rsaPublicKey = snakeoil-keys.${name}.rsaPublic; 20 } 21 extraConfig 22 ]; 23 24 makeTincNode = { config, ... }: name: extraConfig: lib.mkMerge [ 25 { 26 services.tinc.networks.myNetwork = { 27 inherit name; 28 rsaPrivateKeyFile = 29 builtins.toFile "rsa.priv" snakeoil-keys.${name}.rsaPrivate; 30 ed25519PrivateKeyFile = 31 builtins.toFile "ed25519.priv" snakeoil-keys.${name}.ed25519Private; 32 33 hostSettings = lib.mapAttrs makeTincHost { 34 static = { 35 subnet = "10.0.0.11"; 36 # Only specify the addresses in the node's vlans, Tinc does not 37 # seem to try each one, unlike the documentation suggests... 38 extraConfig.addresses = map 39 (vlan: { address = "192.168.${toString vlan}.11"; port = 655; }) 40 config.virtualisation.vlans; 41 }; 42 dynamic1 = { subnet = "10.0.0.21"; }; 43 dynamic2 = { subnet = "10.0.0.22"; }; 44 }; 45 }; 46 47 networking.useDHCP = false; 48 49 networking.interfaces."tinc.myNetwork" = { 50 virtual = true; 51 virtualType = "tun"; 52 ipv4.addresses = [{ 53 address = subnetOf name config; 54 prefixLength = 24; 55 }]; 56 }; 57 58 # Prevents race condition between NixOS service and tinc creating the 59 # interface. 60 # See: https://github.com/NixOS/nixpkgs/issues/27070 61 systemd.services."tinc.myNetwork" = { 62 after = [ "network-addresses-tinc.myNetwork.service" ]; 63 requires = [ "network-addresses-tinc.myNetwork.service" ]; 64 }; 65 66 networking.firewall.allowedTCPPorts = [ 655 ]; 67 networking.firewall.allowedUDPPorts = [ 655 ]; 68 } 69 extraConfig 70 ]; 71 72 in 73 { 74 name = "tinc"; 75 meta.maintainers = with lib.maintainers; [ minijackson ]; 76 77 nodes = { 78 79 static = { ... } @ args: 80 makeTincNode args "static" { 81 virtualisation.vlans = [ 1 2 ]; 82 83 networking.interfaces.eth1.ipv4.addresses = [{ 84 address = "192.168.1.11"; 85 prefixLength = 24; 86 }]; 87 88 networking.interfaces.eth2.ipv4.addresses = [{ 89 address = "192.168.2.11"; 90 prefixLength = 24; 91 }]; 92 }; 93 94 95 dynamic1 = { ... } @ args: 96 makeTincNode args "dynamic1" { 97 virtualisation.vlans = [ 1 ]; 98 }; 99 100 dynamic2 = { ... } @ args: 101 makeTincNode args "dynamic2" { 102 virtualisation.vlans = [ 2 ]; 103 }; 104 105 }; 106 107 testScript = '' 108 start_all() 109 110 static.wait_for_unit("tinc.myNetwork.service") 111 dynamic1.wait_for_unit("tinc.myNetwork.service") 112 dynamic2.wait_for_unit("tinc.myNetwork.service") 113 114 # Static is accessible by the other hosts 115 dynamic1.succeed("ping -c5 192.168.1.11") 116 dynamic2.succeed("ping -c5 192.168.2.11") 117 118 # The other hosts are in separate vlans 119 dynamic1.fail("ping -c5 192.168.2.11") 120 dynamic2.fail("ping -c5 192.168.1.11") 121 122 # Each host can ping themselves through Tinc 123 static.succeed("ping -c5 10.0.0.11") 124 dynamic1.succeed("ping -c5 10.0.0.21") 125 dynamic2.succeed("ping -c5 10.0.0.22") 126 127 # Static is accessible by the other hosts through Tinc 128 dynamic1.succeed("ping -c5 10.0.0.11") 129 dynamic2.succeed("ping -c5 10.0.0.11") 130 131 # Static can access the other hosts through Tinc 132 static.succeed("ping -c5 10.0.0.21") 133 static.succeed("ping -c5 10.0.0.22") 134 135 # The other hosts in separate vlans can access each other through Tinc 136 dynamic1.succeed("ping -c5 10.0.0.22") 137 dynamic2.succeed("ping -c5 10.0.0.21") 138 ''; 139 })