vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / networking / firewall-nftables.nix
blobf954a528410334709df5cc37a1064a07dc460297
1 { config, lib, pkgs, ... }:
2 let
4   cfg = config.networking.firewall;
6   ifaceSet = lib.concatStringsSep ", " (
7     map (x: ''"${x}"'') cfg.trustedInterfaces
8   );
10   portsToNftSet = ports: portRanges: lib.concatStringsSep ", " (
11     map (x: toString x) ports
12     ++ map (x: "${toString x.from}-${toString x.to}") portRanges
13   );
19   options = {
21     networking.firewall = {
22       extraInputRules = lib.mkOption {
23         type = lib.types.lines;
24         default = "";
25         example = "ip6 saddr { fc00::/7, fe80::/10 } tcp dport 24800 accept";
26         description = ''
27           Additional nftables rules to be appended to the input-allow
28           chain.
30           This option only works with the nftables based firewall.
31         '';
32       };
34       extraForwardRules = lib.mkOption {
35         type = lib.types.lines;
36         default = "";
37         example = "iifname wg0 accept";
38         description = ''
39           Additional nftables rules to be appended to the forward-allow
40           chain.
42           This option only works with the nftables based firewall.
43         '';
44       };
46       extraReversePathFilterRules = lib.mkOption {
47         type = lib.types.lines;
48         default = "";
49         example = "fib daddr . mark . iif type local accept";
50         description = ''
51           Additional nftables rules to be appended to the rpfilter-allow
52           chain.
54           This option only works with the nftables based firewall.
55         '';
56       };
57     };
59   };
61   config = lib.mkIf (cfg.enable && config.networking.nftables.enable) {
63     assertions = [
64       {
65         assertion = cfg.extraCommands == "";
66         message = "extraCommands is incompatible with the nftables based firewall: ${cfg.extraCommands}";
67       }
68       {
69         assertion = cfg.extraStopCommands == "";
70         message = "extraStopCommands is incompatible with the nftables based firewall: ${cfg.extraStopCommands}";
71       }
72       {
73         assertion = cfg.pingLimit == null || !(lib.hasPrefix "--" cfg.pingLimit);
74         message = "nftables syntax like \"2/second\" should be used in networking.firewall.pingLimit";
75       }
76       {
77         assertion = config.networking.nftables.rulesetFile == null;
78         message = "networking.nftables.rulesetFile conflicts with the firewall";
79       }
80     ];
82     networking.nftables.tables."nixos-fw".family = "inet";
83     networking.nftables.tables."nixos-fw".content = ''
84         ${lib.optionalString (cfg.checkReversePath != false) ''
85           chain rpfilter {
86             type filter hook prerouting priority mangle + 10; policy drop;
88             meta nfproto ipv4 udp sport . udp dport { 67 . 68, 68 . 67 } accept comment "DHCPv4 client/server"
89             fib saddr . mark ${lib.optionalString (cfg.checkReversePath != "loose") ". iif"} oif exists accept
91             jump rpfilter-allow
93             ${lib.optionalString cfg.logReversePathDrops ''
94               log level info prefix "rpfilter drop: "
95             ''}
97           }
98         ''}
100         chain rpfilter-allow {
101           ${cfg.extraReversePathFilterRules}
102         }
104         chain input {
105           type filter hook input priority filter; policy drop;
107           ${lib.optionalString (ifaceSet != "") ''iifname { ${ifaceSet} } accept comment "trusted interfaces"''}
109           # Some ICMPv6 types like NDP is untracked
110           ct state vmap {
111             invalid : drop,
112             established : accept,
113             related : accept,
114             new : jump input-allow,
115             untracked: jump input-allow,
116           }
118           ${lib.optionalString cfg.logRefusedConnections ''
119             tcp flags syn / fin,syn,rst,ack log level info prefix "refused connection: "
120           ''}
121           ${lib.optionalString (cfg.logRefusedPackets && !cfg.logRefusedUnicastsOnly) ''
122             pkttype broadcast log level info prefix "refused broadcast: "
123             pkttype multicast log level info prefix "refused multicast: "
124           ''}
125           ${lib.optionalString cfg.logRefusedPackets ''
126             pkttype host log level info prefix "refused packet: "
127           ''}
129           ${lib.optionalString cfg.rejectPackets ''
130             meta l4proto tcp reject with tcp reset
131             reject
132           ''}
134         }
136         chain input-allow {
138           ${lib.concatStrings (lib.mapAttrsToList (iface: cfg:
139             let
140               ifaceExpr = lib.optionalString (iface != "default") "iifname ${iface}";
141               tcpSet = portsToNftSet cfg.allowedTCPPorts cfg.allowedTCPPortRanges;
142               udpSet = portsToNftSet cfg.allowedUDPPorts cfg.allowedUDPPortRanges;
143             in
144             ''
145               ${lib.optionalString (tcpSet != "") "${ifaceExpr} tcp dport { ${tcpSet} } accept"}
146               ${lib.optionalString (udpSet != "") "${ifaceExpr} udp dport { ${udpSet} } accept"}
147             ''
148           ) cfg.allInterfaces)}
150           ${lib.optionalString cfg.allowPing ''
151             icmp type echo-request ${lib.optionalString (cfg.pingLimit != null) "limit rate ${cfg.pingLimit}"} accept comment "allow ping"
152           ''}
154           icmpv6 type != { nd-redirect, 139 } accept comment "Accept all ICMPv6 messages except redirects and node information queries (type 139).  See RFC 4890, section 4.4."
155           ip6 daddr fe80::/64 udp dport 546 accept comment "DHCPv6 client"
157           ${cfg.extraInputRules}
159         }
161         ${lib.optionalString cfg.filterForward ''
162           chain forward {
163             type filter hook forward priority filter; policy drop;
165             ct state vmap {
166               invalid : drop,
167               established : accept,
168               related : accept,
169               new : jump forward-allow,
170               untracked : jump forward-allow,
171             }
173           }
175           chain forward-allow {
177             icmpv6 type != { router-renumbering, 139 } accept comment "Accept all ICMPv6 messages except renumbering and node information queries (type 139).  See RFC 4890, section 4.3."
179             ct status dnat accept comment "allow port forward"
181             ${cfg.extraForwardRules}
183           }
184         ''}
185     '';
187   };