From c8c32f5203826d56c48c96af727f3c53ebc61bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Yule=20B=C3=A4dorf?= Date: Mon, 12 Feb 2024 16:46:46 +0100 Subject: [PATCH] wireguard: add public network --- hosts/biolimo/networking.nix | 4 +- hosts/chocolatebar/networking.nix | 4 +- hosts/default.nix | 5 -- hosts/droppie/networking.nix | 24 ++++- hosts/frikandel/wireguard.nix | 23 +++-- hosts/pie/networking.nix | 4 +- hosts/stroopwafel/networking.nix | 18 +++- modules/default.nix | 3 +- modules/wireguard/default.nix | 11 +++ .../default.nix => wireguard/private.nix} | 31 ++++--- modules/wireguard/public.nix | 83 ++++++++++++++++++ secrets/secrets.nix | 3 + secrets/wg-public-droppie.age | 25 ++++++ secrets/wg-public-stroopwafel.age | Bin 0 -> 1227 bytes 14 files changed, 197 insertions(+), 41 deletions(-) create mode 100644 modules/wireguard/default.nix rename modules/{wireguard-client/default.nix => wireguard/private.nix} (65%) create mode 100644 modules/wireguard/public.nix create mode 100644 secrets/wg-public-droppie.age create mode 100644 secrets/wg-public-stroopwafel.age diff --git a/hosts/biolimo/networking.nix b/hosts/biolimo/networking.nix index 2d5c394..c59f720 100644 --- a/hosts/biolimo/networking.nix +++ b/hosts/biolimo/networking.nix @@ -10,11 +10,11 @@ age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-biolimo.age"; - pub-solar.wireguard-client = { + pub-solar.wireguard.private = { ownIPs = [ "10.13.12.6/32" "fd00:b12f:acab:1312:acab:6::/96" ]; - wireguardPrivateKeyFile = "/run/agenix/wg-private-key"; + privateKeyFile = config.age.secrets.wg-private-key.path; }; } diff --git a/hosts/chocolatebar/networking.nix b/hosts/chocolatebar/networking.nix index c2508b7..e791d2d 100644 --- a/hosts/chocolatebar/networking.nix +++ b/hosts/chocolatebar/networking.nix @@ -9,11 +9,11 @@ age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-chocolatebar.age"; - pub-solar.wireguard-client = { + pub-solar.wireguard.private = { ownIPs = [ "10.13.12.5/32" "fd00:b12f:acab:1312:acab:5::/96" ]; - wireguardPrivateKeyFile = "/run/agenix/wg-private-key"; + privateKeyFile = config.age.secrets.wg-private-key.path; }; } diff --git a/hosts/default.nix b/hosts/default.nix index e2b2e44..07d8cb1 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -18,7 +18,6 @@ self.nixosModules.office self.nixosModules.persistence self.nixosModules.printing - self.nixosModules.wireguard-client ]; }; @@ -36,7 +35,6 @@ self.nixosModules.nextcloud self.nixosModules.office self.nixosModules.printing - self.nixosModules.wireguard-client ]; }; @@ -56,7 +54,6 @@ self.nixosModules.office self.nixosModules.printing self.nixosModules.virtualisation - self.nixosModules.wireguard-client self.nixosModules.wireshark ]; }; @@ -68,7 +65,6 @@ self.nixosModules.base ./droppie self.nixosModules.yule - self.nixosModules.wireguard-client self.nixosModules.persistence ]; }; @@ -83,7 +79,6 @@ self.nixosModules.acme self.nixosModules.docker self.nixosModules.invoiceplane - self.nixosModules.wireguard-client ]; }; diff --git a/hosts/droppie/networking.nix b/hosts/droppie/networking.nix index 341eda7..5ece084 100644 --- a/hosts/droppie/networking.nix +++ b/hosts/droppie/networking.nix @@ -13,17 +13,33 @@ ipv6.addresses = [ { address = "2a02:908:5b1:e3c0:3::"; prefixLength = 64; } ]; }; - age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-droppie.age"; - # Allow pub.solar restic backups services.openssh.allowSFTP = true; services.openssh.openFirewall = true; - pub-solar.wireguard-client = { + age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-droppie.age"; + + pub-solar.wireguard.private = { ownIPs = [ "10.13.12.3/32" "fd00:b12f:acab:1312:acab:3::/96" ]; - wireguardPrivateKeyFile = "/run/agenix/wg-private-key"; + privateKeyFile = config.age.secrets.wg-private-key.path; + useDNS = false; + }; + + age.secrets.wg-public-key.file = "${flake.self}/secrets/wg-public-droppie.age"; + + pub-solar.wireguard.public = { + ownIPs = [ + "10.70.16.244/32" + "fc00:bbbb:bbbb:bb01::7:10f3/128" + ]; + privateKeyFile = config.age.secrets.wg-public-key.path; + useDNS = true; + peer = { + publicKey = "m9w2Fr0rcN6R1a9HYrGnUTU176rTZIq2pcsovPd9sms="; + endpoint = "[2a02:6ea0:d406:1::a18f]:3019"; + }; }; } diff --git a/hosts/frikandel/wireguard.nix b/hosts/frikandel/wireguard.nix index 0a88f3a..78c0f8b 100644 --- a/hosts/frikandel/wireguard.nix +++ b/hosts/frikandel/wireguard.nix @@ -5,29 +5,27 @@ lib, ... }: with lib; { - age.secrets.wg-private-key-server.file = "${flake.self}/secrets/wg-private-frikandel-server.age"; - boot.kernel.sysctl = { "net.ipv4.ip_forward" = 1; - "net.ipv6.conf.wg0.forwarding" = 1; - "net.ipv6.conf.wg0.accept_ra" = 1; - "net.ipv6.conf.wg0.accept_ra_pinfo" = 1; + "net.ipv6.conf.wg-private.forwarding" = 1; + "net.ipv6.conf.wg-private.accept_ra" = 1; + "net.ipv6.conf.wg-private.accept_ra_pinfo" = 1; }; networking.nat = { enable = true; enableIPv6 = true; externalInterface = "enp1s0"; - internalInterfaces = [ "wg0" ]; + internalInterfaces = [ "wg-private" ]; }; networking.firewall.allowedUDPPorts = [ 51899 ]; networking.firewall.extraForwardRules = [ - "iifname { != wg0 } reject" - "iifname wg0 accept" + "iifname { != wg-private } reject" + "iifname wg-private accept" ]; - systemd.services.wireguard-wg0 = { + systemd.services.wireguard-wg-private = { after = [ "network.target" "network-online.target" @@ -45,16 +43,18 @@ }; }; + age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-frikandel-server.age"; + # Enable WireGuard networking.wireguard.interfaces = { - wg0 = { + wg-private = { listenPort = 51899; mtu = 1300; ips = [ "10.13.12.7/32" "fd00:b12f:acab:1312:acab:7::/96" ]; - privateKeyFile = "/run/agenix/wg-private-key-server"; + privateKeyFile = config.age.secrets.wg-private-key.path; peers = [ { # pie publicKey = "hPTXEqQ2GYEywdPNdZBacwB9KKcoFZ/heClxnqmizyw="; @@ -62,7 +62,6 @@ "10.13.12.2/32" "fd00:b12f:acab:1312:acab:2::/96" ]; - endpoint = "pie-wg.b12f.io:51899"; persistentKeepalive = 25; } { # droppie diff --git a/hosts/pie/networking.nix b/hosts/pie/networking.nix index 9fed0ae..7d5e3d7 100644 --- a/hosts/pie/networking.nix +++ b/hosts/pie/networking.nix @@ -28,12 +28,12 @@ age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-pie.age"; - pub-solar.wireguard-client = { + pub-solar.wireguard.private = { useDNS = false; ownIPs = [ "10.13.12.2/32" "fd00:b12f:acab:1312:acab:2::/96" ]; - wireguardPrivateKeyFile = "/run/agenix/wg-private-key"; + privateKeyFile = config.age.secrets.wg-private-key.path; }; } diff --git a/hosts/stroopwafel/networking.nix b/hosts/stroopwafel/networking.nix index a7f67e2..e77512d 100644 --- a/hosts/stroopwafel/networking.nix +++ b/hosts/stroopwafel/networking.nix @@ -10,11 +10,25 @@ age.secrets.wg-private-key.file = "${flake.self}/secrets/wg-private-stroopwafel.age"; - pub-solar.wireguard-client = { + pub-solar.wireguard.private = { ownIPs = [ "10.13.12.8/32" "fd00:b12f:acab:1312:acab:8::/96" ]; - wireguardPrivateKeyFile = "/run/agenix/wg-private-key"; + privateKeyFile = config.age.secrets.wg-private-key.path; + }; + + age.secrets.wg-public-key.file = "${flake.self}/secrets/wg-public-stroopwafel.age"; + + pub-solar.wireguard.public = { + ownIPs = [ + "10.68.3.133/32" + "fc00:bbbb:bbbb:bb01::5:384/128" + ]; + privateKeyFile = config.age.secrets.wg-public-key.path; + peer = { + publicKey = "5FZW+fNA2iVBSY99HFl+KjGc9AFVNE+UFAedLNhu8lc="; + endpoint = "146.70.134.2:3565"; + }; }; } diff --git a/modules/default.nix b/modules/default.nix index a021d85..30ec665 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -25,7 +25,7 @@ terminal-life = import ./terminal-life; user = import ./user; virtualisation = import ./virtualisation; - wireguard-client = import ./wireguard-client; + wireguard = import ./wireguard; wireshark = import ./wireshark; base.imports = [ @@ -37,6 +37,7 @@ self.nixosModules.crypto self.nixosModules.nix self.nixosModules.terminal-life + self.nixosModules.wireguard self.nixosModules.root self.nixosModules.user diff --git a/modules/wireguard/default.nix b/modules/wireguard/default.nix new file mode 100644 index 0000000..d81502d --- /dev/null +++ b/modules/wireguard/default.nix @@ -0,0 +1,11 @@ +{ + lib, + config, + pkgs, + ... +}: { + imports = [ + ./private.nix + ./public.nix + ]; +} diff --git a/modules/wireguard-client/default.nix b/modules/wireguard/private.nix similarity index 65% rename from modules/wireguard-client/default.nix rename to modules/wireguard/private.nix index 7211c7d..82cd8e1 100644 --- a/modules/wireguard-client/default.nix +++ b/modules/wireguard/private.nix @@ -6,17 +6,18 @@ }: with lib; let psCfg = config.pub-solar; - cfg = config.pub-solar.wireguard-client; + cfg = config.pub-solar.wireguard.private; in { - options.pub-solar.wireguard-client = { + options.pub-solar.wireguard.private = { ownIPs = mkOption { description = '' Internal ips in wireguard used for cluster control-plane communication. ''; type = types.listOf types.str; + default = []; }; - wireguardPrivateKeyFile = mkOption { + privateKeyFile = mkOption { description = '' Location of private key file ''; @@ -40,10 +41,10 @@ in { }; }; - config = { + config = mkIf (builtins.length cfg.ownIPs != 0) { networking.firewall.allowedUDPPorts = [51899]; - systemd.services.wireguard-wg0 = { + systemd.services.wireguard-wg-private = { after = [ "network.target" "network-online.target" @@ -62,16 +63,24 @@ in { }; networking.wireguard.interfaces = { - wg0 = { + wg-private = { listenPort = 51899; mtu = 1300; ips = cfg.ownIPs; - privateKeyFile = cfg.wireguardPrivateKeyFile; - postSetup = lib.mkIf cfg.useDNS '' - printf "nameserver 10.13.12.7\nnameserver fd00:b12f:acab:1312:acab:7::" | resolvconf -a wg0 -m 0 -x - ''; + privateKeyFile = cfg.privateKeyFile; + postSetup = "" + + (if cfg.useDNS then '' + printf "nameserver 10.13.12.7\nnameserver fd00:b12f:acab:1312:acab:7::" | resolvconf -a wg-private -m 0 -x + '' else "") + + (if cfg.fullTunnel then '' + defaultRoute=$(${pkgs.iproute2}/bin/ip r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') + ipv4=$(${pkgs.dnsutils}/bin/dig +short A vpn.b12f.io) + ${pkgs.iproute2}/bin/ip route add $ipv4 via $defaultRoute + ipv6=$(${pkgs.dnsutils}/bin/dig +short AAAA vpn.b12f.io) + ${pkgs.iproute2}/bin/ip route add $ipv6 via $defaultRoute + '' else ""); postShutdown = lib.mkIf cfg.useDNS '' - resolvconf -d wg0 -f + resolvconf -d wg-private -f ''; peers = [ { diff --git a/modules/wireguard/public.nix b/modules/wireguard/public.nix new file mode 100644 index 0000000..8b8fd01 --- /dev/null +++ b/modules/wireguard/public.nix @@ -0,0 +1,83 @@ +{ + lib, + config, + pkgs, + ... +}: +with lib; let + psCfg = config.pub-solar; + cfg = config.pub-solar.wireguard.public; +in { + options.pub-solar.wireguard.public = { + ownIPs = mkOption { + description = "Internal ips in wireguard used for cluster control-plane communication."; + type = types.listOf types.str; + default = []; + }; + + privateKeyFile = mkOption { + description = "Location of private key file"; + type = types.path; + }; + + peer = { + publicKey = mkOption { + description = "Public key of the peer"; + type = types.str; + }; + endpoint = mkOption { + description = "Peer endpoint address"; + type = types.str; + }; + }; + + useDNS = mkOption { + description = "Whether to use the DNS of the interface as default"; + default = true; + type = types.bool; + }; + }; + + config = mkIf (length cfg.ownIPs != 0){ + networking.firewall.allowedUDPPorts = [51820]; + + systemd.services.wireguard-wg-public = mkIf (length config.pub-solar.wireguard.private.ownIPs != 0) { + after = [ "wireguard-wg-private.service" ]; + }; + + networking.wireguard.interfaces = { + wg-public = { + listenPort = 51820; + ips = cfg.ownIPs; + privateKeyFile = cfg.privateKeyFile; + postSetup = let + splitEndpoint = (strings.splitString ":" cfg.peer.endpoint); + joinIPV6 = p: ip: p + (if (stringLength ip > 0) then ":" else "") + ip; + isIPV4 = length splitEndpoint < 3; + endpointIP = (if isIPV4 + then elemAt splitEndpoint 0 + else lists.fold joinIPV6 "" ((lists.take ((length splitEndpoint) - 1)) splitEndpoint) + ); + in mkIf cfg.useDNS '' + printf "nameserver 10.64.0.1" | resolvconf -a wg-public -m 0 -x + defaultRoute=$(${pkgs.iproute2}/bin/ip r | ${pkgs.gnugrep}/bin/grep "default via" | head -n 1 | ${pkgs.gawk}/bin/awk '{ print $3 " " $4 " " $5 }') + ${pkgs.iproute2}/bin/ip ${if isIPV4 then "" else "-6"} route add ${endpointIP}${if isIPV4 then "" else "/128"} via $defaultRoute + ''; + postShutdown = mkIf cfg.useDNS '' + resolvconf -d wg-public -f + ''; + peers = [ + { + publicKey = cfg.peer.publicKey; + allowedIPs = [ + "0.0.0.0/0" + "::/0" + ]; + endpoint = cfg.peer.endpoint; + persistentKeepalive = 25; + } + ]; + }; + }; + }; +} diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 6742e4a..f4c9af1 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -80,6 +80,9 @@ in { "wg-private-droppie.age".publicKeys = droppieKeys ++ baseKeys; "wg-private-frikandel-server.age".publicKeys = frikandelKeys ++ baseKeys; + "wg-public-stroopwafel.age".publicKeys = stroopwafelKeys ++ baseKeys; + "wg-public-droppie.age".publicKeys = droppieKeys ++ baseKeys; + "invoiceplane-db-password.age".publicKeys = pieKeys ++ baseKeys; "invoiceplane-db-secrets.env.age".publicKeys = pieKeys ++ baseKeys; diff --git a/secrets/wg-public-droppie.age b/secrets/wg-public-droppie.age new file mode 100644 index 0000000..f3a9095 --- /dev/null +++ b/secrets/wg-public-droppie.age @@ -0,0 +1,25 @@ +age-encryption.org/v1 +-> ssh-ed25519 LVlqCg i1tTmBYjRhUWC9g3712yHyoOtJI+OC1zDLS0LTwB6BU +qQVM3zeTYDd6f6JNO970Xe9OUhaRN9oAU/6HM/NSp9o +-> ssh-rsa kFDS0A +h9B46QuyjABsEZf5GkFJ5JrAFKjyFrxhWEIK2X3wCVtG+8QiJ6Ij4OzXmMoMwSwk +QDF7yjmrbzyf+7331Hfh6FjSRUQ0TOK6lAjQJi4l8i7yB91d5NzcxKfyq5GiTrya +0l3A/FeRKwdKaHgyMONq+eFcCEiF7NPjmS/ALxO+fFJxrxUPGujgwSKH14JnN8P8 +RzIAWOqrL6odN2oRCDsCFEheKbFBTRYPf7VrPJHDlr11jM9O+XKEJigN80w+8Byt +U79pVgLEbvppxoXE2i5vrdhRmTIVN0qck9KtdEDSBMjc758nMMlTv6NdRkRXNnR5 +BQWVtqx/BMS/rV58jv3TTkBR/gl3aTaEnLDBW/GeZoBTBe9of3kAtJtGO7bZmkIP +SSuZKhZj5w4aq6kppiKEqf2iYYvb8Rx19OoBzCER25puE1XfshTlaorH06APAB+6 +lWrDIKQovSH4j+2SUVncoCiathyzCyKZB5hGs6bcBcAgUaAPFARPiuX5tYnXCiox +rMiZ3kP6ivTxcHDcZOrTXLiIeamaXVzv9sRREcn2SX76rgNlyi09kJL9E0W2XCom +O4Isl2vBSd0F6jv03VSQJnAPHNzB5i7/Fuer+WzD29BvQUqhoj/M2olBh7fluBo9 +Q4Sl6TM3r5Tng6UnnvjCcWDYy1W68epJDO8ijwtRj5U +-> piv-p256 zqq/iw ArboTsOuymJL0R4DjPFn6YQqC0Z4MWJuR8DhFvD+xdP+ +mmerIEHZNmBlX9Arb6BKxnDNZvgnjfn1b2+48/vbZH8 +-> piv-p256 vRzPNw Ava9AZcCeI0Y0FkB8mP54ywDYGcuInc9xZ2frmBL9aXV +6sLexmlUZC5iehf3qNj5y2N6Ss7WKqrqxiUYHa5jEJk +-> PaU0nX@"-grease +v+xWWiviKP1h5IEGV4KUXKsuMw50FVDzlikOrHx9zH89p8rJSTfsOnjiQQQoLADo + +--- 88jMG7EjNFpsb0AmpMPfaMdv3Jc/ctCR2GP5xpAYYjA +)D:\/IX^}i;Y>eԡ +tfֻl vzk'U QȧP \ No newline at end of file diff --git a/secrets/wg-public-stroopwafel.age b/secrets/wg-public-stroopwafel.age new file mode 100644 index 0000000000000000000000000000000000000000..d3a28f80feb2f67508d32af1d77107e94834216e GIT binary patch literal 1227 zcmY+?JL~IY0Dy6EP>JB;a@-0>5D7JJ-ZV+OsLi#PT$;3L(zuv3$(uIU=H4I(XLT1G z9CQ*CJRd+5oZJ+2b8-^DgYx&B!NE`PgNMgM;WW(8)xB&kMgC4vA)+I(>ARD+H=Ps{%II&GZ)b`?GD%^B%~gI%jjO zHs?iuxtk*wI|fw`{MtOR>Do^hMsZ$Gi3<6Y)eW;AhATUX_#iru*inAwJSJlAi%}tlw7^MZXGX8c z>!~eH3Y*kx!3I2S?R_+kI(^I>t%v#|01#`}S=zyBGcFo7%=-f{y;}6)XwU0DHc|t~ zqEG4hkts$}p=07S9=edYhbOB%qTASGt;8-H?#@Z%Y7Dn@%%1L4Gczt@bhRiw6J?w# zgN5WSXU9#{SA`P9JMo+W$=d4svfX20b1l|Xs#|0s%bEG$NemJLXqdl{q4vt zYV9np2^XGnZZruLM+ip@eO0l05$Hg`(|jjTTTn|1N*cs#u3*7rtp-Y3t%%MVs56Xd zW}a+%WiRyfT%|S;Oc{2WO%zxD!GE{HR{s`Py0bWD`^h}m|D7<(c{;fmd5txVA# zSB{My4lG@fF|Vp30n$U%v;u|fyXBF_|E$g&ciJTp6~hJI*N3DVGIiq@eZ#1mWIud(TLIzjS+8LMjLpCsKMb3!N!$g6d!rADo0 zv$h?qNEy=A(XucCJ^t{!H-2Y7dh+#Klxe;9^vOTJJ{n*C>9bEie)yvK`{8@;btLS^ um%jbxRqmCyfBOad;QgP!Y+rnV|Le!eQv!Yd$5#)3{*d*LyiZ;$gMR_Fw3ZkE literal 0 HcmV?d00001