110 lines
3.9 KiB
Nix
110 lines
3.9 KiB
Nix
{ config, lib, pkgs, ... }: let
|
|
|
|
isValidPeer = p:
|
|
(p ? syscfg.net.wg.enable) &&
|
|
(p.syscfg.net.wg.enable == true) &&
|
|
(p.syscfg.net.wg.pubkey != config.syscfg.net.wg.pubkey);
|
|
activePeers = builtins.filter isValidPeer config.syscfg.peers;
|
|
|
|
isServer = config.syscfg.server ? wireguard && config.syscfg.server.wireguard;
|
|
vpnPeer = {
|
|
name = "vpn-helcel";
|
|
publicKey = "NFBJvYXZC+bd62jhrKnM7/pugidWhgR6+C5qIiUiq3Q=";
|
|
allowedIPs = [ "10.10.1.0/24" "fd10:10:10::0/64" ];
|
|
};
|
|
|
|
vpnTable = "51820";
|
|
vpnDown = pkgs.writeShellScript "wg0-vpn-down" ''
|
|
PATH=${lib.makeBinPath [ pkgs.iproute2 pkgs.wireguard-tools ]}
|
|
for f in -4 -6; do
|
|
ip $f rule del pref 31000 2>/dev/null
|
|
ip $f rule del pref 31001 2>/dev/null
|
|
ip $f route flush table ${vpnTable} 2>/dev/null
|
|
done
|
|
wg set wg0 fwmark off peer ${vpnPeer.publicKey} allowed-ips ${lib.concatStringsSep "," vpnPeer.allowedIPs} 2>/dev/null
|
|
true
|
|
'';
|
|
vpnUp = pkgs.writeShellScript "wg0-vpn-up" ''
|
|
set -e
|
|
PATH=${lib.makeBinPath [ pkgs.iproute2 pkgs.wireguard-tools pkgs.procps ]}
|
|
${vpnDown}
|
|
sysctl -q net.ipv4.conf.all.src_valid_mark=1
|
|
wg set wg0 fwmark ${vpnTable} peer ${vpnPeer.publicKey} allowed-ips 0.0.0.0/0,::/0
|
|
for f in -4 -6; do
|
|
ip $f route replace default dev wg0 table ${vpnTable}
|
|
ip $f rule add table main suppress_prefixlength 0 pref 31000
|
|
ip $f rule add not fwmark ${vpnTable} table ${vpnTable} pref 31001
|
|
done
|
|
'';
|
|
in
|
|
{
|
|
config = lib.mkIf (config.syscfg.net.wg.enable) {
|
|
networking.wireguard = {
|
|
enable = true;
|
|
interfaces = {
|
|
wg0 = {
|
|
ips = [ config.syscfg.net.wg.ip4 config.syscfg.net.wg.ip6 ];
|
|
privateKeyFile =
|
|
config.sops.secrets."${config.syscfg.hostname}_wg_priv".path;
|
|
listenPort = 1515;
|
|
mtu = 1340;
|
|
peers =
|
|
if isServer then
|
|
map (p: {
|
|
name = p.syscfg.hostname;
|
|
publicKey = p.syscfg.net.wg.pubkey;
|
|
allowedIPs = [ p.syscfg.net.wg.ip4 p.syscfg.net.wg.ip6 ];
|
|
}) activePeers
|
|
else
|
|
[(vpnPeer // {
|
|
endpoint = "vpn.helcel.net:1515";
|
|
persistentKeepalive = 30;
|
|
})];
|
|
};
|
|
};
|
|
};
|
|
|
|
# Let the desktop (eww network panel, scripts/net/wg-toggle) bring the
|
|
# tunnel up and down. eww runs as a user service outside the login
|
|
# session, where polkit cannot ask for a password, so wheel users may
|
|
# start/stop wireguard-* units without one.
|
|
security.polkit.extraConfig = ''
|
|
polkit.addRule(function(action, subject) {
|
|
if (action.id == "org.freedesktop.systemd1.manage-units" &&
|
|
subject.isInGroup("wheel") &&
|
|
/^wireguard-/.test(action.lookup("unit") || "")) {
|
|
return polkit.Result.YES;
|
|
}
|
|
});
|
|
'';
|
|
|
|
systemd.services."wireguard-wg0-peer-vpn-helcel" = {
|
|
after = [ "network-online.target" "nss-lookup.target" ];
|
|
bindsTo = [ "network-online.target" ];
|
|
wantedBy = lib.mkForce [ "network-online.target" ];
|
|
before = lib.mkForce [ ];
|
|
serviceConfig = {
|
|
Restart = "on-failure";
|
|
RestartSec = "10s"; # Wait 2 seconds before retrying the domain query
|
|
};
|
|
startLimitIntervalSec = 0;
|
|
};
|
|
|
|
systemd.services."wireguard-wg0-vpn" = lib.mkIf (!isServer) {
|
|
description = "WireGuard wg0 - route all traffic";
|
|
bindsTo = [ "wireguard-wg0.service" ];
|
|
wants = [ "wireguard-wg0-peer-vpn-helcel.service" ];
|
|
partOf = [ "wireguard-wg0-peer-vpn-helcel.service" ];
|
|
after = [ "wireguard-wg0.service" "wireguard-wg0-peer-vpn-helcel.service" ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
ExecStart = vpnUp;
|
|
ExecStop = vpnDown;
|
|
};
|
|
};
|
|
|
|
networking.firewall.checkReversePath = lib.mkIf (!isServer) "loose";
|
|
};
|
|
}
|