mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-10 03:23:29 +03:00
nixos/wireguard: add AmneziaWG support
Co-authored-by: azahi <azat@bahawi.net>
This commit is contained in:
parent
1ce7180d60
commit
0240773f49
3 changed files with 164 additions and 11 deletions
|
@ -15,6 +15,15 @@ let
|
|||
|
||||
options = {
|
||||
|
||||
type = mkOption {
|
||||
example = "amneziawg";
|
||||
default = "wireguard";
|
||||
type = types.enum ["wireguard" "amneziawg"];
|
||||
description = ''
|
||||
The type of the interface. Currently only "wireguard" and "amneziawg" are supported.
|
||||
'';
|
||||
};
|
||||
|
||||
ips = mkOption {
|
||||
example = [ "192.168.2.1/24" ];
|
||||
default = [];
|
||||
|
@ -204,6 +213,22 @@ let
|
|||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = with types; attrsOf (oneOf [ str int ]);
|
||||
default = { };
|
||||
example = {
|
||||
Jc = 5;
|
||||
Jmin = 10;
|
||||
Jmax = 42;
|
||||
S1 = 60;
|
||||
S2 = 90;
|
||||
H4 = 12345;
|
||||
};
|
||||
description = ''
|
||||
Extra options to append to the interface section. Can be used to define AmneziaWG-specific options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -342,6 +367,16 @@ let
|
|||
|
||||
};
|
||||
|
||||
wgBins = {
|
||||
wireguard = "wg";
|
||||
amneziawg = "awg";
|
||||
};
|
||||
|
||||
wgPackages = {
|
||||
wireguard = pkgs.wireguard-tools;
|
||||
amneziawg = pkgs.amneziawg-tools;
|
||||
};
|
||||
|
||||
generateKeyServiceUnit = name: values:
|
||||
assert values.generatePrivateKeyFile;
|
||||
nameValuePair "wireguard-${name}-key"
|
||||
|
@ -350,7 +385,7 @@ let
|
|||
wantedBy = [ "wireguard-${name}.service" ];
|
||||
requiredBy = [ "wireguard-${name}.service" ];
|
||||
before = [ "wireguard-${name}.service" ];
|
||||
path = with pkgs; [ wireguard-tools ];
|
||||
path = [ wgPackages.${values.type} ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
@ -366,7 +401,7 @@ let
|
|||
|
||||
if [ ! -f "${values.privateKeyFile}" ]; then
|
||||
# Write private key file with atomically-correct permissions.
|
||||
(set -e; umask 077; wg genkey > "${values.privateKeyFile}")
|
||||
(set -e; umask 077; ${wgBins.${values.type}} genkey > "${values.privateKeyFile}")
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
@ -391,7 +426,7 @@ let
|
|||
src = interfaceCfg.socketNamespace;
|
||||
dst = interfaceCfg.interfaceNamespace;
|
||||
ip = nsWrap "ip" src dst;
|
||||
wg = nsWrap "wg" src dst;
|
||||
wg = nsWrap wgBins.${interfaceCfg.type} src dst;
|
||||
dynamicEndpointRefreshSeconds = dynamicRefreshSeconds interfaceCfg peer;
|
||||
dynamicRefreshEnabled = dynamicEndpointRefreshSeconds != 0;
|
||||
# We generate a different name (a `-refresh` suffix) when `dynamicEndpointRefreshSeconds`
|
||||
|
@ -408,7 +443,7 @@ let
|
|||
wantedBy = [ "wireguard-${interfaceName}.service" ];
|
||||
environment.DEVICE = interfaceName;
|
||||
environment.WG_ENDPOINT_RESOLUTION_RETRIES = "infinity";
|
||||
path = with pkgs; [ iproute2 wireguard-tools ];
|
||||
path = with pkgs; [ iproute2 wgPackages.${interfaceCfg.type} ];
|
||||
|
||||
serviceConfig =
|
||||
if !dynamicRefreshEnabled
|
||||
|
@ -497,7 +532,7 @@ let
|
|||
dst = values.interfaceNamespace;
|
||||
ipPreMove = nsWrap "ip" src null;
|
||||
ipPostMove = nsWrap "ip" src dst;
|
||||
wg = nsWrap "wg" src dst;
|
||||
wg = nsWrap wgBins.${values.type} src dst;
|
||||
ns = if dst == "init" then "1" else dst;
|
||||
|
||||
in
|
||||
|
@ -508,7 +543,7 @@ let
|
|||
wants = [ "network.target" ];
|
||||
before = [ "network.target" ];
|
||||
environment.DEVICE = name;
|
||||
path = with pkgs; [ kmod iproute2 wireguard-tools ];
|
||||
path = with pkgs; [ kmod iproute2 wgPackages.${values.type} ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
@ -516,10 +551,10 @@ let
|
|||
};
|
||||
|
||||
script = concatStringsSep "\n" (
|
||||
optional (!config.boot.isContainer) "modprobe wireguard || true"
|
||||
optional (!config.boot.isContainer) "modprobe ${values.type} || true"
|
||||
++ [
|
||||
values.preSetup
|
||||
''${ipPreMove} link add dev "${name}" type wireguard''
|
||||
''${ipPreMove} link add dev "${name}" type ${values.type}''
|
||||
]
|
||||
++ optional (values.interfaceNamespace != null && values.interfaceNamespace != values.socketNamespace) ''${ipPreMove} link set "${name}" netns "${ns}"''
|
||||
++ optional (values.mtu != null) ''${ipPostMove} link set "${name}" mtu ${toString values.mtu}''
|
||||
|
@ -531,6 +566,7 @@ let
|
|||
[ ''${wg} set "${name}" private-key "${privKey}"'' ]
|
||||
++ optional (values.listenPort != null) ''listen-port "${toString values.listenPort}"''
|
||||
++ optional (values.fwMark != null) ''fwmark "${values.fwMark}"''
|
||||
++ mapAttrsToList (k: v: ''${toLower k} "${toString v}"'') values.extraOptions
|
||||
))
|
||||
''${ipPostMove} link set up dev "${name}"''
|
||||
values.postSetup
|
||||
|
@ -550,6 +586,9 @@ let
|
|||
ns = last nsList;
|
||||
in
|
||||
if (length nsList > 0 && ns != "init") then ''ip netns exec "${ns}" "${cmd}"'' else cmd;
|
||||
|
||||
usingWg = any (x: x.type == "wireguard") (attrValues cfg.interfaces);
|
||||
usingAwg = any (x: x.type == "amneziawg") (attrValues cfg.interfaces);
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -624,9 +663,11 @@ in
|
|||
message = "networking.wireguard.interfaces.${interfaceName} peer «${peer.publicKey}» has both presharedKey and presharedKeyFile set, but only one can be used.";
|
||||
}) all_peers;
|
||||
|
||||
boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard;
|
||||
boot.kernelModules = [ "wireguard" ];
|
||||
environment.systemPackages = [ pkgs.wireguard-tools ];
|
||||
boot.extraModulePackages =
|
||||
optional (usingWg && (versionOlder kernel.kernel.version "5.6")) kernel.wireguard
|
||||
++ optional usingAwg kernel.amneziawg;
|
||||
boot.kernelModules = optional usingWg "wireguard" ++ optional usingAwg "amneziawg";
|
||||
environment.systemPackages = optional usingWg pkgs.wireguard-tools ++ optional usingAwg pkgs.amneziawg-tools;
|
||||
|
||||
systemd.services = mkIf (!cfg.useNetworkd) (
|
||||
(mapAttrs' generateInterfaceUnit cfg.interfaces)
|
||||
|
|
111
nixos/tests/wireguard/amneziawg.nix
Normal file
111
nixos/tests/wireguard/amneziawg.nix
Normal file
|
@ -0,0 +1,111 @@
|
|||
import ../make-test-python.nix (
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
kernelPackages ? null,
|
||||
...
|
||||
}:
|
||||
let
|
||||
wg-snakeoil-keys = import ./snakeoil-keys.nix;
|
||||
peer = (import ./make-peer.nix) { inherit lib; };
|
||||
extraOptions = {
|
||||
Jc = 5;
|
||||
Jmin = 10;
|
||||
Jmax = 42;
|
||||
S1 = 60;
|
||||
S2 = 90;
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "amneziawg";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
averyanalex
|
||||
azahi
|
||||
];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
peer0 = peer {
|
||||
ip4 = "192.168.0.1";
|
||||
ip6 = "fd00::1";
|
||||
extraConfig = {
|
||||
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; };
|
||||
networking.firewall.allowedUDPPorts = [ 23542 ];
|
||||
networking.wireguard.interfaces.wg0 = {
|
||||
type = "amneziawg";
|
||||
ips = [
|
||||
"10.23.42.1/32"
|
||||
"fc00::1/128"
|
||||
];
|
||||
listenPort = 23542;
|
||||
|
||||
inherit (wg-snakeoil-keys.peer0) privateKey;
|
||||
|
||||
peers = lib.singleton {
|
||||
allowedIPs = [
|
||||
"10.23.42.2/32"
|
||||
"fc00::2/128"
|
||||
];
|
||||
|
||||
inherit (wg-snakeoil-keys.peer1) publicKey;
|
||||
};
|
||||
|
||||
inherit extraOptions;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
peer1 = peer {
|
||||
ip4 = "192.168.0.2";
|
||||
ip6 = "fd00::2";
|
||||
extraConfig = {
|
||||
boot = lib.mkIf (kernelPackages != null) { inherit kernelPackages; };
|
||||
networking.wireguard.interfaces.wg0 = {
|
||||
type = "amneziawg";
|
||||
ips = [
|
||||
"10.23.42.2/32"
|
||||
"fc00::2/128"
|
||||
];
|
||||
listenPort = 23542;
|
||||
allowedIPsAsRoutes = false;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
postSetup =
|
||||
let
|
||||
inherit (pkgs) iproute2;
|
||||
in
|
||||
''
|
||||
${iproute2}/bin/ip route replace 10.23.42.1/32 dev wg0
|
||||
${iproute2}/bin/ip route replace fc00::1/128 dev wg0
|
||||
'';
|
||||
|
||||
inherit extraOptions;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
peer0.wait_for_unit("wireguard-wg0.service")
|
||||
peer1.wait_for_unit("wireguard-wg0.service")
|
||||
|
||||
peer1.succeed("ping -c5 fc00::1")
|
||||
peer1.succeed("ping -c5 10.23.42.1")
|
||||
'';
|
||||
}
|
||||
)
|
|
@ -10,6 +10,7 @@ with pkgs.lib;
|
|||
let
|
||||
tests = let callTest = p: args: import p ({ inherit system pkgs; } // args); in {
|
||||
basic = callTest ./basic.nix;
|
||||
amneziawg = callTest ./amneziawg.nix;
|
||||
namespaces = callTest ./namespaces.nix;
|
||||
networkd = callTest ./networkd.nix;
|
||||
wg-quick = callTest ./wg-quick.nix;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue