From 5fbd39adfc2d94a5f0bc59c0b3c75590f0a3f066 Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Wed, 5 Jul 2023 11:40:40 +0800 Subject: [PATCH] hosts/ni: modularize Wireguard I also added a conditional configuration for systemd-networkd and a condition for the default which should be enabled when NetworkManager is enabled. Ideally this should be the default when systemd-networkd is not enabled but since they are the only network manager, we'll let it slide. --- hosts/ni/default.nix | 71 +---------------- hosts/ni/modules/wireguard.nix | 139 +++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 69 deletions(-) create mode 100644 hosts/ni/modules/wireguard.nix diff --git a/hosts/ni/default.nix b/hosts/ni/default.nix index 5c403196..0fa7f34d 100644 --- a/hosts/ni/default.nix +++ b/hosts/ni/default.nix @@ -1,24 +1,12 @@ { config, pkgs, lib, ... }: -let - network = import ../plover/modules/hardware/networks.nix; - inherit (builtins) toString; - inherit (network) - interfaces - wireguardPort - wireguardPeers; - - wireguardAllowedIPs = [ - "${interfaces.lan.IPv4.address}/16" - "${interfaces.lan.IPv6.address}/64" - ]; - wireguardIFName = "wireguard0"; -in { imports = [ # Include the results of the hardware scan. ./hardware-configuration.nix + ./modules/wireguard.nix + (lib.mapHomeManagerUser "foo-dogsquared" { extraGroups = [ "adbusers" @@ -66,9 +54,6 @@ in sops.secrets = lib.getSecrets ./secrets/secrets.yaml { "ni/ssh-key" = { }; - "ni/wireguard/private-key" = { }; - "ni/wireguard/preshared-keys/plover" = { }; - "ni/wireguard/preshared-keys/phone" = { }; }; sops.age.keyFile = "/var/lib/sops-nix/key.txt"; @@ -182,7 +167,6 @@ in nftables.enable = true; firewall = { enable = true; - allowedUDPPorts = [ wireguardPort ]; allowedTCPPorts = [ 22 # Secure Shells. ]; @@ -196,55 +180,4 @@ in ]; system.stateVersion = "23.05"; # Yes! I read the comment! - - # Setting up Wireguard as a VPN tunnel. Since this is a laptop that meant to - # be used anywhere, we're configuring Wireguard here as a "client". - # - # We're using wg-quick here as this host is using network managers that can - # differ between workflows (i.e., GNOME and KDE Plasma using NetworkManager, - # others might be using systemd-networkd). - networking.wg-quick.interfaces.wireguard0 = - let - domains = [ - "~plover.foodogsquared.one" - "~0.27.172.in-addr.arpa" - "~0.28.172.in-addr.arpa" - ]; - in - { - privateKeyFile = config.sops.secrets."ni/wireguard/private-key".path; - listenPort = wireguardPort; - dns = with interfaces.lan; [ IPv4.address IPv6.address ]; - postUp = - let - resolvectl = "${lib.getBin pkgs.systemd}/bin/resolvectl"; - in - '' - ${resolvectl} domain ${wireguardIFName} ${lib.concatStringsSep " " domains} - ${resolvectl} dnssec ${wireguardIFName} no - ''; - - address = with wireguardPeers.desktop; [ - "${IPv4}/32" - "${IPv6}/128" - ]; - - peers = [ - # The "server" peer. - { - publicKey = lib.removeSuffix "\n" (lib.readFile ../plover/files/wireguard/wireguard-public-key-plover); - presharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/plover".path; - allowedIPs = wireguardAllowedIPs; - endpoint = "${interfaces.wan.IPv4.address}:${toString wireguardPort}"; - persistentKeepalive = 25; - } - - # The "phone" peer. - { - publicKey = lib.removeSuffix "\n" (lib.readFile ../plover/files/wireguard/wireguard-public-key-phone); - presharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/phone".path; - allowedIPs = wireguardAllowedIPs; - } - ]; - }; } diff --git a/hosts/ni/modules/wireguard.nix b/hosts/ni/modules/wireguard.nix new file mode 100644 index 00000000..0dfef1c1 --- /dev/null +++ b/hosts/ni/modules/wireguard.nix @@ -0,0 +1,139 @@ +{ config, lib, pkgs, ... }: + +let + network = import ../../plover/modules/hardware/networks.nix; + inherit (builtins) toString; + inherit (network) + interfaces + wireguardPort + wireguardPeers; + + wireguardAllowedIPs = [ + "${interfaces.lan.IPv4.address}/16" + "${interfaces.lan.IPv6.address}/64" + ]; + wireguardIFName = "wireguard0"; + + internalDomains = [ + "~plover.foodogsquared.one" + "~0.27.172.in-addr.arpa" + "~0.28.172.in-addr.arpa" + ]; +in +{ + # Setting up Wireguard as a VPN tunnel. Since this is a laptop that meant to + # be used anywhere, we're configuring Wireguard here as a "client". + config = lib.mkMerge [ + { + networking.firewall.allowedUDPPorts = [ wireguardPort ]; + sops.secrets = lib.getSecrets ../secrets/secrets.yaml { + "ni/wireguard/private-key" = { }; + "ni/wireguard/preshared-keys/plover" = { }; + "ni/wireguard/preshared-keys/phone" = { }; + }; + } + + (lib.mkIf config.networking.networkmanager.enable { + networking.wg-quick.interfaces.wireguard0 = { + privateKeyFile = config.sops.secrets."ni/wireguard/private-key".path; + listenPort = wireguardPort; + dns = with interfaces.lan; [ IPv4.address IPv6.address ]; + postUp = + let + resolvectl = "${lib.getBin pkgs.systemd}/bin/resolvectl"; + in + '' + ${resolvectl} domain ${wireguardIFName} ${lib.concatStringsSep " " internalDomains} + ${resolvectl} dnssec ${wireguardIFName} no + ''; + + address = with wireguardPeers.desktop; [ + "${IPv4}/32" + "${IPv6}/128" + ]; + + # Take note wg-quick doesn't trim the files so we have to trim it ourselves. + peers = [ + # The "server" peer. + { + publicKey = lib.removeSuffix "\n" (lib.readFile ../../plover/files/wireguard/wireguard-public-key-plover); + presharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/plover".path; + allowedIPs = wireguardAllowedIPs; + endpoint = "${interfaces.wan.IPv4.address}:${toString wireguardPort}"; + persistentKeepalive = 25; + } + + # The "phone" peer. + { + publicKey = lib.removeSuffix "\n" (lib.readFile ../../plover/files/wireguard/wireguard-public-key-phone); + presharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/phone".path; + allowedIPs = wireguardAllowedIPs; + } + ]; + }; + }) + + (lib.mkIf config.systemd.network.enable { + # Just apply the appropriate permissions for systemd-networkd. + sops.secrets = let + systemdNetworkFileAttrs = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; + applySystemdAttr = secretPaths: lib.listToAttrs + (builtins.map (path: lib.nameValuePair path systemdNetworkFileAttrs)) + secretPaths; + in + applySystemdAttr [ + "ni/wireguard/private-key" + "ni/wireguard/preshared-keys/phone" + "ni/wireguard/preshared-keys/plover" + ]; + + systemd.network = { + netdevs."99-${wireguardIFName}" = { + netdevConfig = { + Name = wireguardIFName; + Kind = "wireguard"; + }; + + wireguardConfig = { + PrivateKeyFile = config.sops.secrets."ni/wireguard/private-key"; + ListenPort = wireguardPort; + }; + + wireguardPeers = [ + # The "server" peer. + { + PublicKey = lib.readFile ../../plover/files/wireguard/wireguard-public-key-plover; + PresharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/plover".path; + AllowedIPs = lib.concatStringsSep "," wireguardAllowedIPs; + Endpoint = "${interfaces.wan.IPv4.address}:${toString wireguardPort}"; + PersistentKeepalive = 25; + } + + # The "phone" peer. + { + PublicKey = lib.readFile ../../plover/files/wireguard/wireguard-public-key-phone; + PresharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/phone".path; + AllowedIPs = lib.concatStringsSep "," wireguardAllowedIPs; + } + ]; + }; + + networks."99-${wireguardIFName}" = { + matchConfig.Name = wireguardIFName; + + address = with wireguardPeers.desktop; [ + "${IPv4}/32" + "${IPv6}/128" + ]; + + dns = with interfaces.lan; [ IPv4.address IPv6.address ]; + domains = internalDomains; + }; + }; + }) + ]; +}