at 23.11-pre 5.5 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.networking.firewall; 8 9 ifaceSet = concatStringsSep ", " ( 10 map (x: ''"${x}"'') cfg.trustedInterfaces 11 ); 12 13 portsToNftSet = ports: portRanges: concatStringsSep ", " ( 14 map (x: toString x) ports 15 ++ map (x: "${toString x.from}-${toString x.to}") portRanges 16 ); 17 18in 19 20{ 21 22 options = { 23 24 networking.firewall = { 25 extraInputRules = mkOption { 26 type = types.lines; 27 default = ""; 28 example = "ip6 saddr { fc00::/7, fe80::/10 } tcp dport 24800 accept"; 29 description = lib.mdDoc '' 30 Additional nftables rules to be appended to the input-allow 31 chain. 32 33 This option only works with the nftables based firewall. 34 ''; 35 }; 36 37 extraForwardRules = mkOption { 38 type = types.lines; 39 default = ""; 40 example = "iifname wg0 accept"; 41 description = lib.mdDoc '' 42 Additional nftables rules to be appended to the forward-allow 43 chain. 44 45 This option only works with the nftables based firewall. 46 ''; 47 }; 48 }; 49 50 }; 51 52 config = mkIf (cfg.enable && config.networking.nftables.enable) { 53 54 assertions = [ 55 { 56 assertion = cfg.extraCommands == ""; 57 message = "extraCommands is incompatible with the nftables based firewall: ${cfg.extraCommands}"; 58 } 59 { 60 assertion = cfg.extraStopCommands == ""; 61 message = "extraStopCommands is incompatible with the nftables based firewall: ${cfg.extraStopCommands}"; 62 } 63 { 64 assertion = cfg.pingLimit == null || !(hasPrefix "--" cfg.pingLimit); 65 message = "nftables syntax like \"2/second\" should be used in networking.firewall.pingLimit"; 66 } 67 { 68 assertion = config.networking.nftables.rulesetFile == null; 69 message = "networking.nftables.rulesetFile conflicts with the firewall"; 70 } 71 ]; 72 73 networking.nftables.ruleset = '' 74 75 table inet nixos-fw { 76 77 ${optionalString (cfg.checkReversePath != false) '' 78 chain rpfilter { 79 type filter hook prerouting priority mangle + 10; policy drop; 80 81 meta nfproto ipv4 udp sport . udp dport { 67 . 68, 68 . 67 } accept comment "DHCPv4 client/server" 82 fib saddr . mark ${optionalString (cfg.checkReversePath != "loose") ". iif"} oif exists accept 83 84 ${optionalString cfg.logReversePathDrops '' 85 log level info prefix "rpfilter drop: " 86 ''} 87 88 } 89 ''} 90 91 chain input { 92 type filter hook input priority filter; policy drop; 93 94 ${optionalString (ifaceSet != "") ''iifname { ${ifaceSet} } accept comment "trusted interfaces"''} 95 96 # Some ICMPv6 types like NDP is untracked 97 ct state vmap { 98 invalid : drop, 99 established : accept, 100 related : accept, 101 new : jump input-allow, 102 untracked: jump input-allow, 103 } 104 105 ${optionalString cfg.logRefusedConnections '' 106 tcp flags syn / fin,syn,rst,ack log level info prefix "refused connection: " 107 ''} 108 ${optionalString (cfg.logRefusedPackets && !cfg.logRefusedUnicastsOnly) '' 109 pkttype broadcast log level info prefix "refused broadcast: " 110 pkttype multicast log level info prefix "refused multicast: " 111 ''} 112 ${optionalString cfg.logRefusedPackets '' 113 pkttype host log level info prefix "refused packet: " 114 ''} 115 116 ${optionalString cfg.rejectPackets '' 117 meta l4proto tcp reject with tcp reset 118 reject 119 ''} 120 121 } 122 123 chain input-allow { 124 125 ${concatStrings (mapAttrsToList (iface: cfg: 126 let 127 ifaceExpr = optionalString (iface != "default") "iifname ${iface}"; 128 tcpSet = portsToNftSet cfg.allowedTCPPorts cfg.allowedTCPPortRanges; 129 udpSet = portsToNftSet cfg.allowedUDPPorts cfg.allowedUDPPortRanges; 130 in 131 '' 132 ${optionalString (tcpSet != "") "${ifaceExpr} tcp dport { ${tcpSet} } accept"} 133 ${optionalString (udpSet != "") "${ifaceExpr} udp dport { ${udpSet} } accept"} 134 '' 135 ) cfg.allInterfaces)} 136 137 ${optionalString cfg.allowPing '' 138 icmp type echo-request ${optionalString (cfg.pingLimit != null) "limit rate ${cfg.pingLimit}"} accept comment "allow ping" 139 ''} 140 141 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." 142 ip6 daddr fe80::/64 udp dport 546 accept comment "DHCPv6 client" 143 144 ${cfg.extraInputRules} 145 146 } 147 148 ${optionalString cfg.filterForward '' 149 chain forward { 150 type filter hook forward priority filter; policy drop; 151 152 ct state vmap { 153 invalid : drop, 154 established : accept, 155 related : accept, 156 new : jump forward-allow, 157 untracked : jump forward-allow, 158 } 159 160 } 161 162 chain forward-allow { 163 164 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." 165 166 ct status dnat accept comment "allow port forward" 167 168 ${cfg.extraForwardRules} 169 170 } 171 ''} 172 173 } 174 175 ''; 176 177 }; 178 179}