vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / tayga.nix
blob9f118b243e90c5963abe562ba858c1057a3b1b2e
1 { config, lib, pkgs, ... }:
3 with lib;
4 let
5   cfg = config.services.tayga;
7   # Converts an address set to a string
8   strAddr = addr: "${addr.address}/${toString addr.prefixLength}";
10   configFile = pkgs.writeText "tayga.conf" ''
11     tun-device ${cfg.tunDevice}
13     ipv4-addr ${cfg.ipv4.address}
14     ${optionalString (cfg.ipv6.address != null) "ipv6-addr ${cfg.ipv6.address}"}
16     prefix ${strAddr cfg.ipv6.pool}
17     dynamic-pool ${strAddr cfg.ipv4.pool}
18     data-dir ${cfg.dataDir}
20     ${concatStringsSep "\n" (mapAttrsToList (ipv4: ipv6: "map " + ipv4 + " " + ipv6) cfg.mappings)}
21   '';
23   addrOpts = v:
24     assert v == 4 || v == 6;
25     {
26       options = {
27         address = mkOption {
28           type = types.str;
29           description = "IPv${toString v} address.";
30         };
32         prefixLength = mkOption {
33           type = types.addCheck types.int (n: n >= 0 && n <= (if v == 4 then 32 else 128));
34           description = ''
35             Subnet mask of the interface, specified as the number of
36             bits in the prefix ("${if v == 4 then "24" else "64"}").
37           '';
38         };
39       };
40     };
42   versionOpts = v: {
43     options = {
44       router = {
45         address = mkOption {
46           type = types.str;
47           description = "The IPv${toString v} address of the router.";
48         };
49       };
51       address = mkOption {
52         type = types.nullOr types.str;
53         default = null;
54         description = "The source IPv${toString v} address of the TAYGA server.";
55       };
57       pool = mkOption {
58         type = with types; nullOr (submodule (addrOpts v));
59         description = "The pool of IPv${toString v} addresses which are used for translation.";
60       };
61     };
62   };
65   options = {
66     services.tayga = {
67       enable = mkEnableOption "Tayga";
69       package = mkPackageOption pkgs "tayga" { };
71       ipv4 = mkOption {
72         type = types.submodule (versionOpts 4);
73         description = "IPv4-specific configuration.";
74         example = literalExpression ''
75           {
76             address = "192.0.2.0";
77             router = {
78               address = "192.0.2.1";
79             };
80             pool = {
81               address = "192.0.2.1";
82               prefixLength = 24;
83             };
84           }
85         '';
86       };
88       ipv6 = mkOption {
89         type = types.submodule (versionOpts 6);
90         description = "IPv6-specific configuration.";
91         example = literalExpression ''
92           {
93             address = "2001:db8::1";
94             router = {
95               address = "64:ff9b::1";
96             };
97             pool = {
98               address = "64:ff9b::";
99               prefixLength = 96;
100             };
101           }
102         '';
103       };
105       dataDir = mkOption {
106         type = types.path;
107         default = "/var/lib/tayga";
108         description = "Directory for persistent data.";
109       };
111       tunDevice = mkOption {
112         type = types.str;
113         default = "nat64";
114         description = "Name of the nat64 tun device.";
115       };
117       mappings = mkOption {
118         type = types.attrsOf types.str;
119         default = {};
120         description = "Static IPv4 -> IPv6 host mappings.";
121         example = literalExpression ''
122           {
123             "192.168.5.42" = "2001:db8:1:4444::1";
124             "192.168.5.43" = "2001:db8:1:4444::2";
125             "192.168.255.2" = "2001:db8:1:569::143";
126           }
127         '';
128       };
129     };
130   };
132   config = mkIf cfg.enable {
133     assertions = [
134       {
135         assertion = allUnique (attrValues cfg.mappings);
136         message = "Neither the IPv4 nor the IPv6 addresses must be entered twice in the mappings.";
137       }
138     ];
140     networking.interfaces."${cfg.tunDevice}" = {
141       virtual = true;
142       virtualType = "tun";
143       virtualOwner = mkIf config.networking.useNetworkd "";
144       ipv4 = {
145         addresses = [
146           { address = cfg.ipv4.router.address; prefixLength = 32; }
147         ];
148         routes = [
149           cfg.ipv4.pool
150         ];
151       };
152       ipv6 = {
153         addresses = [
154           { address = cfg.ipv6.router.address; prefixLength = 128; }
155         ];
156         routes = [
157           cfg.ipv6.pool
158         ];
159       };
160     };
162     systemd.services.tayga = {
163       description = "Stateless NAT64 implementation";
164       wantedBy = [ "multi-user.target" ];
165       after = [ "network.target" ];
167       serviceConfig = {
168         ExecStart = "${cfg.package}/bin/tayga -d --nodetach --config ${configFile}";
169         ExecReload = "${pkgs.coreutils}/bin/kill -SIGHUP $MAINPID";
170         Restart = "always";
172         # Hardening Score:
173         #  - nixos-scripts: 2.1
174         #  - systemd-networkd: 1.6
175         ProtectHome = true;
176         SystemCallFilter = [
177           "@network-io"
178           "@system-service"
179           "~@privileged"
180           "~@resources"
181         ];
182         ProtectKernelLogs = true;
183         AmbientCapabilities = [
184           "CAP_NET_ADMIN"
185         ];
186         CapabilityBoundingSet = "";
187         RestrictAddressFamilies = [
188           "AF_INET"
189           "AF_INET6"
190           "AF_NETLINK"
191         ];
192         StateDirectory = "tayga";
193         DynamicUser = mkIf config.networking.useNetworkd true;
194         MemoryDenyWriteExecute = true;
195         RestrictRealtime = true;
196         RestrictSUIDSGID = true;
197         ProtectHostname = true;
198         ProtectKernelModules = true;
199         ProtectKernelTunables = true;
200         RestrictNamespaces = true;
201         NoNewPrivileges = true;
202         ProtectControlGroups = true;
203         SystemCallArchitectures = "native";
204         PrivateTmp = true;
205         LockPersonality = true;
206         ProtectSystem = true;
207         PrivateUsers = true;
208         ProtectProc = "invisible";
209       };
210     };
211   };