216 lines
7.1 KiB
Nix
216 lines
7.1 KiB
Nix
{
|
|
lib,
|
|
config,
|
|
...
|
|
}:
|
|
|
|
let
|
|
machines = [
|
|
"controller1"
|
|
"controller2"
|
|
"peer1"
|
|
"peer2"
|
|
"peer3"
|
|
# external machine for external peer testing
|
|
"external1"
|
|
];
|
|
|
|
controllerPrefix =
|
|
controllerName:
|
|
builtins.readFile (
|
|
config.clan.directory
|
|
+ "/vars/per-machine/${controllerName}/wireguard-network-wg-test-one/prefix/value"
|
|
);
|
|
peerSuffix =
|
|
peerName:
|
|
builtins.readFile (
|
|
config.clan.directory + "/vars/per-machine/${peerName}/wireguard-network-wg-test-one/suffix/value"
|
|
);
|
|
# external peer suffixes are stored via shared vars
|
|
externalPeerSuffix =
|
|
externalName:
|
|
builtins.readFile (
|
|
config.clan.directory
|
|
+ "/vars/shared/wireguard-network-wg-test-one-external-peer-${externalName}/suffix/value"
|
|
);
|
|
in
|
|
{
|
|
name = "wireguard";
|
|
|
|
clan = {
|
|
directory = ./.;
|
|
inventory = {
|
|
|
|
machines = lib.genAttrs machines (_: { });
|
|
|
|
instances = {
|
|
|
|
/*
|
|
wg-test-one
|
|
┌───────────────────────────────┐
|
|
│ ◄───────────── │
|
|
│ controller2 controller1
|
|
│ ▲ ─────────────► ▲ ▲
|
|
│ │ │ │ │ │ │ │ │
|
|
│ │ │ │ │ │ │ │ │
|
|
│ │ │ │ │ │ │ │ │
|
|
│ │ │ │ └───────────────┐ │ │ │ │
|
|
│ │ │ └──────────────┐ │ │ │ │ │
|
|
│ ▼ │ ▼ ▼ ▼
|
|
└─► peer2 │ peer1 peer3
|
|
│ ▲
|
|
└──────────┘
|
|
*/
|
|
|
|
wg-test-one = {
|
|
|
|
module.name = "@clan/wireguard";
|
|
module.input = "self";
|
|
|
|
roles.controller.machines."controller1".settings = {
|
|
endpoint = "192.168.1.1";
|
|
# add an external peer to controller1 only
|
|
externalPeers = [ "external1" ];
|
|
};
|
|
|
|
roles.controller.machines."controller2".settings = {
|
|
endpoint = "192.168.1.2";
|
|
# add the same external peer to controller2 to test multi-controller connection
|
|
externalPeers = [ "external1" ];
|
|
};
|
|
|
|
roles.peer.machines = {
|
|
peer1.settings.controller = "controller1";
|
|
peer2.settings.controller = "controller2";
|
|
peer3.settings.controller = "controller1";
|
|
};
|
|
};
|
|
|
|
# TODO: Will this actually work with conflicting ports? Can we re-use interfaces?
|
|
#wg-test-two = {
|
|
# module.name = "@clan/wireguard";
|
|
|
|
# roles.controller.machines."controller1".settings = {
|
|
# endpoint = "192.168.1.1";
|
|
# port = 51922;
|
|
# };
|
|
|
|
# roles.peer.machines = {
|
|
# peer1 = { };
|
|
# };
|
|
#};
|
|
};
|
|
};
|
|
};
|
|
|
|
nodes.external1 =
|
|
let
|
|
controller1Prefix = controllerPrefix "controller1";
|
|
controller2Prefix = controllerPrefix "controller2";
|
|
external1Suffix = externalPeerSuffix "external1";
|
|
in
|
|
{
|
|
networking.extraHosts = ''
|
|
${controller1Prefix}::1 controller1.wg-test-one
|
|
${controller2Prefix}::1 controller2.wg-test-one
|
|
'';
|
|
networking.wireguard.interfaces."wg0" = {
|
|
|
|
# Multiple IPs, one in each controller's subnet
|
|
ips = [
|
|
"${controller1Prefix + ":" + external1Suffix}/56"
|
|
"${controller2Prefix + ":" + external1Suffix}/56"
|
|
];
|
|
|
|
privateKeyFile =
|
|
builtins.toFile "wg-priv-key"
|
|
# This needs to be updated whenever update-vars was executed
|
|
# Get the value from the generated vars via this command:
|
|
# echo "AGE-SECRET-KEY-1PL0M9CWRCG3PZ9DXRTTLMCVD57U6JDFE8K7DNVQ35F4JENZ6G3MQ0RQLRV" | SOPS_AGE_KEY_FILE=/dev/stdin nix run nixpkgs#sops decrypt clanServices/wireguard/tests/vm/vars/shared/wireguard-network-wg-test-one-external-peer-external1/privatekey/secret
|
|
"wO8dl3JWgV5J+0D/2UDcLsxTD25IWTvd5ed6vv2Nikk=";
|
|
|
|
# Connect to both controllers
|
|
peers = [
|
|
# Controller 1
|
|
{
|
|
publicKey = (
|
|
builtins.readFile (
|
|
config.clan.directory + "/vars/per-machine/controller1/wireguard-keys-wg-test-one/publickey/value"
|
|
)
|
|
);
|
|
|
|
# Allow controller1's /56 subnet
|
|
allowedIPs = [ "${controller1Prefix}::/56" ];
|
|
|
|
endpoint = "controller1:51820";
|
|
|
|
persistentKeepalive = 25;
|
|
}
|
|
# Controller 2
|
|
{
|
|
publicKey = (
|
|
builtins.readFile (
|
|
config.clan.directory + "/vars/per-machine/controller2/wireguard-keys-wg-test-one/publickey/value"
|
|
)
|
|
);
|
|
|
|
# Allow controller2's /56 subnet
|
|
allowedIPs = [ "${controller2Prefix}::/56" ];
|
|
|
|
endpoint = "controller2:51820";
|
|
|
|
persistentKeepalive = 25;
|
|
}
|
|
];
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
start_all()
|
|
|
|
# Start network on all machines including external1
|
|
machines = [peer1, peer2, peer3, controller1, controller2, external1]
|
|
for m in machines:
|
|
m.systemctl("start network-online.target")
|
|
|
|
for m in machines:
|
|
m.wait_for_unit("network-online.target")
|
|
m.wait_for_unit("systemd-networkd.service")
|
|
|
|
print("\n\n" + "="*60)
|
|
print("STARTING PING TESTS")
|
|
print("="*60)
|
|
|
|
# Test mesh connectivity between regular clan machines
|
|
clan_machines = [peer1, peer2, peer3, controller1, controller2]
|
|
for m1 in clan_machines:
|
|
for m2 in clan_machines:
|
|
if m1 != m2:
|
|
print(f"\n--- Pinging from {m1.name} to {m2.name}.wg-test-one ---")
|
|
m1.wait_until_succeeds(f"ping -c1 {m2.name}.wg-test-one >&2")
|
|
|
|
# Test that external peer can reach both controllers (multi-controller connection)
|
|
print("\n--- Testing external1 -> controller1 (direct connection) ---")
|
|
external1.wait_until_succeeds("ping -c1 controller1.wg-test-one >&2")
|
|
|
|
print("\n--- Testing external1 -> controller2 (direct connection) ---")
|
|
external1.wait_until_succeeds("ping -c1 controller2.wg-test-one >&2")
|
|
|
|
# Test that all clan machines can reach the external peer
|
|
for m in clan_machines:
|
|
print(f"\n--- Pinging from {m.name} to external1.wg-test-one ---")
|
|
m.wait_until_succeeds("ping -c1 external1.wg-test-one >&2")
|
|
|
|
# Test that external peer can reach a regular peer via controller1
|
|
print("\n--- Testing external1 -> peer1 (via controller1) ---")
|
|
external1.wait_until_succeeds("ping -c1 ${controllerPrefix "controller1"}:${peerSuffix "peer1"} >&2")
|
|
|
|
# Test controller failover
|
|
print("\n--- Shutting down controller1 ---")
|
|
controller1.shutdown()
|
|
print("\n--- Testing external1 -> peer1 (via controller2 after controller1 shutdown) ---")
|
|
external1.wait_until_succeeds("ping -c1 ${controllerPrefix "controller2"}:${peerSuffix "peer1"} >&2")
|
|
|
|
'';
|
|
}
|