nixosTests.wireguard: handleTest -> runTest

(cherry picked from commit 71d0e1c8b5ffc0a4e8b6a85ce85b1a32d2dbcf8a)
This commit is contained in:
Sizhe Zhao 2025-07-13 23:06:35 +08:00
parent 0ba7638e25
commit ef29596a75
No known key found for this signature in database
GPG Key ID: ED1807251A7DA08F
11 changed files with 532 additions and 534 deletions

View File

@ -1553,7 +1553,10 @@ in
whoogle-search = runTest ./whoogle-search.nix; whoogle-search = runTest ./whoogle-search.nix;
wiki-js = runTest ./wiki-js.nix; wiki-js = runTest ./wiki-js.nix;
wine = handleTest ./wine.nix { }; wine = handleTest ./wine.nix { };
wireguard = handleTest ./wireguard { }; wireguard = import ./wireguard {
inherit pkgs runTest;
inherit (pkgs) lib;
};
wg-access-server = runTest ./wg-access-server.nix; wg-access-server = runTest ./wg-access-server.nix;
without-nix = runTest ./without-nix.nix; without-nix = runTest ./without-nix.nix;
wmderland = runTest ./wmderland.nix; wmderland = runTest ./wmderland.nix;

View File

@ -1,125 +1,120 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, nftables ? false,
kernelPackages ? null, ...
nftables ? false, }:
... let
}: wg-snakeoil-keys = import ./snakeoil-keys.nix;
let peer = import ./make-peer.nix;
wg-snakeoil-keys = import ./snakeoil-keys.nix; commonConfig =
peer = import ./make-peer.nix { inherit lib; }; { pkgs, ... }:
commonConfig = { {
boot.kernelPackages = lib.mkIf (kernelPackages != null) kernelPackages; boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.nftables.enable = nftables; networking.nftables.enable = nftables;
# Make sure iptables doesn't work with nftables enabled # Make sure iptables doesn't work with nftables enabled
boot.blacklistedKernelModules = lib.mkIf nftables [ "nft_compat" ]; boot.blacklistedKernelModules = lib.mkIf nftables [ "nft_compat" ];
}; };
extraOptions = { extraOptions = {
Jc = 5; Jc = 5;
Jmin = 10; Jmin = 10;
Jmax = 42; Jmax = 42;
S1 = 60; S1 = 60;
S2 = 90; S2 = 90;
}; };
in in
{ {
name = "amneziawg-quick"; name = "amneziawg-quick";
meta = with pkgs.lib.maintainers; { meta.maintainers = with lib.maintainers; [
maintainers = [ averyanalex
averyanalex azahi
azahi ];
];
};
nodes = { nodes = {
peer0 = peer { peer0 = peer {
ip4 = "192.168.0.1"; ip4 = "192.168.0.1";
ip6 = "fd00::1"; ip6 = "fd00::1";
extraConfig = lib.mkMerge [ extraConfig = {
commonConfig imports = [ commonConfig ];
{
networking.firewall.allowedUDPPorts = [ 23542 ];
networking.wg-quick.interfaces.wg0 = {
type = "amneziawg";
address = [ networking.firewall.allowedUDPPorts = [ 23542 ];
"10.23.42.1/32" networking.wg-quick.interfaces.wg0 = {
"fc00::1/128" type = "amneziawg";
];
listenPort = 23542;
inherit (wg-snakeoil-keys.peer0) privateKey; address = [
"10.23.42.1/32"
"fc00::1/128"
];
listenPort = 23542;
peers = lib.singleton { inherit (wg-snakeoil-keys.peer0) privateKey;
allowedIPs = [
"10.23.42.2/32"
"fc00::2/128"
];
inherit (wg-snakeoil-keys.peer1) publicKey; peers = lib.singleton {
}; allowedIPs = [
"10.23.42.2/32"
"fc00::2/128"
];
dns = [ inherit (wg-snakeoil-keys.peer1) publicKey;
"10.23.42.2" };
"fc00::2"
"wg0"
];
inherit extraOptions; dns = [
}; "10.23.42.2"
} "fc00::2"
]; "wg0"
}; ];
peer1 = peer { inherit extraOptions;
ip4 = "192.168.0.2"; };
ip6 = "fd00::2";
extraConfig = lib.mkMerge [
commonConfig
{
networking.useNetworkd = true;
networking.wg-quick.interfaces.wg0 = {
type = "amneziawg";
address = [
"10.23.42.2/32"
"fc00::2/128"
];
inherit (wg-snakeoil-keys.peer1) privateKey;
peers = lib.singleton {
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
endpoint = "192.168.0.1:23542";
persistentKeepalive = 25;
inherit (wg-snakeoil-keys.peer0) publicKey;
};
dns = [
"10.23.42.1"
"fc00::1"
"wg0"
];
inherit extraOptions;
};
}
];
}; };
}; };
testScript = '' peer1 = peer {
start_all() ip4 = "192.168.0.2";
ip6 = "fd00::2";
extraConfig = {
imports = [ commonConfig ];
peer0.wait_for_unit("wg-quick-wg0.service") networking.useNetworkd = true;
peer1.wait_for_unit("wg-quick-wg0.service") networking.wg-quick.interfaces.wg0 = {
type = "amneziawg";
peer1.succeed("ping -c5 fc00::1") address = [
peer1.succeed("ping -c5 10.23.42.1") "10.23.42.2/32"
''; "fc00::2/128"
} ];
) inherit (wg-snakeoil-keys.peer1) privateKey;
peers = lib.singleton {
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
endpoint = "192.168.0.1:23542";
persistentKeepalive = 25;
inherit (wg-snakeoil-keys.peer0) publicKey;
};
dns = [
"10.23.42.1"
"fc00::1"
"wg0"
];
inherit extraOptions;
};
};
};
};
testScript = ''
start_all()
peer0.wait_for_unit("wg-quick-wg0.service")
peer1.wait_for_unit("wg-quick-wg0.service")
peer1.succeed("ping -c5 fc00::1")
peer1.succeed("ping -c5 10.23.42.1")
'';
}

View File

@ -1,36 +1,34 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, ...
kernelPackages ? null, }:
... let
}: wg-snakeoil-keys = import ./snakeoil-keys.nix;
let peer = import ./make-peer.nix;
wg-snakeoil-keys = import ./snakeoil-keys.nix; extraOptions = {
peer = (import ./make-peer.nix) { inherit lib; }; Jc = 5;
extraOptions = { Jmin = 10;
Jc = 5; Jmax = 42;
Jmin = 10; S1 = 60;
Jmax = 42; S2 = 90;
S1 = 60; };
S2 = 90; in
}; {
in name = "amneziawg";
{ meta.maintainers = with lib.maintainers; [
name = "amneziawg"; averyanalex
meta = with pkgs.lib.maintainers; { azahi
maintainers = [ ];
averyanalex
azahi
];
};
nodes = { nodes = {
peer0 = peer { peer0 = peer {
ip4 = "192.168.0.1"; ip4 = "192.168.0.1";
ip6 = "fd00::1"; ip6 = "fd00::1";
extraConfig = { extraConfig =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.firewall.allowedUDPPorts = [ 23542 ]; networking.firewall.allowedUDPPorts = [ 23542 ];
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
type = "amneziawg"; type = "amneziawg";
@ -54,13 +52,15 @@ import ../make-test-python.nix (
inherit extraOptions; inherit extraOptions;
}; };
}; };
}; };
peer1 = peer { peer1 = peer {
ip4 = "192.168.0.2"; ip4 = "192.168.0.2";
ip6 = "fd00::2"; ip6 = "fd00::2";
extraConfig = { extraConfig =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
type = "amneziawg"; type = "amneziawg";
ips = [ ips = [
@ -85,27 +85,26 @@ import ../make-test-python.nix (
postSetup = postSetup =
let let
inherit (pkgs) iproute2; ip = lib.getExe' pkgs.iproute2 "ip";
in in
'' ''
${iproute2}/bin/ip route replace 10.23.42.1/32 dev wg0 ${ip} route replace 10.23.42.1/32 dev wg0
${iproute2}/bin/ip route replace fc00::1/128 dev wg0 ${ip} route replace fc00::1/128 dev wg0
''; '';
inherit extraOptions; inherit extraOptions;
}; };
}; };
};
}; };
};
testScript = '' testScript = ''
start_all() start_all()
peer0.wait_for_unit("wireguard-wg0.service") peer0.wait_for_unit("wireguard-wg0.service")
peer1.wait_for_unit("wireguard-wg0.service") peer1.wait_for_unit("wireguard-wg0.service")
peer1.succeed("ping -c5 fc00::1") peer1.succeed("ping -c5 fc00::1")
peer1.succeed("ping -c5 10.23.42.1") peer1.succeed("ping -c5 10.23.42.1")
''; '';
} }
)

View File

@ -1,26 +1,24 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, ...
kernelPackages ? null, }:
... let
}: wg-snakeoil-keys = import ./snakeoil-keys.nix;
let peer = import ./make-peer.nix;
wg-snakeoil-keys = import ./snakeoil-keys.nix; in
peer = (import ./make-peer.nix) { inherit lib; }; {
in name = "wireguard";
{ meta.maintainers = with lib.maintainers; [ ma27 ];
name = "wireguard";
meta = with pkgs.lib.maintainers; {
maintainers = [ ma27 ];
};
nodes = { nodes = {
peer0 = peer { peer0 = peer {
ip4 = "192.168.0.1"; ip4 = "192.168.0.1";
ip6 = "fd00::1"; ip6 = "fd00::1";
extraConfig = { extraConfig =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.firewall.allowedUDPPorts = [ 23542 ]; networking.firewall.allowedUDPPorts = [ 23542 ];
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
ips = [ ips = [
@ -41,13 +39,15 @@ import ../make-test-python.nix (
}; };
}; };
}; };
}; };
peer1 = peer { peer1 = peer {
ip4 = "192.168.0.2"; ip4 = "192.168.0.2";
ip6 = "fd00::2"; ip6 = "fd00::2";
extraConfig = { extraConfig =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
ips = [ ips = [
"10.23.42.2/32" "10.23.42.2/32"
@ -71,25 +71,24 @@ import ../make-test-python.nix (
postSetup = postSetup =
let let
inherit (pkgs) iproute2; ip = lib.getExe' pkgs.iproute2 "ip";
in in
'' ''
${iproute2}/bin/ip route replace 10.23.42.1/32 dev wg0 ${ip} route replace 10.23.42.1/32 dev wg0
${iproute2}/bin/ip route replace fc00::1/128 dev wg0 ${ip} route replace fc00::1/128 dev wg0
''; '';
}; };
}; };
};
}; };
};
testScript = '' testScript = ''
start_all() start_all()
peer0.wait_for_unit("wireguard-wg0.service") peer0.wait_for_unit("wireguard-wg0.service")
peer1.wait_for_unit("wireguard-wg0.service") peer1.wait_for_unit("wireguard-wg0.service")
peer1.succeed("ping -c5 fc00::1") peer1.succeed("ping -c5 fc00::1")
peer1.succeed("ping -c5 10.23.42.1") peer1.succeed("ping -c5 10.23.42.1")
''; '';
} }
)

View File

@ -1,46 +1,49 @@
{ {
system ? builtins.currentSystem, runTest,
config ? { }, lib,
pkgs ? import ../../.. { inherit system config; }, pkgs,
# Test current default (LTS) and latest kernel # Test current default (LTS) and latest kernel
kernelVersionsToTest ? [ kernelVersionsToTest ? [
(pkgs.lib.versions.majorMinor pkgs.linuxPackages.kernel.version) (lib.versions.majorMinor pkgs.linuxPackages.kernel.version)
"latest" "latest"
], ],
}: }:
with pkgs.lib;
let let
tests = tests =
let let
callTest = p: args: import p ({ inherit system pkgs; } // args); callTest =
p: args:
runTest {
imports = [ p ];
_module = { inherit args; };
};
in in
{ {
basic = callTest ./basic.nix; basic = callTest ./basic.nix;
amneziawg = callTest ./amneziawg.nix; amneziawg = callTest ./amneziawg.nix;
namespaces = callTest ./namespaces.nix; namespaces = callTest ./namespaces.nix;
networkd = callTest ./networkd.nix; networkd = callTest ./networkd.nix;
wg-quick = callTest ./wg-quick.nix; wg-quick = args: callTest ./wg-quick.nix ({ nftables = false; } // args);
wg-quick-nftables = args: callTest ./wg-quick.nix ({ nftables = true; } // args); wg-quick-nftables = args: callTest ./wg-quick.nix ({ nftables = true; } // args);
amneziawg-quick = callTest ./amneziawg-quick.nix; amneziawg-quick = args: callTest ./amneziawg-quick.nix ({ nftables = false; } // args);
generated = callTest ./generated.nix; generated = callTest ./generated.nix;
dynamic-refresh = callTest ./dynamic-refresh.nix; dynamic-refresh = args: callTest ./dynamic-refresh.nix ({ useNetworkd = false; } // args);
dynamic-refresh-networkd = args: callTest ./dynamic-refresh.nix ({ useNetworkd = true; } // args); dynamic-refresh-networkd = args: callTest ./dynamic-refresh.nix ({ useNetworkd = true; } // args);
}; };
in in
listToAttrs ( lib.listToAttrs (
flip concatMap kernelVersionsToTest ( lib.flip lib.concatMap kernelVersionsToTest (
version: version:
let let
v' = replaceStrings [ "." ] [ "_" ] version; v' = lib.replaceString "." "_" version;
in in
flip mapAttrsToList tests ( lib.flip lib.mapAttrsToList tests (
name: test: name: test:
nameValuePair "wireguard-${name}-linux-${v'}" (test { lib.nameValuePair "wireguard-${name}-linux-${v'}" (test {
kernelPackages = kernelPackages =
if v' == "latest" then pkgs.linuxPackages_latest else pkgs.linuxKernel.packages."linux_${v'}"; pkgs: if v' == "latest" then pkgs.linuxPackages_latest else pkgs.linuxKernel.packages."linux_${v'}";
}) })
) )
) )

View File

@ -1,27 +1,25 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, useNetworkd ? false,
kernelPackages ? null, ...
useNetworkd ? false, }:
... let
}: wg-snakeoil-keys = import ./snakeoil-keys.nix;
let in
wg-snakeoil-keys = import ./snakeoil-keys.nix; {
in name = "wireguard-dynamic-refresh";
{ meta.maintainers = with lib.maintainers; [ majiir ];
name = "wireguard-dynamic-refresh";
meta = with lib.maintainers; {
maintainers = [ majiir ];
};
nodes = { nodes = {
server = { server =
{ lib, pkgs, ... }:
{
virtualisation.vlans = [ virtualisation.vlans = [
1 1
2 2
]; ];
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.firewall.allowedUDPPorts = [ 23542 ]; networking.firewall.allowedUDPPorts = [ 23542 ];
networking.useDHCP = false; networking.useDHCP = false;
networking.wireguard.useNetworkd = useNetworkd; networking.wireguard.useNetworkd = useNetworkd;
@ -40,66 +38,70 @@ import ../make-test-python.nix (
}; };
}; };
client = client =
{ nodes, ... }: {
{ nodes,
virtualisation.vlans = [ lib,
1 pkgs,
2 ...
]; }:
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; {
networking.useDHCP = false; virtualisation.vlans = [
networking.wireguard.useNetworkd = useNetworkd; 1
networking.wireguard.interfaces.wg0 = { 2
ips = [ "10.23.42.2/32" ]; ];
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.useDHCP = false;
networking.wireguard.useNetworkd = useNetworkd;
networking.wireguard.interfaces.wg0 = {
ips = [ "10.23.42.2/32" ];
# !!! Don't do this with real keys. The /nix store is world-readable! # !!! Don't do this with real keys. The /nix store is world-readable!
privateKeyFile = toString (pkgs.writeText "privateKey" wg-snakeoil-keys.peer1.privateKey); privateKeyFile = toString (pkgs.writeText "privateKey" wg-snakeoil-keys.peer1.privateKey);
dynamicEndpointRefreshSeconds = 2; dynamicEndpointRefreshSeconds = 2;
peers = lib.singleton { peers = lib.singleton {
allowedIPs = [ allowedIPs = [
"0.0.0.0/0" "0.0.0.0/0"
"::/0" "::/0"
]; ];
endpoint = "server:23542"; endpoint = "server:23542";
inherit (wg-snakeoil-keys.peer0) publicKey; inherit (wg-snakeoil-keys.peer0) publicKey;
};
};
specialisation.update-hosts.configuration = {
networking.extraHosts =
let
testCfg = nodes.server.virtualisation.test;
in
lib.mkForce "192.168.2.${toString testCfg.nodeNumber} ${testCfg.nodeName}";
}; };
}; };
};
testScript = specialisation.update-hosts.configuration = {
{ nodes, ... }: networking.extraHosts =
'' let
start_all() testCfg = nodes.server.virtualisation.test;
in
lib.mkForce "192.168.2.${toString testCfg.nodeNumber} ${testCfg.nodeName}";
};
};
};
server.systemctl("start network-online.target") testScript =
server.wait_for_unit("network-online.target") { nodes, ... }:
''
start_all()
client.systemctl("start network-online.target") server.systemctl("start network-online.target")
client.wait_for_unit("network-online.target") server.wait_for_unit("network-online.target")
client.succeed("ping -n -w 1 -c 1 10.23.42.1") client.systemctl("start network-online.target")
client.wait_for_unit("network-online.target")
client.succeed("ip link set down eth1") client.succeed("ping -n -w 1 -c 1 10.23.42.1")
client.fail("ping -n -w 1 -c 1 10.23.42.1") client.succeed("ip link set down eth1")
with client.nested("update hosts file"): client.fail("ping -n -w 1 -c 1 10.23.42.1")
client.succeed("${nodes.client.system.build.toplevel}/specialisation/update-hosts/bin/switch-to-configuration test")
client.succeed("sleep 5 && ping -n -w 1 -c 1 10.23.42.1") with client.nested("update hosts file"):
''; client.succeed("${nodes.client.system.build.toplevel}/specialisation/update-hosts/bin/switch-to-configuration test")
}
) client.succeed("sleep 5 && ping -n -w 1 -c 1 10.23.42.1")
'';
}

View File

@ -1,22 +1,20 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, ...
kernelPackages ? null, }:
... {
}: name = "wireguard-generated";
{ meta.maintainers = with lib.maintainers; [
name = "wireguard-generated"; ma27
meta = with pkgs.lib.maintainers; { grahamc
maintainers = [ ];
ma27
grahamc
];
};
nodes = { nodes = {
peer1 = { peer1 =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.firewall.allowedUDPPorts = [ 12345 ]; networking.firewall.allowedUDPPorts = [ 12345 ];
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
ips = [ "10.10.10.1/24" ]; ips = [ "10.10.10.1/24" ];
@ -27,8 +25,10 @@ import ../make-test-python.nix (
}; };
}; };
peer2 = { peer2 =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.firewall.allowedUDPPorts = [ 12345 ]; networking.firewall.allowedUDPPorts = [ 12345 ];
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
ips = [ "10.10.10.2/24" ]; ips = [ "10.10.10.2/24" ];
@ -37,38 +37,37 @@ import ../make-test-python.nix (
generatePrivateKeyFile = true; generatePrivateKeyFile = true;
}; };
}; };
}; };
testScript = '' testScript = ''
start_all() start_all()
peer1.wait_for_unit("wireguard-wg0.service") peer1.wait_for_unit("wireguard-wg0.service")
peer2.wait_for_unit("wireguard-wg0.service") peer2.wait_for_unit("wireguard-wg0.service")
retcode, peer1pubkey = peer1.execute("wg pubkey < /etc/wireguard/private") retcode, peer1pubkey = peer1.execute("wg pubkey < /etc/wireguard/private")
if retcode != 0: if retcode != 0:
raise Exception("Could not read public key from peer1") raise Exception("Could not read public key from peer1")
retcode, peer2pubkey = peer2.execute("wg pubkey < /etc/wireguard/private") retcode, peer2pubkey = peer2.execute("wg pubkey < /etc/wireguard/private")
if retcode != 0: if retcode != 0:
raise Exception("Could not read public key from peer2") raise Exception("Could not read public key from peer2")
peer1.succeed( peer1.succeed(
"wg set wg0 peer {} allowed-ips 10.10.10.2/32 endpoint 192.168.1.2:12345 persistent-keepalive 1".format( "wg set wg0 peer {} allowed-ips 10.10.10.2/32 endpoint 192.168.1.2:12345 persistent-keepalive 1".format(
peer2pubkey.strip() peer2pubkey.strip()
) )
) )
peer1.succeed("ip route replace 10.10.10.2/32 dev wg0 table main") peer1.succeed("ip route replace 10.10.10.2/32 dev wg0 table main")
peer2.succeed( peer2.succeed(
"wg set wg0 peer {} allowed-ips 10.10.10.1/32 endpoint 192.168.1.1:12345 persistent-keepalive 1".format( "wg set wg0 peer {} allowed-ips 10.10.10.1/32 endpoint 192.168.1.1:12345 persistent-keepalive 1".format(
peer1pubkey.strip() peer1pubkey.strip()
) )
) )
peer2.succeed("ip route replace 10.10.10.1/32 dev wg0 table main") peer2.succeed("ip route replace 10.10.10.1/32 dev wg0 table main")
peer1.succeed("ping -c1 10.10.10.2") peer1.succeed("ping -c1 10.10.10.2")
peer2.succeed("ping -c1 10.10.10.1") peer2.succeed("ping -c1 10.10.10.1")
''; '';
} }
)

View File

@ -1,32 +1,33 @@
{ lib, ... }:
{ {
ip4, ip4,
ip6, ip6,
extraConfig, extraConfig,
}: }:
lib.mkMerge [ {
{ imports = [
boot.kernel.sysctl = { {
"net.ipv6.conf.all.forwarding" = "1"; boot.kernel.sysctl = {
"net.ipv6.conf.default.forwarding" = "1"; "net.ipv6.conf.all.forwarding" = "1";
"net.ipv4.ip_forward" = "1"; "net.ipv6.conf.default.forwarding" = "1";
}; "net.ipv4.ip_forward" = "1";
};
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.eth1 = { networking.interfaces.eth1 = {
ipv4.addresses = [ ipv4.addresses = [
{ {
address = ip4; address = ip4;
prefixLength = 24; prefixLength = 24;
} }
]; ];
ipv6.addresses = [ ipv6.addresses = [
{ {
address = ip6; address = ip6;
prefixLength = 64; prefixLength = 64;
} }
]; ];
}; };
} }
extraConfig extraConfig
] ];
}

View File

@ -1,3 +1,8 @@
{
lib,
kernelPackages ? null,
...
}:
let let
listenPort = 12345; listenPort = 12345;
socketNamespace = "foo"; socketNamespace = "foo";
@ -10,27 +15,18 @@ let
generatePrivateKeyFile = true; generatePrivateKeyFile = true;
}; };
}; };
in in
{
name = "wireguard-with-namespaces";
meta.maintainers = with lib.maintainers; [ asymmetric ];
import ../make-test-python.nix ( nodes = {
{ # interface should be created in the socketNamespace
pkgs, # and not moved from there
lib, peer0 =
kernelPackages ? null, { lib, pkgs, ... }:
... lib.attrsets.recursiveUpdate node {
}: boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
{
name = "wireguard-with-namespaces";
meta = with pkgs.lib.maintainers; {
maintainers = [ asymmetric ];
};
nodes = {
# interface should be created in the socketNamespace
# and not moved from there
peer0 = pkgs.lib.attrsets.recursiveUpdate node {
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; };
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
preSetup = '' preSetup = ''
ip netns add ${socketNamespace} ip netns add ${socketNamespace}
@ -38,10 +34,12 @@ import ../make-test-python.nix (
inherit socketNamespace; inherit socketNamespace;
}; };
}; };
# interface should be created in the init namespace # interface should be created in the init namespace
# and moved to the interfaceNamespace # and moved to the interfaceNamespace
peer1 = pkgs.lib.attrsets.recursiveUpdate node { peer1 =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
lib.attrsets.recursiveUpdate node {
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
preSetup = '' preSetup = ''
ip netns add ${interfaceNamespace} ip netns add ${interfaceNamespace}
@ -50,10 +48,12 @@ import ../make-test-python.nix (
inherit interfaceNamespace; inherit interfaceNamespace;
}; };
}; };
# interface should be created in the socketNamespace # interface should be created in the socketNamespace
# and moved to the interfaceNamespace # and moved to the interfaceNamespace
peer2 = pkgs.lib.attrsets.recursiveUpdate node { peer2 =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
lib.attrsets.recursiveUpdate node {
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
preSetup = '' preSetup = ''
ip netns add ${socketNamespace} ip netns add ${socketNamespace}
@ -62,10 +62,12 @@ import ../make-test-python.nix (
inherit socketNamespace interfaceNamespace; inherit socketNamespace interfaceNamespace;
}; };
}; };
# interface should be created in the socketNamespace # interface should be created in the socketNamespace
# and moved to the init namespace # and moved to the init namespace
peer3 = pkgs.lib.attrsets.recursiveUpdate node { peer3 =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
lib.attrsets.recursiveUpdate node {
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
preSetup = '' preSetup = ''
ip netns add ${socketNamespace} ip netns add ${socketNamespace}
@ -74,18 +76,17 @@ import ../make-test-python.nix (
interfaceNamespace = "init"; interfaceNamespace = "init";
}; };
}; };
}; };
testScript = '' testScript = ''
start_all() start_all()
for machine in peer0, peer1, peer2, peer3: for machine in peer0, peer1, peer2, peer3:
machine.wait_for_unit("wireguard-wg0.service") machine.wait_for_unit("wireguard-wg0.service")
peer0.succeed("ip -n ${socketNamespace} link show wg0") peer0.succeed("ip -n ${socketNamespace} link show wg0")
peer1.succeed("ip -n ${interfaceNamespace} link show wg0") peer1.succeed("ip -n ${interfaceNamespace} link show wg0")
peer2.succeed("ip -n ${interfaceNamespace} link show wg0") peer2.succeed("ip -n ${interfaceNamespace} link show wg0")
peer3.succeed("ip link show wg0") peer3.succeed("ip link show wg0")
''; '';
} }
)

View File

@ -1,26 +1,24 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, ...
kernelPackages ? null, }:
... let
}: wg-snakeoil-keys = import ./snakeoil-keys.nix;
let peer = import ./make-peer.nix;
wg-snakeoil-keys = import ./snakeoil-keys.nix; in
peer = (import ./make-peer.nix) { inherit lib; }; {
in name = "wireguard-networkd";
{ meta.maintainers = with lib.maintainers; [ majiir ];
name = "wireguard-networkd";
meta = with pkgs.lib.maintainers; {
maintainers = [ majiir ];
};
nodes = { nodes = {
peer0 = peer { peer0 = peer {
ip4 = "192.168.0.1"; ip4 = "192.168.0.1";
ip6 = "fd00::1"; ip6 = "fd00::1";
extraConfig = { extraConfig =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.firewall.allowedUDPPorts = [ 23542 ]; networking.firewall.allowedUDPPorts = [ 23542 ];
networking.wireguard.useNetworkd = true; networking.wireguard.useNetworkd = true;
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
@ -46,13 +44,15 @@ import ../make-test-python.nix (
}; };
}; };
}; };
}; };
peer1 = peer { peer1 = peer {
ip4 = "192.168.0.2"; ip4 = "192.168.0.2";
ip6 = "fd00::2"; ip6 = "fd00::2";
extraConfig = { extraConfig =
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; }; { lib, pkgs, ... }:
{
boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.wireguard.useNetworkd = true; networking.wireguard.useNetworkd = true;
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
ips = [ ips = [
@ -79,24 +79,23 @@ import ../make-test-python.nix (
}; };
}; };
}; };
};
}; };
};
testScript = '' testScript = ''
start_all() start_all()
peer0.systemctl("start network-online.target") peer0.systemctl("start network-online.target")
peer0.wait_for_unit("network-online.target") peer0.wait_for_unit("network-online.target")
peer1.systemctl("start network-online.target") peer1.systemctl("start network-online.target")
peer1.wait_for_unit("network-online.target") peer1.wait_for_unit("network-online.target")
peer1.succeed("ping -c5 fc00::1") peer1.succeed("ping -c5 fc00::1")
peer1.succeed("ping -c5 10.23.42.1") peer1.succeed("ping -c5 10.23.42.1")
with subtest("Has PSK set"): with subtest("Has PSK set"):
peer0.succeed("wg | grep 'preshared key'") peer0.succeed("wg | grep 'preshared key'")
peer1.succeed("wg | grep 'preshared key'") peer1.succeed("wg | grep 'preshared key'")
''; '';
} }
)

View File

@ -1,104 +1,101 @@
import ../make-test-python.nix ( {
{ lib,
pkgs, kernelPackages ? null,
lib, nftables ? false,
kernelPackages ? null, ...
nftables ? false, }:
... let
}: wg-snakeoil-keys = import ./snakeoil-keys.nix;
let peer = import ./make-peer.nix;
wg-snakeoil-keys = import ./snakeoil-keys.nix; commonConfig =
peer = import ./make-peer.nix { inherit lib; }; { pkgs, ... }:
commonConfig = { {
boot.kernelPackages = lib.mkIf (kernelPackages != null) kernelPackages; boot.kernelPackages = lib.mkIf (kernelPackages != null) (kernelPackages pkgs);
networking.nftables.enable = nftables; networking.nftables.enable = nftables;
# Make sure iptables doesn't work with nftables enabled # Make sure iptables doesn't work with nftables enabled
boot.blacklistedKernelModules = lib.mkIf nftables [ "nft_compat" ]; boot.blacklistedKernelModules = lib.mkIf nftables [ "nft_compat" ];
}; };
in in
{ {
name = "wg-quick"; name = "wg-quick";
nodes = { nodes = {
peer0 = peer { peer0 = peer {
ip4 = "192.168.0.1"; ip4 = "192.168.0.1";
ip6 = "fd00::1"; ip6 = "fd00::1";
extraConfig = lib.mkMerge [ extraConfig = {
commonConfig imports = [ commonConfig ];
{
networking.firewall.allowedUDPPorts = [ 23542 ];
networking.wg-quick.interfaces.wg0 = {
address = [
"10.23.42.1/32"
"fc00::1/128"
];
listenPort = 23542;
inherit (wg-snakeoil-keys.peer0) privateKey; networking.firewall.allowedUDPPorts = [ 23542 ];
networking.wg-quick.interfaces.wg0 = {
address = [
"10.23.42.1/32"
"fc00::1/128"
];
listenPort = 23542;
peers = lib.singleton { inherit (wg-snakeoil-keys.peer0) privateKey;
allowedIPs = [
"10.23.42.2/32"
"fc00::2/128"
];
inherit (wg-snakeoil-keys.peer1) publicKey; peers = lib.singleton {
}; allowedIPs = [
"10.23.42.2/32"
"fc00::2/128"
];
dns = [ inherit (wg-snakeoil-keys.peer1) publicKey;
"10.23.42.2" };
"fc00::2"
"wg0"
];
};
}
];
};
peer1 = peer { dns = [
ip4 = "192.168.0.2"; "10.23.42.2"
ip6 = "fd00::2"; "fc00::2"
extraConfig = lib.mkMerge [ "wg0"
commonConfig ];
{ };
networking.useNetworkd = true;
networking.wg-quick.interfaces.wg0 = {
address = [
"10.23.42.2/32"
"fc00::2/128"
];
inherit (wg-snakeoil-keys.peer1) privateKey;
peers = lib.singleton {
allowedIPs = [
"0.0.0.0/0"
"::/0"
];
endpoint = "192.168.0.1:23542";
persistentKeepalive = 25;
inherit (wg-snakeoil-keys.peer0) publicKey;
};
dns = [
"10.23.42.1"
"fc00::1"
"wg0"
];
};
}
];
}; };
}; };
testScript = '' peer1 = peer {
start_all() ip4 = "192.168.0.2";
ip6 = "fd00::2";
extraConfig = {
imports = [ commonConfig ];
peer0.wait_for_unit("wg-quick-wg0.service") networking.useNetworkd = true;
peer1.wait_for_unit("wg-quick-wg0.service") networking.wg-quick.interfaces.wg0 = {
address = [
"10.23.42.2/32"
"fc00::2/128"
];
inherit (wg-snakeoil-keys.peer1) privateKey;
peer1.succeed("ping -c5 fc00::1") peers = lib.singleton {
peer1.succeed("ping -c5 10.23.42.1") allowedIPs = [
''; "0.0.0.0/0"
} "::/0"
) ];
endpoint = "192.168.0.1:23542";
persistentKeepalive = 25;
inherit (wg-snakeoil-keys.peer0) publicKey;
};
dns = [
"10.23.42.1"
"fc00::1"
"wg0"
];
};
};
};
};
testScript = ''
start_all()
peer0.wait_for_unit("wg-quick-wg0.service")
peer1.wait_for_unit("wg-quick-wg0.service")
peer1.succeed("ping -c5 fc00::1")
peer1.succeed("ping -c5 10.23.42.1")
'';
}