Merge #361424: refactor lib.packagesFromDirectoryRecursive (v2)
[NixPkgs.git] / nixos / modules / services / networking / firewall.nix
blobbf3119292eeeb361d37e5e7688fca94a3c5125c7
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
9   cfg = config.networking.firewall;
11   canonicalizePortList = ports: lib.unique (builtins.sort builtins.lessThan ports);
13   commonOptions = {
14     allowedTCPPorts = lib.mkOption {
15       type = lib.types.listOf lib.types.port;
16       default = [ ];
17       apply = canonicalizePortList;
18       example = [
19         22
20         80
21       ];
22       description = ''
23         List of TCP ports on which incoming connections are
24         accepted.
25       '';
26     };
28     allowedTCPPortRanges = lib.mkOption {
29       type = lib.types.listOf (lib.types.attrsOf lib.types.port);
30       default = [ ];
31       example = [
32         {
33           from = 8999;
34           to = 9003;
35         }
36       ];
37       description = ''
38         A range of TCP ports on which incoming connections are
39         accepted.
40       '';
41     };
43     allowedUDPPorts = lib.mkOption {
44       type = lib.types.listOf lib.types.port;
45       default = [ ];
46       apply = canonicalizePortList;
47       example = [ 53 ];
48       description = ''
49         List of open UDP ports.
50       '';
51     };
53     allowedUDPPortRanges = lib.mkOption {
54       type = lib.types.listOf (lib.types.attrsOf lib.types.port);
55       default = [ ];
56       example = [
57         {
58           from = 60000;
59           to = 61000;
60         }
61       ];
62       description = ''
63         Range of open UDP ports.
64       '';
65     };
66   };
72   options = {
74     networking.firewall = {
75       enable = lib.mkOption {
76         type = lib.types.bool;
77         default = true;
78         description = ''
79           Whether to enable the firewall.  This is a simple stateful
80           firewall that blocks connection attempts to unauthorised TCP
81           or UDP ports on this machine.
82         '';
83       };
85       package = lib.mkOption {
86         type = lib.types.package;
87         default = if config.networking.nftables.enable then pkgs.nftables else pkgs.iptables;
88         defaultText = lib.literalExpression ''if config.networking.nftables.enable then "pkgs.nftables" else "pkgs.iptables"'';
89         example = lib.literalExpression "pkgs.iptables-legacy";
90         description = ''
91           The package to use for running the firewall service.
92         '';
93       };
95       logRefusedConnections = lib.mkOption {
96         type = lib.types.bool;
97         default = true;
98         description = ''
99           Whether to log rejected or dropped incoming connections.
100           Note: The logs are found in the kernel logs, i.e. dmesg
101           or journalctl -k.
102         '';
103       };
105       logRefusedPackets = lib.mkOption {
106         type = lib.types.bool;
107         default = false;
108         description = ''
109           Whether to log all rejected or dropped incoming packets.
110           This tends to give a lot of log messages, so it's mostly
111           useful for debugging.
112           Note: The logs are found in the kernel logs, i.e. dmesg
113           or journalctl -k.
114         '';
115       };
117       logRefusedUnicastsOnly = lib.mkOption {
118         type = lib.types.bool;
119         default = true;
120         description = ''
121           If {option}`networking.firewall.logRefusedPackets`
122           and this option are enabled, then only log packets
123           specifically directed at this machine, i.e., not broadcasts
124           or multicasts.
125         '';
126       };
128       rejectPackets = lib.mkOption {
129         type = lib.types.bool;
130         default = false;
131         description = ''
132           If set, refused packets are rejected rather than dropped
133           (ignored).  This means that an ICMP "port unreachable" error
134           message is sent back to the client (or a TCP RST packet in
135           case of an existing connection).  Rejecting packets makes
136           port scanning somewhat easier.
137         '';
138       };
140       trustedInterfaces = lib.mkOption {
141         type = lib.types.listOf lib.types.str;
142         default = [ ];
143         example = [ "enp0s2" ];
144         description = ''
145           Traffic coming in from these interfaces will be accepted
146           unconditionally.  Traffic from the loopback (lo) interface
147           will always be accepted.
148         '';
149       };
151       allowPing = lib.mkOption {
152         type = lib.types.bool;
153         default = true;
154         description = ''
155           Whether to respond to incoming ICMPv4 echo requests
156           ("pings").  ICMPv6 pings are always allowed because the
157           larger address space of IPv6 makes network scanning much
158           less effective.
159         '';
160       };
162       pingLimit = lib.mkOption {
163         type = lib.types.nullOr (lib.types.separatedString " ");
164         default = null;
165         example = "--limit 1/minute --limit-burst 5";
166         description = ''
167           If pings are allowed, this allows setting rate limits on them.
169           For the iptables based firewall, it should be set like
170           "--limit 1/minute --limit-burst 5".
172           For the nftables based firewall, it should be set like
173           "2/second" or "1/minute burst 5 packets".
174         '';
175       };
177       checkReversePath = lib.mkOption {
178         type = lib.types.either lib.types.bool (
179           lib.types.enum [
180             "strict"
181             "loose"
182           ]
183         );
184         default = true;
185         defaultText = lib.literalMD "`true` except if the iptables based firewall is in use and the kernel lacks rpfilter support";
186         example = "loose";
187         description = ''
188           Performs a reverse path filter test on a packet.  If a reply
189           to the packet would not be sent via the same interface that
190           the packet arrived on, it is refused.
192           If using asymmetric routing or other complicated routing, set
193           this option to loose mode or disable it and setup your own
194           counter-measures.
196           This option can be either true (or "strict"), "loose" (only
197           drop the packet if the source address is not reachable via any
198           interface) or false.
199         '';
200       };
202       logReversePathDrops = lib.mkOption {
203         type = lib.types.bool;
204         default = false;
205         description = ''
206           Logs dropped packets failing the reverse path filter test if
207           the option networking.firewall.checkReversePath is enabled.
208         '';
209       };
211       filterForward = lib.mkOption {
212         type = lib.types.bool;
213         default = false;
214         description = ''
215           Enable filtering in IP forwarding.
217           This option only works with the nftables based firewall.
218         '';
219       };
221       connectionTrackingModules = lib.mkOption {
222         type = lib.types.listOf lib.types.str;
223         default = [ ];
224         example = [
225           "ftp"
226           "irc"
227           "sane"
228           "sip"
229           "tftp"
230           "amanda"
231           "h323"
232           "netbios_sn"
233           "pptp"
234           "snmp"
235         ];
236         description = ''
237           List of connection-tracking helpers that are auto-loaded.
238           The complete list of possible values is given in the example.
240           As helpers can pose as a security risk, it is advised to
241           set this to an empty list and disable the setting
242           networking.firewall.autoLoadConntrackHelpers unless you
243           know what you are doing. Connection tracking is disabled
244           by default.
246           Loading of helpers is recommended to be done through the
247           CT target.  More info:
248           https://home.regit.org/netfilter-en/secure-use-of-helpers/
249         '';
250       };
252       autoLoadConntrackHelpers = lib.mkOption {
253         type = lib.types.bool;
254         default = false;
255         description = ''
256           Whether to auto-load connection-tracking helpers.
257           See the description at networking.firewall.connectionTrackingModules
259           (needs kernel 3.5+)
260         '';
261       };
263       extraPackages = lib.mkOption {
264         type = lib.types.listOf lib.types.package;
265         default = [ ];
266         example = lib.literalExpression "[ pkgs.ipset ]";
267         description = ''
268           Additional packages to be included in the environment of the system
269           as well as the path of networking.firewall.extraCommands.
270         '';
271       };
273       interfaces = lib.mkOption {
274         default = { };
275         type = with lib.types; attrsOf (submodule [ { options = commonOptions; } ]);
276         description = ''
277           Interface-specific open ports.
278         '';
279       };
281       allInterfaces = lib.mkOption {
282         internal = true;
283         visible = false;
284         default = {
285           default = lib.mapAttrs (name: value: cfg.${name}) commonOptions;
286         } // cfg.interfaces;
287         type = with lib.types; attrsOf (submodule [ { options = commonOptions; } ]);
288         description = ''
289           All open ports.
290         '';
291       };
292     } // commonOptions;
294   };
296   config = lib.mkIf cfg.enable {
298     assertions = [
299       {
300         assertion = cfg.filterForward -> config.networking.nftables.enable;
301         message = "filterForward only works with the nftables based firewall";
302       }
303       {
304         assertion =
305           cfg.autoLoadConntrackHelpers -> lib.versionOlder config.boot.kernelPackages.kernel.version "6";
306         message = "conntrack helper autoloading has been removed from kernel 6.0 and newer";
307       }
308     ];
310     networking.firewall.trustedInterfaces = [ "lo" ];
312     environment.systemPackages = [
313       cfg.package
314       pkgs.nixos-firewall-tool
315     ] ++ cfg.extraPackages;
317     boot.kernelModules =
318       (lib.optional cfg.autoLoadConntrackHelpers "nf_conntrack")
319       ++ map (x: "nf_conntrack_${x}") cfg.connectionTrackingModules;
320     boot.extraModprobeConfig = lib.optionalString cfg.autoLoadConntrackHelpers ''
321       options nf_conntrack nf_conntrack_helper=1
322     '';
324   };