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