normcap: fix on GNOME wayland when used via keybind or alt-f2 (#351763)
[NixPkgs.git] / nixos / modules / services / networking / firewall-nftables.nix
blobd9695c0e4d27211dabd4496ce949dd0e4a8739f1
2   config,
3   lib,
4   pkgs,
5   ...
6 }:
7 let
9   cfg = config.networking.firewall;
11   ifaceSet = lib.concatStringsSep ", " (map (x: ''"${x}"'') cfg.trustedInterfaces);
13   portsToNftSet =
14     ports: portRanges:
15     lib.concatStringsSep ", " (
16       map (x: toString x) ports ++ map (x: "${toString x.from}-${toString x.to}") portRanges
17     );
23   options = {
25     networking.firewall = {
26       extraInputRules = lib.mkOption {
27         type = lib.types.lines;
28         default = "";
29         example = "ip6 saddr { fc00::/7, fe80::/10 } tcp dport 24800 accept";
30         description = ''
31           Additional nftables rules to be appended to the input-allow
32           chain.
34           This option only works with the nftables based firewall.
35         '';
36       };
38       extraForwardRules = lib.mkOption {
39         type = lib.types.lines;
40         default = "";
41         example = "iifname wg0 accept";
42         description = ''
43           Additional nftables rules to be appended to the forward-allow
44           chain.
46           This option only works with the nftables based firewall.
47         '';
48       };
50       extraReversePathFilterRules = lib.mkOption {
51         type = lib.types.lines;
52         default = "";
53         example = "fib daddr . mark . iif type local accept";
54         description = ''
55           Additional nftables rules to be appended to the rpfilter-allow
56           chain.
58           This option only works with the nftables based firewall.
59         '';
60       };
61     };
63   };
65   config = lib.mkIf (cfg.enable && config.networking.nftables.enable) {
67     assertions = [
68       {
69         assertion = cfg.extraCommands == "";
70         message = "extraCommands is incompatible with the nftables based firewall: ${cfg.extraCommands}";
71       }
72       {
73         assertion = cfg.extraStopCommands == "";
74         message = "extraStopCommands is incompatible with the nftables based firewall: ${cfg.extraStopCommands}";
75       }
76       {
77         assertion = cfg.pingLimit == null || !(lib.hasPrefix "--" cfg.pingLimit);
78         message = "nftables syntax like \"2/second\" should be used in networking.firewall.pingLimit";
79       }
80       {
81         assertion = config.networking.nftables.rulesetFile == null;
82         message = "networking.nftables.rulesetFile conflicts with the firewall";
83       }
84     ];
86     networking.nftables.tables."nixos-fw".family = "inet";
87     networking.nftables.tables."nixos-fw".content = ''
88       set temp-ports {
89         comment "Temporarily opened ports"
90         type inet_proto . inet_service
91         flags interval
92         auto-merge
93       }
95       ${lib.optionalString (cfg.checkReversePath != false) ''
96         chain rpfilter {
97           type filter hook prerouting priority mangle + 10; policy drop;
99           meta nfproto ipv4 udp sport . udp dport { 67 . 68, 68 . 67 } accept comment "DHCPv4 client/server"
100           fib saddr . mark ${lib.optionalString (cfg.checkReversePath != "loose") ". iif"} oif exists accept
102           jump rpfilter-allow
104           ${lib.optionalString cfg.logReversePathDrops ''
105             log level info prefix "rpfilter drop: "
106           ''}
108         }
109       ''}
111       chain rpfilter-allow {
112         ${cfg.extraReversePathFilterRules}
113       }
115       chain input {
116         type filter hook input priority filter; policy drop;
118         ${lib.optionalString (
119           ifaceSet != ""
120         ) ''iifname { ${ifaceSet} } accept comment "trusted interfaces"''}
122         # Some ICMPv6 types like NDP is untracked
123         ct state vmap {
124           invalid : drop,
125           established : accept,
126           related : accept,
127           new : jump input-allow,
128           untracked: jump input-allow,
129         }
131         ${lib.optionalString cfg.logRefusedConnections ''
132           tcp flags syn / fin,syn,rst,ack log level info prefix "refused connection: "
133         ''}
134         ${lib.optionalString (cfg.logRefusedPackets && !cfg.logRefusedUnicastsOnly) ''
135           pkttype broadcast log level info prefix "refused broadcast: "
136           pkttype multicast log level info prefix "refused multicast: "
137         ''}
138         ${lib.optionalString cfg.logRefusedPackets ''
139           pkttype host log level info prefix "refused packet: "
140         ''}
142         ${lib.optionalString cfg.rejectPackets ''
143           meta l4proto tcp reject with tcp reset
144           reject
145         ''}
147       }
149       chain input-allow {
151         ${lib.concatStrings (
152           lib.mapAttrsToList (
153             iface: cfg:
154             let
155               ifaceExpr = lib.optionalString (iface != "default") "iifname ${iface}";
156               tcpSet = portsToNftSet cfg.allowedTCPPorts cfg.allowedTCPPortRanges;
157               udpSet = portsToNftSet cfg.allowedUDPPorts cfg.allowedUDPPortRanges;
158             in
159             ''
160               ${lib.optionalString (tcpSet != "") "${ifaceExpr} tcp dport { ${tcpSet} } accept"}
161               ${lib.optionalString (udpSet != "") "${ifaceExpr} udp dport { ${udpSet} } accept"}
162             ''
163           ) cfg.allInterfaces
164         )}
166         meta l4proto . th dport @temp-ports accept
168         ${lib.optionalString cfg.allowPing ''
169           icmp type echo-request ${
170             lib.optionalString (cfg.pingLimit != null) "limit rate ${cfg.pingLimit}"
171           } accept comment "allow ping"
172         ''}
174         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."
175         ip6 daddr fe80::/64 udp dport 546 accept comment "DHCPv6 client"
177         ${cfg.extraInputRules}
179       }
181       ${lib.optionalString cfg.filterForward ''
182         chain forward {
183           type filter hook forward priority filter; policy drop;
185           ct state vmap {
186             invalid : drop,
187             established : accept,
188             related : accept,
189             new : jump forward-allow,
190             untracked : jump forward-allow,
191           }
193         }
195         chain forward-allow {
197           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."
199           ct status dnat accept comment "allow port forward"
201           ${cfg.extraForwardRules}
203         }
204       ''}
205     '';
207   };