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