vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / ndppd.nix
blob102bf1160cd0b9e7eb93dc9a2a163a94210dd858
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.services.ndppd;
8   render = s: f: concatStringsSep "\n" (mapAttrsToList f s);
9   prefer = a: b: if a != null then a else b;
11   ndppdConf = prefer cfg.configFile (pkgs.writeText "ndppd.conf" ''
12     route-ttl ${toString cfg.routeTTL}
13     ${render cfg.proxies (proxyInterfaceName: proxy: ''
14     proxy ${prefer proxy.interface proxyInterfaceName} {
15       router ${boolToString proxy.router}
16       timeout ${toString proxy.timeout}
17       ttl ${toString proxy.ttl}
18       ${render proxy.rules (ruleNetworkName: rule: ''
19       rule ${prefer rule.network ruleNetworkName} {
20         ${rule.method}${optionalString (rule.method == "iface") " ${rule.interface}"}
21       }'')}
22     }'')}
23   '');
25   proxy = types.submodule {
26     options = {
27       interface = mkOption {
28         type = types.nullOr types.str;
29         description = ''
30           Listen for any Neighbor Solicitation messages on this interface,
31           and respond to them according to a set of rules.
32           Defaults to the name of the attrset.
33         '';
34         default = null;
35       };
36       router = mkOption {
37         type = types.bool;
38         description = ''
39           Turns on or off the router flag for Neighbor Advertisement Messages.
40         '';
41         default = true;
42       };
43       timeout = mkOption {
44         type = types.int;
45         description = ''
46           Controls how long to wait for a Neighbor Advertisement Message before
47           invalidating the entry, in milliseconds.
48         '';
49         default = 500;
50       };
51       ttl = mkOption {
52         type = types.int;
53         description = ''
54           Controls how long a valid or invalid entry remains in the cache, in
55           milliseconds.
56         '';
57         default = 30000;
58       };
59       rules = mkOption {
60         type = types.attrsOf rule;
61         description = ''
62           This is a rule that the target address is to match against. If no netmask
63           is provided, /128 is assumed. You may have several rule sections, and the
64           addresses may or may not overlap.
65         '';
66         default = {};
67       };
68     };
69   };
71   rule = types.submodule {
72     options = {
73       network = mkOption {
74         type = types.nullOr types.str;
75         description = ''
76           This is the target address is to match against. If no netmask
77           is provided, /128 is assumed. The addresses of several rules
78           may or may not overlap.
79           Defaults to the name of the attrset.
80         '';
81         default = null;
82       };
83       method = mkOption {
84         type = types.enum [ "static" "iface" "auto" ];
85         description = ''
86           static: Immediately answer any Neighbor Solicitation Messages
87             (if they match the IP rule).
88           iface: Forward the Neighbor Solicitation Message through the specified
89             interface and only respond if a matching Neighbor Advertisement
90             Message is received.
91           auto: Same as iface, but instead of manually specifying the outgoing
92             interface, check for a matching route in /proc/net/ipv6_route.
93         '';
94         default = "auto";
95       };
96       interface = mkOption {
97         type = types.nullOr types.str;
98         description = "Interface to use when method is iface.";
99         default = null;
100       };
101     };
102   };
104 in {
105   options.services.ndppd = {
106     enable = mkEnableOption "daemon that proxies NDP (Neighbor Discovery Protocol) messages between interfaces";
107     interface = mkOption {
108       type = types.nullOr types.str;
109       description = ''
110         Interface which is on link-level with router.
111         (Legacy option, use services.ndppd.proxies.\<interface\>.rules.\<network\> instead)
112       '';
113       default = null;
114       example = "eth0";
115     };
116     network = mkOption {
117       type = types.nullOr types.str;
118       description = ''
119         Network that we proxy.
120         (Legacy option, use services.ndppd.proxies.\<interface\>.rules.\<network\> instead)
121       '';
122       default = null;
123       example = "1111::/64";
124     };
125     configFile = mkOption {
126       type = types.nullOr types.path;
127       description = "Path to configuration file.";
128       default = null;
129     };
130     routeTTL = mkOption {
131       type = types.int;
132       description = ''
133         This tells 'ndppd' how often to reload the route file /proc/net/ipv6_route,
134         in milliseconds.
135       '';
136       default = 30000;
137     };
138     proxies = mkOption {
139       type = types.attrsOf proxy;
140       description = ''
141         This sets up a listener, that will listen for any Neighbor Solicitation
142         messages, and respond to them according to a set of rules.
143       '';
144       default = {};
145       example = literalExpression ''
146         {
147           eth0.rules."1111::/64" = {};
148         }
149       '';
150     };
151   };
153   config = mkIf cfg.enable {
154     warnings = mkIf (cfg.interface != null && cfg.network != null) [ ''
155       The options services.ndppd.interface and services.ndppd.network will probably be removed soon,
156       please use services.ndppd.proxies.<interface>.rules.<network> instead.
157     '' ];
159     services.ndppd.proxies = mkIf (cfg.interface != null && cfg.network != null) {
160       ${cfg.interface}.rules.${cfg.network} = {};
161     };
163     systemd.services.ndppd = {
164       description = "NDP Proxy Daemon";
165       documentation = [ "man:ndppd(1)" "man:ndppd.conf(5)" ];
166       after = [ "network-pre.target" ];
167       wantedBy = [ "multi-user.target" ];
168       serviceConfig = {
169         ExecStart = "${pkgs.ndppd}/bin/ndppd -c ${ndppdConf}";
171         # Sandboxing
172         CapabilityBoundingSet = "CAP_NET_RAW CAP_NET_ADMIN";
173         ProtectSystem = "strict";
174         ProtectHome = true;
175         PrivateTmp = true;
176         PrivateDevices = true;
177         ProtectKernelTunables = true;
178         ProtectKernelModules = true;
179         ProtectControlGroups = true;
180         RestrictAddressFamilies = "AF_INET6 AF_PACKET AF_NETLINK";
181         RestrictNamespaces = true;
182         LockPersonality = true;
183         MemoryDenyWriteExecute = true;
184         RestrictRealtime = true;
185         RestrictSUIDSGID = true;
186       };
187     };
188   };