]> Git — Sourcephile - sourcephile-nix.git/blob - hosts/losurdo/networking/wireguard/intranet.nix
wireguard: enable hole punching
[sourcephile-nix.git] / hosts / losurdo / networking / wireguard / intranet.nix
1 { pkgs, lib, config, hosts, ... }:
2 let
3 inherit (builtins) hasAttr removeAttrs;
4 inherit (config.security) gnupg;
5 inherit (config.boot) initrd;
6 iface = "wg-intra";
7 wg = config.networking.wireguard.interfaces.${iface};
8 relay =
9 hosts.mermet.extraArgs //
10 hosts.mermet.config.networking.wireguard.interfaces.${iface} //
11 lib.head (lib.filter (peer:
12 peer.endpoint != null &&
13 builtins.match "^\(.*\):[0-9]*$" peer.endpoint ==
14 [hosts.mermet.extraArgs.ipv4])
15 wg.peers);
16 in
17 {
18 imports = [
19 ../../../../networking/wireguard/wg-intra.nix
20 ];
21 config = {
22 networking.wireguard.interfaces.${iface} = {
23 privateKeyFile = gnupg.secrets."wireguard/${iface}/privateKey".path;
24 };
25 security.gnupg.secrets."wireguard/${iface}/privateKey" = {
26 /*
27 systemdConfig.serviceConfig = {
28 before = [ "wireguard-${iface}.service" ];
29 wantedBy = [ "wireguard-${iface}.service" ];
30 requiredBy = [ "wireguard-${iface}.service" ];
31 };
32 */
33 };
34 systemd.services."wireguard-${iface}" = {
35 after = [ gnupg.secrets."wireguard/${iface}/privateKey".service ];
36 requires = [ gnupg.secrets."wireguard/${iface}/privateKey".service ];
37 serviceConfig.Upholds = [ "upnpc-${toString wg.listenPort}.service" ];
38 };
39 networking.nftables.ruleset = ''
40 # Allow initiating connection to and from other peers
41 add rule inet filter fw2net udp sport ${toString wg.listenPort} counter accept comment "${iface} output to peers"
42 add rule inet filter net2fw udp dport ${toString wg.listenPort} counter accept comment "${iface} input from peers"
43
44 # Hook ${iface} into relevant chains
45 add rule inet filter input iifname "${iface}" jump intra2fw
46 add rule inet filter input iifname "${iface}" log level warn prefix "intra2fw: " counter drop
47 add rule inet filter output oifname "${iface}" jump fw2intra
48 add rule inet filter output oifname "${iface}" log level warn prefix "fw2intra: " counter drop
49
50 # ${iface} firewalling
51 add rule inet filter fw2intra counter accept
52 ${lib.concatMapStringsSep "\n" (ip: ''
53 add rule inet filter intra2fw ip saddr ${ip} counter accept comment "relay"
54 '') relay.ips}
55 add rule inet filter forward iifname "${iface}" jump fwd-intra
56 '';
57 # Apparently required to get NAT reflection.
58 services.upnpc.redirections = [
59 { description = "WireGuard"; externalPort = wg.listenPort; protocol = "UDP"; duration = 30 * 60;
60 service.requiredBy = [ "wireguard-${iface}.service" ];
61 service.before = [ "wireguard-${iface}.service" ];
62 }
63 ];
64 boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
65
66 # Open a wireguard tunnel to a relay
67 # in case the host is hosted behind a NAT and has no SSH port forwarding.
68 # This enables to send the disk password to the initrd, like that:
69 # ssh -J mermet.sourcephile.fr root@losurdo.wg -p 2222
70 boot.initrd.secrets."/root/initrd/${iface}.key" = "/root/initrd/${iface}.key";
71 /*
72 installer.ssh-nixos.script = ''
73 # Send the wireguard key of the initrd
74 gpg --decrypt '${gnupg.store}/wireguard/${iface}/privateKey.gpg' |
75 ssh '${config.installer.ssh-nixos.target}' \
76 install -D -m 400 -o root -g root /dev/stdin /root/initrd/${iface}.key
77 '';
78 */
79 boot.initrd.kernelModules = [ "wireguard" ];
80 boot.initrd.extraUtilsCommands = ''
81 #copy_bin_and_libs ${pkgs.wireguard-tools}/bin/wg
82 cp -fpdv ${pkgs.wireguard-tools}/bin/.wg-wrapped $out/bin/wg
83 '';
84 boot.initrd.network.postCommands = ''
85 ip link add dev ${iface} type wireguard
86 ${lib.concatMapStringsSep "\n" (ip: ''
87 ip address add ${ip} dev ${iface}
88 '') wg.ips}
89 wg set ${iface} private-key /root/initrd/${iface}.key \
90 listen-port ${toString wg.listenPort}
91 ip link set up dev ${iface}
92 wg set ${iface} peer ${relay.publicKey} \
93 endpoint ${relay.ipv4}:${toString relay.listenPort} \
94 allowed-ips ${relay.ipv4}/32 \
95 persistent-keepalive 5
96 ip route replace ${relay.ipv4}/32 dev ${iface} table main
97 '';
98 boot.initrd.postMountCommands = lib.mkIf initrd.network.flushBeforeStage2 ''
99 ip link del dev ${iface}
100 '';
101 };
102 }