diff options
| author | Mel <mel@rnrd.eu> | 2026-05-01 18:40:37 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2026-05-01 18:40:37 +0200 |
| commit | a4ab740d07706d86503b84d36addcbbbf7a4944b (patch) | |
| tree | 24c52a29b9a3182149db37e332bee3af9b9f6014 /modules | |
| parent | c9f2260dc0414d451d551f8ffdf1f573e7be41ff (diff) | |
| download | network-a4ab740d07706d86503b84d36addcbbbf7a4944b.tar.zst network-a4ab740d07706d86503b84d36addcbbbf7a4944b.zip | |
Re-add simple VPN and simplify module with shared users with tunnel
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/foundation/default.nix | 1 | ||||
| -rw-r--r-- | modules/foundation/vpn.nix | 90 | ||||
| -rw-r--r-- | modules/tunnel/definition.nix | 31 | ||||
| -rw-r--r-- | modules/tunnel/ingress.nix | 6 |
4 files changed, 95 insertions, 33 deletions
diff --git a/modules/foundation/default.nix b/modules/foundation/default.nix index 3905eb8..fa84750 100644 --- a/modules/foundation/default.nix +++ b/modules/foundation/default.nix @@ -6,5 +6,6 @@ ./services ./monitoring ./www + ./vpn.nix ]; } diff --git a/modules/foundation/vpn.nix b/modules/foundation/vpn.nix new file mode 100644 index 0000000..1a7524d --- /dev/null +++ b/modules/foundation/vpn.nix @@ -0,0 +1,90 @@ +{ + config, + lib, + ... +}: + +let + inherit (lib) + mkEnableOption + mkOption + types + mkIf + attrValues + replaceString + ; + + cfg = config.foundation.vpn; + + inherit (import ../../assets/vpn.nix) users; + + interface = "vpn0"; + port = 51820; + + # while the tunnel uses the lower subnets for the paths, + # the vpn always uses subnet number 10. + subnetIndex = 10; + + addressFromTemplate = + template: prefix: "${replaceString "X" (toString subnetIndex) template}/${toString prefix}"; +in +{ + options.foundation.vpn = { + enable = mkEnableOption "WireGuard VPN server"; + + externalInterface = mkOption { + type = types.str; + description = "External network interface"; + }; + }; + + config = mkIf cfg.enable { + age.secrets.wg-private-key = { + file = ../../secrets/wg-private-key.age; + owner = "systemd-network"; + }; + + networking.firewall.allowedUDPPorts = [ port ]; + + systemd.network = { + netdevs."30-${interface}" = { + netdevConfig = { + Kind = "wireguard"; + Name = interface; + }; + wireguardConfig = { + PrivateKeyFile = config.age.secrets.wg-private-key.path; + ListenPort = port; + }; + wireguardPeers = map (user: { + PublicKey = user.key; + AllowedIPs = [ (addressFromTemplate user.ip 32) ]; + }) (attrValues users); + }; + + networks."30-${interface}" = { + name = interface; + address = [ (addressFromTemplate "10.123.X.1" 24) ]; + linkConfig = { + RequiredForOnline = "no"; + }; + }; + }; + + networking.nftables.tables.vpn-nat = { + family = "ip"; + content = '' + chain postrouting { + type nat hook postrouting priority srcnat; policy accept; + iifname "${interface}" oifname "${cfg.externalInterface}" masquerade + } + + chain forward { + type filter hook forward priority 0; policy accept; + iifname "${interface}" oifname "${cfg.externalInterface}" accept + iifname "${cfg.externalInterface}" oifname "${interface}" ct state established,related accept + } + ''; + }; + }; +} diff --git a/modules/tunnel/definition.nix b/modules/tunnel/definition.nix index 74ae268..82534bf 100644 --- a/modules/tunnel/definition.nix +++ b/modules/tunnel/definition.nix @@ -36,40 +36,11 @@ } ]; - # there are our users who are allowed to connect to any of our "paths". - # their ip is always a template, with 'X' representing the path index. - users = { - mel = { - key = "vnZoHXapCLLUhZ8A8R5W0iJ8LpWVLve29z41kkoT0BU="; - ip = "10.123.X.101"; - }; - - andrei = { - key = "qqU4uYImLfUohIwl4KBshPtTINFcs0JVALjbmwpfxRg="; - ip = "10.123.X.102"; - }; - - sergo = { - key = "qbZGMNIDZFCJC6SHtlyNIlIdGWHELceXClJCcagrj2Y="; - ip = "10.123.X.103"; - }; - - fedor = { - key = "tEO9r8+jTpu8TBRmZ+/v087IgD/QfmofLUKs249i/F0="; - ip = "10.123.X.104"; - }; - }; + inherit (import ../../assets/vpn.nix) users; # we use a website as a "mask" for vless/reality, which will tell our peers # to pretend as if they're a user and a well-known website communicating with # each other, even though they know that the keys don't actually match up, # it's not possible to see that on the outside. mask = "microsoft.com"; - - # we don't actually need this to configure the tunnel, but this is - # the public key of the ingress interface. - # when creating wireguard vpn configurations for the users, this - # is the public key of the server peer at `tunnel.rnrd.eu`. - # the matching private key of the pair is the secret `tunnel/ingress-key`. - ingress.public = "s5yyPCJiN0uqW0jzKIbYCF7I9TthymiRzpNt466XeWk="; } diff --git a/modules/tunnel/ingress.nix b/modules/tunnel/ingress.nix index 1ea1613..f609f3d 100644 --- a/modules/tunnel/ingress.nix +++ b/modules/tunnel/ingress.nix @@ -38,8 +38,8 @@ in checkReversePath = "loose"; }; - age.secrets.ingress-key = { - file = ../../secrets/tunnel/ingress-key.age; + age.secrets.wg-private-key = { + file = ../../secrets/wg-private-key.age; owner = "systemd-network"; }; @@ -52,7 +52,7 @@ in Name = ingressName index; }; wireguardConfig = { - PrivateKeyFile = config.age.secrets.ingress-key.path; + PrivateKeyFile = config.age.secrets.wg-private-key.path; ListenPort = path.port; }; wireguardPeers = map (user: { |
