165 lines
4.5 KiB
Nix
165 lines
4.5 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")
|
|
'';
|
|
}
|
|
)
|