Files
clan-core/clanServices/wireguard/tests/vm/default.nix
DavHau 6a3f5e077b wireguard: add support for external peers
This adds support for external peers via the instance option `roles.controller.<name>.settings.externalPeers = ["external1"]`.

External peers are peers which are not associated wth a machine inside the clan, for example a mobile phone or a device that cannot be managed via clan for some reason.
2025-10-21 11:49:37 +07:00

168 lines
5.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"
);
# 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";
};
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";
external1Suffix = externalPeerSuffix "external1";
in
{
networking.extraHosts = ''
${controller1Prefix}::1 controller1.wg-test-one
'';
networking.wireguard.interfaces."wg0" = {
ips = [ "${controller1Prefix + ":" + 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=";
peers = [
{
publicKey = (
builtins.readFile (
config.clan.directory + "/vars/per-machine/controller1/wireguard-keys-wg-test-one/publickey/value"
)
);
# Allow each controller's /56 subnet
allowedIPs = [
# "${controller1Prefix}::/56"
"::/0"
];
endpoint = "controller1:51820";
persistentKeepalive = 25;
}
];
};
};
testScript = ''
start_all()
# Show all addresses
machines = [peer1, peer2, peer3, controller1, controller2]
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)
for m1 in machines:
# ping all other machines
for m2 in 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")
# ping external peer from all other peers and controllers
print(f"\n--- Pinging from {m1.name} to external1.wg-test-one ---")
m1.wait_until_succeeds("ping -c1 external1.wg-test-one >&2")
'';
}