140 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| import ../make-test-python.nix ({ lib, ... }:
 | |
|   let
 | |
|     snakeoil-keys = import ./snakeoil-keys.nix;
 | |
| 
 | |
|     hosts = lib.attrNames snakeoil-keys;
 | |
| 
 | |
|     subnetOf = name: config:
 | |
|       let
 | |
|         subnets = config.services.tinc.networks.myNetwork.hostSettings.${name}.subnets;
 | |
|       in
 | |
|       (builtins.head subnets).address;
 | |
| 
 | |
|     makeTincHost = name: { subnet, extraConfig ? { } }: lib.mkMerge [
 | |
|       {
 | |
|         subnets = [{ address = subnet; }];
 | |
|         settings = {
 | |
|           Ed25519PublicKey = snakeoil-keys.${name}.ed25519Public;
 | |
|         };
 | |
|         rsaPublicKey = snakeoil-keys.${name}.rsaPublic;
 | |
|       }
 | |
|       extraConfig
 | |
|     ];
 | |
| 
 | |
|     makeTincNode = { config, ... }: name: extraConfig: lib.mkMerge [
 | |
|       {
 | |
|         services.tinc.networks.myNetwork = {
 | |
|           inherit name;
 | |
|           rsaPrivateKeyFile =
 | |
|             builtins.toFile "rsa.priv" snakeoil-keys.${name}.rsaPrivate;
 | |
|           ed25519PrivateKeyFile =
 | |
|             builtins.toFile "ed25519.priv" snakeoil-keys.${name}.ed25519Private;
 | |
| 
 | |
|           hostSettings = lib.mapAttrs makeTincHost {
 | |
|             static = {
 | |
|               subnet = "10.0.0.11";
 | |
|               # Only specify the addresses in the node's vlans, Tinc does not
 | |
|               # seem to try each one, unlike the documentation suggests...
 | |
|               extraConfig.addresses = map
 | |
|                 (vlan: { address = "192.168.${toString vlan}.11"; port = 655; })
 | |
|                 config.virtualisation.vlans;
 | |
|             };
 | |
|             dynamic1 = { subnet = "10.0.0.21"; };
 | |
|             dynamic2 = { subnet = "10.0.0.22"; };
 | |
|           };
 | |
|         };
 | |
| 
 | |
|         networking.useDHCP = false;
 | |
| 
 | |
|         networking.interfaces."tinc.myNetwork" = {
 | |
|           virtual = true;
 | |
|           virtualType = "tun";
 | |
|           ipv4.addresses = [{
 | |
|             address = subnetOf name config;
 | |
|             prefixLength = 24;
 | |
|           }];
 | |
|         };
 | |
| 
 | |
|         # Prevents race condition between NixOS service and tinc creating the
 | |
|         # interface.
 | |
|         # See: https://github.com/NixOS/nixpkgs/issues/27070
 | |
|         systemd.services."tinc.myNetwork" = {
 | |
|           after = [ "network-addresses-tinc.myNetwork.service" ];
 | |
|           requires = [ "network-addresses-tinc.myNetwork.service" ];
 | |
|         };
 | |
| 
 | |
|         networking.firewall.allowedTCPPorts = [ 655 ];
 | |
|         networking.firewall.allowedUDPPorts = [ 655 ];
 | |
|       }
 | |
|       extraConfig
 | |
|     ];
 | |
| 
 | |
|   in
 | |
|   {
 | |
|     name = "tinc";
 | |
|     meta.maintainers = with lib.maintainers; [ minijackson ];
 | |
| 
 | |
|     nodes = {
 | |
| 
 | |
|       static = { ... } @ args:
 | |
|         makeTincNode args "static" {
 | |
|           virtualisation.vlans = [ 1 2 ];
 | |
| 
 | |
|           networking.interfaces.eth1.ipv4.addresses = [{
 | |
|             address = "192.168.1.11";
 | |
|             prefixLength = 24;
 | |
|           }];
 | |
| 
 | |
|           networking.interfaces.eth2.ipv4.addresses = [{
 | |
|             address = "192.168.2.11";
 | |
|             prefixLength = 24;
 | |
|           }];
 | |
|         };
 | |
| 
 | |
| 
 | |
|       dynamic1 = { ... } @ args:
 | |
|         makeTincNode args "dynamic1" {
 | |
|           virtualisation.vlans = [ 1 ];
 | |
|         };
 | |
| 
 | |
|       dynamic2 = { ... } @ args:
 | |
|         makeTincNode args "dynamic2" {
 | |
|           virtualisation.vlans = [ 2 ];
 | |
|         };
 | |
| 
 | |
|     };
 | |
| 
 | |
|     testScript = ''
 | |
|       start_all()
 | |
| 
 | |
|       static.wait_for_unit("tinc.myNetwork.service")
 | |
|       dynamic1.wait_for_unit("tinc.myNetwork.service")
 | |
|       dynamic2.wait_for_unit("tinc.myNetwork.service")
 | |
| 
 | |
|       # Static is accessible by the other hosts
 | |
|       dynamic1.succeed("ping -c5 192.168.1.11")
 | |
|       dynamic2.succeed("ping -c5 192.168.2.11")
 | |
| 
 | |
|       # The other hosts are in separate vlans
 | |
|       dynamic1.fail("ping -c5 192.168.2.11")
 | |
|       dynamic2.fail("ping -c5 192.168.1.11")
 | |
| 
 | |
|       # Each host can ping themselves through Tinc
 | |
|       static.succeed("ping -c5 10.0.0.11")
 | |
|       dynamic1.succeed("ping -c5 10.0.0.21")
 | |
|       dynamic2.succeed("ping -c5 10.0.0.22")
 | |
| 
 | |
|       # Static is accessible by the other hosts through Tinc
 | |
|       dynamic1.succeed("ping -c5 10.0.0.11")
 | |
|       dynamic2.succeed("ping -c5 10.0.0.11")
 | |
| 
 | |
|       # Static can access the other hosts through Tinc
 | |
|       static.succeed("ping -c5 10.0.0.21")
 | |
|       static.succeed("ping -c5 10.0.0.22")
 | |
| 
 | |
|       # The other hosts in separate vlans can access each other through Tinc
 | |
|       dynamic1.succeed("ping -c5 10.0.0.22")
 | |
|       dynamic2.succeed("ping -c5 10.0.0.21")
 | |
|     '';
 | |
|   })
 | 
