From 6bf2642ffc1a90ba8764064918b36059ee28f691 Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Tue, 17 Jan 2023 16:05:11 +0800 Subject: [PATCH] hosts: add Wireguard services to related peers Among other things, Plover now ignores certain IP for fail2ban. This is for the VPN users that are placed in that range. --- hosts/ni/default.nix | 77 +++++++++++++++++++ .../files/wireguard/wireguard-public-key-ni | 1 + hosts/ni/secrets/secrets.yaml | 9 ++- hosts/plover/default.nix | 28 ++++++- .../wireguard/wireguard-public-key-phone | 1 + .../wireguard/wireguard-public-key-plover | 1 + hosts/plover/modules/hardware/networks.nix | 3 + hosts/plover/modules/services/wireguard.nix | 66 ++++++++++++++++ hosts/plover/secrets/secrets.yaml | 9 ++- 9 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 hosts/ni/files/wireguard/wireguard-public-key-ni create mode 100644 hosts/plover/files/wireguard/wireguard-public-key-phone create mode 100644 hosts/plover/files/wireguard/wireguard-public-key-plover create mode 100644 hosts/plover/modules/services/wireguard.nix diff --git a/hosts/ni/default.nix b/hosts/ni/default.nix index 4a1eea62..59fc29f6 100644 --- a/hosts/ni/default.nix +++ b/hosts/ni/default.nix @@ -1,5 +1,12 @@ { config, pkgs, lib, ... }: +let + network = import ../plover/modules/hardware/networks.nix; + inherit (network) publicIP wireguardIPv6BaseAddress wireguardPort; + + wireguardAllowedIPs = [ "0:0:0:0/0" "::/0" ]; + wireguardIFName = "wireguard0"; +in { imports = [ # Include the results of the hardware scan. @@ -44,6 +51,21 @@ getSecrets { ssh-key = { }; "ldap/password" = { }; + "wireguard/private-key" = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; + "wireguard/preshared-keys/plover" = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; + "wireguard/preshared-keys/phone" = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; }; sops.age.keyFile = "/var/lib/sops-nix/key.txt"; @@ -166,4 +188,59 @@ daemon.enable = true; server = "ldaps://ldap.foodogsquared.one/"; }; + + # 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 also setting up this configuration as a forwarder + systemd.network = { + netdevs."99-${wireguardIFName}" = { + netdevConfig = { + Name = wireguardIFName; + Kind = "wireguard"; + }; + + wireguardConfig = { + PrivateKeyFile = config.sops.secrets."ni/wireguard/private-key".path; + ListenPort = wireguardPort; + }; + + wireguardPeers = [ + # Plover server peer. This is the main "server" of the network. + { + wireguardPeerConfig = { + 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 = "${publicIP}:51820"; + }; + } + + # "Phone" peer. It is also expected to be anywhere on the global + # network so we're basically setting up our own peer as a traffic + # forwarder in case there's ever a reason to do connect from the phone + # to the server which is always available anyways. + { + wireguardPeerConfig = { + PublicKey = lib.readFile ../plover/files/wireguard/wireguard-public-key-phone; + PresharedKeyFile = config.sops.secrets."ni/wireguard/preshared-keys/phone".path; + AllowedIPs = lib.concatStringsSep "," wireguardAllowedIPs; + Endpoint = "${publicIP}:51820"; + }; + } + ]; + }; + + networks."99-${wireguardIFName}" = { + matchConfig.Name = wireguardIFName; + address = [ + "172.45.1.2/24" + "${wireguardIPv6BaseAddress}/48" + ]; + + # Otherwise, it will autostart every bootup when I need it only at few + # hours at a time. + linkConfig.Unmanaged = true; + }; + }; } diff --git a/hosts/ni/files/wireguard/wireguard-public-key-ni b/hosts/ni/files/wireguard/wireguard-public-key-ni new file mode 100644 index 00000000..8843b2d8 --- /dev/null +++ b/hosts/ni/files/wireguard/wireguard-public-key-ni @@ -0,0 +1 @@ +7N7bPsPU0Pn5DGPJxB1gMOiSKDw9s8I7y22YlGLDhCI= diff --git a/hosts/ni/secrets/secrets.yaml b/hosts/ni/secrets/secrets.yaml index cc27dd27..8af5f6f4 100644 --- a/hosts/ni/secrets/secrets.yaml +++ b/hosts/ni/secrets/secrets.yaml @@ -1,6 +1,11 @@ ssh-key: ENC[AES256_GCM,data:QKlQJCr4saNFHFBmbZBYnb0trwDaD+P925PRv0StcHjjT/eQVQijxGJRn4R73F0rChpB0YcnLsqn/mcgZzitzw0Q8MTREBNWYHITKl/VzTiOVhPdfD3hhlLMOVXRjtFwIk69iwheQeh9aGtRmin8MmbjZJHv7bczDuLeD5GtdL7G5Y8KPTF4BFOHFwLuUgL1vOG3wc+vWynFJ6W0t7umnBmcSHaIf2o8ZY2arGruHXsCJHVCtj9G5PS8SMBb1pGstiAXAdhd9rOhbHSYF0rqL841CkGnLL1hUrgNYTXNlEuss06exuYNEQq24GXRYdnMNizhNiWJxGiVC53masTWynryGdj0qRUvjqzzttLLer3w6wS4rA743vPvmlNnVrWauyoUtE9Z/EBLfh2gv2m+I6A8e7aAUyAqsI0e/zMbv0Mvm+Gv2veGHp1sX+PLF6MbQMDxMuax0ZNBgdidGqWAqBtKZ7buLQ5ckU43Js9/CaRB+qQ7VzTJ+amhtQPrlgILY+yQKheLribkSKRuw99p,iv:UaWomy2e/WE0jYAkblGoZDOEEPtQpaIiGawMh8q4Emk=,tag:kS1rafdiqkyMEbdPj+TdqA==,type:str] ldap: password: ENC[AES256_GCM,data:ukPDXnF21z4SKZSEtIlHbup9EPoU,iv:yAz5nlBnM9taU3JC+yCF+7ymIys/YvBVbgeXx7UvVAw=,tag:6yz0548WSaBoD9cwOxfQAw==,type:str] +wireguard: + private-key: ENC[AES256_GCM,data:PFq7LRaOYEuRY4/q4bB52tU/hTTBVU0YcSHLdo2c+SmvSC6ZeGF1Yt10NSU=,iv:cz/lBt40/fCrL95AyjnqqBZGdReorXXchFmwIvBRJfI=,tag:cg5AnpwKkST/Q9g0PyzYeg==,type:str] + preshared-keys: + plover: ENC[AES256_GCM,data:TT2Mhak2j6SQOsFRe2vAaqQ4U2Ul+LElw0ZssOqyZk+QlBG8XUggDJeNy7s=,iv:2917dEAHVMGuuq1h8TDuZk+6ZgmzhHGhb7xgcIQlsWw=,tag:ce7YM+aWd7q4v0uEpm1+Mw==,type:str] + phone: ENC[AES256_GCM,data:GiXlORbE/yrV9USLmoQFtsz0hYfc1qf2Qpz2nQ8D9KZiP/CRK7NMKF6fJJY=,iv:EQFNmi+i/VC4d/AaO5bBKjeVo5BX+ElTrbSCAS/E35U=,tag:N6Ftv/8WsDtE5je44gaDQg==,type:str] sops: kms: [] gcp_kms: [] @@ -16,8 +21,8 @@ sops: eEV0YWkyWHlIRmxhZjNYU3kzNlN3alkKDbMlrB1MkJ8145OcXyOhQLjLkKhrI/Vm ba7etZO7hqWwajWgEhFGNexI6QuQwgUU3zIOc//zPp8P7nNySfWOww== -----END AGE ENCRYPTED FILE----- - lastmodified: "2022-12-29T06:47:49Z" - mac: ENC[AES256_GCM,data:lo0nbFQNYeq3pq7RoVl3Qz33ZgAMsDjLvpMpGALIhdP40sVHhwAcTJNAKN/uqQHi3fhEQ5YG5+4IOuE7OToKmxI2sK4ffWiTils89nSH2CeQxYibHfKUYraCLEZhVH26Bgt0uaggG9BHjpGdA9Ua4jwFQReWPq9cpMF2oKkYSak=,iv:zZNt5CZQfwN2CdYiGNi0q+/QeGyTTo1Vd70CUwb3OTM=,tag:aSFcF1BPA7P0+W9Dce/NAg==,type:str] + lastmodified: "2023-01-17T09:10:27Z" + mac: ENC[AES256_GCM,data:NYVy8tPqsvBrqLmtSkuza6tDHeVz45yj3n6QJ2tz37QGdNK6KYXL+6kYVXaJ7JEZRoFkufYUFwD/ilu1MYbpFaInbkF/wkIRQ9hp1UHKGmaLIVcg0k5o+qCFENHbQqdfNQCb9ursHmt+W65yLjaWcQV6PUv2uHiR/fSrf4EFzrI=,iv:BT1GbF2YU79Ia4OmnJgGnsdKW2Jvny7OtXZnt1sR3Ms=,tag:ArlU4b0NmtlFU7Q4k/+zGg==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.3 diff --git a/hosts/plover/default.nix b/hosts/plover/default.nix index 357694bf..4bc3ad77 100644 --- a/hosts/plover/default.nix +++ b/hosts/plover/default.nix @@ -34,7 +34,7 @@ in ./modules/services/keycloak.nix ./modules/services/portunus.nix ./modules/services/vaultwarden.nix - ./modules/services/openvpn.nix + ./modules/services/wireguard.nix ]; boot.loader.grub.enable = true; @@ -56,6 +56,11 @@ in }; }; + services.fail2ban.ignoreIP = [ + "172.16.0.0/12" + "fc00::/7" + ]; + # TODO: Put the secrets to the respective service module. sops.secrets = let @@ -89,8 +94,28 @@ in "borg/ssh-key" = { }; "keycloak/db/password".owner = postgresUserGroup; "ldap/users/foodogsquared/password".owner = config.services.portunus.user; + "wireguard/private-key" = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; + "wireguard/preshared-keys/ni" = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; + "wireguard/preshared-keys/phone" = { + group = config.users.users.systemd-network.group; + reloadUnits = [ "systemd-networkd.service" ]; + mode = "0640"; + }; }; + services.resolved = { + enable = true; + dnssec = "true"; + }; + # All of the keys required to deploy the secrets. sops.age.keyFile = "/var/lib/sops-nix/key.txt"; @@ -104,6 +129,7 @@ in # DNS-related settings. We're settling by configuring the ACME setup with a # DNS provider. security.acme.defaults = { + email = "admin@foodogsquared.one"; dnsProvider = "porkbun"; credentialsFile = config.sops.secrets."plover/lego/env".path; }; diff --git a/hosts/plover/files/wireguard/wireguard-public-key-phone b/hosts/plover/files/wireguard/wireguard-public-key-phone new file mode 100644 index 00000000..4565039b --- /dev/null +++ b/hosts/plover/files/wireguard/wireguard-public-key-phone @@ -0,0 +1 @@ +MBqt2HPZFGRkIXjv5sIPhGjDytGCWC3K9uTHIa7Xtlc= diff --git a/hosts/plover/files/wireguard/wireguard-public-key-plover b/hosts/plover/files/wireguard/wireguard-public-key-plover new file mode 100644 index 00000000..1fb33599 --- /dev/null +++ b/hosts/plover/files/wireguard/wireguard-public-key-plover @@ -0,0 +1 @@ +zXYsuKGj0F/MJmTyHyTj3EIzMnrof7FzK/tx3w/xTEk= diff --git a/hosts/plover/modules/hardware/networks.nix b/hosts/plover/modules/hardware/networks.nix index e237fe3e..3d9f4fd5 100644 --- a/hosts/plover/modules/hardware/networks.nix +++ b/hosts/plover/modules/hardware/networks.nix @@ -7,4 +7,7 @@ privateIPNetworkRange = "172.16.0.0/32"; privateNetworkGatewayIP = "172.16.0.1/32"; + + wireguardIPv6BaseAddress = "fdee:b0de:54e6::"; + wireguardPort = 51820; } diff --git a/hosts/plover/modules/services/wireguard.nix b/hosts/plover/modules/services/wireguard.nix new file mode 100644 index 00000000..8ed201a4 --- /dev/null +++ b/hosts/plover/modules/services/wireguard.nix @@ -0,0 +1,66 @@ +{ config, lib, pkgs, ... }: + +# Take note this service is heavily based on the hardware networking setup of +# this host so better stay focused on the hardware configuration on this host. +let + acmeName = "wireguard.${config.networking.domain}"; + networks = import ../hardware/networks.nix; + inherit (networks) privateNetworkGatewayIP wireguardIPv6BaseAddress wireguardPort; + + wireguardIFName = "wireguard0"; + wireguardAddresses = [ + # Private IP address. + "172.45.1.1/32" + + # Private IPv6 address. Just arbitrarily chosen. + "${wireguardIPv6BaseAddress}/48" + ]; + wireguardAllowedIPs = [ "172.45.1.2/24" "${wireguardIPv6BaseAddress}/48" ]; +in +{ + environment.systemPackages = [ pkgs.wireguard-tools ]; + + networking.firewall.allowedUDPPorts = [ wireguardPort ]; + + systemd.network = { + netdevs."99-${wireguardIFName}" = { + netdevConfig = { + Name = wireguardIFName; + Kind = "wireguard"; + }; + + wireguardConfig = { + PrivateKeyFile = config.sops.secrets."plover/wireguard/private-key".path; + ListenPort = wireguardPort; + }; + + wireguardPeers = [ + # Desktop workstation. + { + wireguardPeerConfig = { + PublicKey = lib.readFile ../../../ni/files/wireguard/wireguard-public-key-ni; + PresharedKeyFile = config.sops.secrets."plover/wireguard/preshared-keys/ni".path; + AllowedIPs = lib.concatStringsSep "," wireguardAllowedIPs; + }; + } + + # Phone. + { + wireguardPeerConfig = { + PublicKey = lib.readFile ../../files/wireguard/wireguard-public-key-phone; + PresharedKeyFile = config.sops.secrets."plover/wireguard/preshared-keys/phone".path; + AllowedIPs = lib.concatStringsSep "," wireguardAllowedIPs; + }; + } + ]; + }; + + networks."99-${wireguardIFName}" = { + matchConfig.Name = wireguardIFName; + + address = wireguardAddresses; + + gateway = [ privateNetworkGatewayIP ]; + }; + }; +} diff --git a/hosts/plover/secrets/secrets.yaml b/hosts/plover/secrets/secrets.yaml index 6b581edf..37c92b68 100644 --- a/hosts/plover/secrets/secrets.yaml +++ b/hosts/plover/secrets/secrets.yaml @@ -31,6 +31,11 @@ ldap: users: foodogsquared: password: ENC[AES256_GCM,data:Nw12pHkmHc8Jbia8PjSu9wUc3t01Sxd73nuayg==,iv:STenM48MFhaq/64V69wRQG6BDQI8DzK7RcyRBctga9M=,tag:+em9U2/Rn4JUyDEJfnYRbw==,type:str] +wireguard: + private-key: ENC[AES256_GCM,data:6mrCsG7CSK7vTuG6kctevPPpIUKDPrHHfZJEPBfVq9AbuDkghT0jOy0nx+E=,iv:fEYzTOYWYIpfRIEBd0rxDc8uUCb1d1IyByguDXk9sVg=,tag:79miZddF6Sr4CwW/980HOw==,type:str] + preshared-keys: + ni: ENC[AES256_GCM,data:NAgNnVtPKCaaSagWCIet5pd5ZehymJPmhQShoO/ktqa1pl6MtzJsygbTktk=,iv:2/sOdNN6QX1Rou5xnq87t/m/kguPTthOXD8oXJfvM90=,tag:F/I2CYR9O1LAlLs/9LaXGg==,type:str] + phone: ENC[AES256_GCM,data:3wIv8mE7eYhvSjwcE9fwsUZhh2Svmzg+RFjJzvjvMyB9V3uvBYG8vmB751w=,iv:iSm4dXNVqFa52eq0Hhct1MGSoq4x7FFzWdjXHlkGTW8=,tag:Lr463ee5r/ZhEC78uYyzfQ==,type:str] sops: kms: [] gcp_kms: [] @@ -46,8 +51,8 @@ sops: ZCtNbnFqdzNkVlBtNjVCdE4yNHMrRjQKfFV4GaReO0UO81xsTB0EuN5ibVsafXJY miBgZAZWbJjSBcM4X+Fym/DlxHRoB1a6iFEFN9yg+Z9WI8PfjKnbsA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-01-12T07:19:30Z" - mac: ENC[AES256_GCM,data:MIWWaQ8c7HTbaB5zc0WSmfY1O0uJcUBXWois2w3yAqSyNhoNWkMyjGDDHWVENUPkB4As+oAdEsUYvd6WI1UXW6ozyLPJAW4ojJpIRYSJPtnlrJwlrnvuGx4bnMh8ApGp4RcJ+nZf5aWDmPj3yRL+8QAaB5gxyzXvyjoLUft1Y6s=,iv:R9/e6Y1NLgQvIaKi46uEX5GbNED1tckiCN9QAur/41c=,tag:WgDvcQ88MaUMWYQ1VYW5wg==,type:str] + lastmodified: "2023-01-17T09:10:51Z" + mac: ENC[AES256_GCM,data:wzxOoyd+Zq6Fna1GxCZ6Uha6rdW3xVRx3uJniyuJ6TpGCpMoCzv9O0F7JgYyK7je2GR1RomynECEGu84re46yK9AkwV9KKWXVAs8jaI9QeZ6usEbFdr7KmyLFZbO/OMP72OIV03wxJ7Hguz2snF5ONjjhbAfZ2n+xXTofFJqBZY=,iv:cMZdVJQ4Vpf1FB70De3Rf/iMqp2Uv1QARp6897bew1A=,tag:rRx+ufoCVqqOGWhURxo6aQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.7.3