{ config, pkgs, lib, ... }: let inherit (pkgs) iptables; inherit (lib) mkIf mkEnableOption mkOption assertMsg types ; cfg = config.foundation.wireguard; # TODO: we might want to configure these through options? wireguardPort = 51820; wireguardIPv4 = number: subnet: "10.123.10.${number}/${subnet}"; wireguardIPv6 = number: subnet: "fd0f:123::${number}/${subnet}"; wireguardInterface = "wg0"; in { options.foundation.wireguard = let peerSubmodule = with types; submodule { options = { ip = mkOption { type = int; }; key = mkOption { type = str; }; }; }; in { server = { enable = mkEnableOption "wireguard vpn server"; externalInterface = mkOption { type = types.str; default = "eth0"; }; peers = mkOption { type = types.attrsOf peerSubmodule; default = { }; }; }; }; config = mkIf cfg.server.enable { age.secrets.wireguard-private-key = { file = ../../secrets/wireguard-private-key.age; }; # enable nat, to rename internal wireguard ips to external ip (w/ iptables) networking = { nat = { enable = true; internalInterfaces = [ wireguardInterface ]; inherit (cfg.server) externalInterface; }; firewall = { allowedUDPPorts = [ wireguardPort ]; }; }; # enable kernel support for ipv6 forwarding boot.kernel.sysctl = { "net.ipv6.conf.all.forwarding" = 1; "net.ipv6.conf.default.forwarding" = 1; }; networking.wireguard.interfaces.${wireguardInterface} = let inherit (cfg.server) externalInterface; peerIPs = peerNumber: [ (wireguardIPv4 peerNumber "32") (wireguardIPv6 peerNumber "128") ]; mkPeer = p: assert assertMsg (p.ip > 1) "ip has to be larger that 1"; { allowedIPs = peerIPs (toString p.ip); publicKey = p.key; }; peers = map mkPeer (builtins.attrValues cfg.server.peers); in { inherit peers; # ip address of server + subnet of network ips = [ (wireguardIPv4 "1" "24") (wireguardIPv6 "1" "112") ]; listenPort = wireguardPort; # route wireguard traffic to the internet # also requires clients to have dns set. (i think) # to avoid, maybe? use wg-quick + dnsmasq? postSetup = '' ${iptables}/bin/iptables -t nat -A POSTROUTING -s ${wireguardIPv4 "0" "24"} -o ${externalInterface} -j MASQUERADE ${iptables}/bin/ip6tables -t nat -A POSTROUTING -s ${wireguardIPv6 "0" "112"} -o ${externalInterface} -j MASQUERADE ''; postShutdown = '' ${iptables}/bin/iptables -t nat -D POSTROUTING -s ${wireguardIPv4 "0" "24"} -o ${externalInterface} -j MASQUERADE ${iptables}/bin/ip6tables -t nat -D POSTROUTING -s ${wireguardIPv6 "0" "112"} -o ${externalInterface} -j MASQUERADE ''; privateKeyFile = config.age.secrets.wireguard-private-key.path; }; }; }