summaryrefslogtreecommitdiff
path: root/modules/wg/module.nix
blob: c27f32519ff5366fad251f9c4323a7731e06eb03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{
  lib,
  config,
  self,
  registry,
  ...
}:
{

  config =
    let
      currenthost = config.networking.hostName;
      wg = config.oxalab.wg;

      # get all the networks we participate in
      networks = builtins.filter (net: builtins.hasAttr "${currenthost}" net.hosts) wg;

      # create wg networks
      network-attrset = map (net: {
        name = "30-wg-${net.networkName}";
        value = {
          matchConfig.Name = "wg-${net.networkName}";
          networkConfig =
            {
              Address = net.hosts.${currenthost}.address;
              IPv6AcceptRA = false; # for now static IPv6
            }
            // (
              if net.hosts.${currenthost}.endpoint.enable then
                {
                  IPv4Forwarding = true;
                  IPv6Forwarding = true;
                }
              else
                { }
            );
        };
      }) networks;

      systemd-networks = builtins.listToAttrs network-attrset;

      # get all the networks we client in
      net-client = builtins.filter (net: !net.hosts.${currenthost}.endpoint.enable) networks;
      # get all the networks we are endpoint of
      net-endpoint = builtins.filter (net: net.hosts.${currenthost}.endpoint.enable) networks;

      # wg netdevs
      # client
      netdev-client-list = map (net: {
        name = "30-wg-${net.networkName}";
        value = {
          netdevConfig = {
            Kind = "wireguard";
            Name = "wg-${net.networkName}";
          };
          wireguardConfig.PrivateKeyFile = net.hosts.${currenthost}.privateKeyFile;
          # for client this is only endpoint for now
          wireguardPeers =
            let
              endpoint = lib.attrsets.filterAttrs (_k: v: v.endpoint.enable) net.hosts;
              wg-peers-attrs = lib.attrsets.mapAttrs (_k: v: {
                PersistentKeepalive = 29;
                PublicKey = v.publicKey;
                Endpoint = "${v.endpoint.endpoint}:${toString v.endpoint.port}";
                AllowedIPs = net.CIDRs;
              }) endpoint;
              wg-peers = lib.attrsets.attrValues wg-peers-attrs;
            in
            wg-peers;
        };
      }) net-client;
      netdev-client = builtins.listToAttrs netdev-client-list;

      maskip = (
        net: hostattrs:
        if hostattrs.endpoint.enable then
          hostattrs.address
        else
          map (baseaddr: if lib.strings.hasInfix "." baseaddr then "${baseaddr}/32" else "${baseaddr}/128") (
            map (addr: builtins.elemAt (lib.strings.splitString "/" addr) 0) hostattrs.address
          )
      );
      # endpoint
      # TODO: this requires bit more logic for allowedIPs if we have more then
      # 2 endpoints e.g. for routing client -> endpoint1 -> endpoint2 ->
      # client2
      netdev-endpoint-list = map (net: {
        name = "30-wg-${net.networkName}";
        value = {
          netdevConfig = {
            Kind = "wireguard";
            Name = "wg-${net.networkName}";
          };
          wireguardConfig.PrivateKeyFile = net.hosts.${currenthost}.privateKeyFile;
          wireguardConfig.ListenPort = net.hosts.${currenthost}.endpoint.port;
          wireguardPeers =
            let
              peers = lib.attrsets.filterAttrs (k: _v: k != currenthost) net.hosts;
              wg-peers-attrs = lib.attrsets.mapAttrs (
                _k: v:
                {
                  PersistentKeepalive = 29;
                  PublicKey = v.publicKey;
                  # only route to /32 or /128, i.e. single client
                  AllowedIPs = maskip net v;
                }
                // (
                  if !isNull v.endpoint.endpoint then
                    { Endpoint = "${v.endpoint.endpoint}:${toString v.endpoint.port}"; }
                  else
                    { }
                )
              ) peers;
              wg-peers = lib.attrsets.attrValues wg-peers-attrs;
            in
            wg-peers;
        };
      }) net-endpoint;
      netdev-endpoint = builtins.listToAttrs netdev-endpoint-list;

    in
    {
      # make sure that the networkd and wg are enabled
      networking.wireguard.enable = true;
      systemd.network.enable = true;

      systemd.network.networks = systemd-networks;
      systemd.network.netdevs = netdev-client // netdev-endpoint;
    };
}