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")
							 | 
						||
| 
								 | 
							
								    '';
							 | 
						||
| 
								 | 
							
								  })
							 |