summary refs log tree commit diff
path: root/nixos/modules/services/networking/firewall.nix
diff options
context:
space:
mode:
authorgnidorah <gnidorah@users.noreply.github.com>2018-05-29 22:10:25 +0300
committergnidorah <gnidorah@users.noreply.github.com>2018-06-24 16:49:10 +0300
commitc60c8aa759b7b3b396a709effefb879ceed96fa6 (patch)
treec4d58b7e4195273940621c428a8e02c187137231 /nixos/modules/services/networking/firewall.nix
parent0450c7f5f3b197a27e3d75544ec062adc46ef47e (diff)
downloadnixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.tar
nixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.tar.gz
nixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.tar.bz2
nixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.tar.lz
nixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.tar.xz
nixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.tar.zst
nixpkgs-c60c8aa759b7b3b396a709effefb879ceed96fa6.zip
nixos/firewall: per-interface port options
Diffstat (limited to 'nixos/modules/services/networking/firewall.nix')
-rw-r--r--nixos/modules/services/networking/firewall.nix439
1 files changed, 230 insertions, 209 deletions
diff --git a/nixos/modules/services/networking/firewall.nix b/nixos/modules/services/networking/firewall.nix
index c4bd0e7f9ee..36f1dd8d247 100644
--- a/nixos/modules/services/networking/firewall.nix
+++ b/nixos/modules/services/networking/firewall.nix
@@ -148,38 +148,42 @@ let
     ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept
 
     # Accept connections to the allowed TCP ports.
-    ${concatMapStrings (port:
+    ${concatStrings (mapAttrsToList (iface: cfg:
+      concatMapStrings (port:
         ''
-          ip46tables -A nixos-fw -p tcp --dport ${toString port} -j nixos-fw-accept
+          ip46tables -A nixos-fw -p tcp --dport ${toString port} -j nixos-fw-accept ${optionalString (iface != "default") "-i ${iface}"}
         ''
       ) cfg.allowedTCPPorts
-    }
+    ) cfg.interfaces)}
 
     # Accept connections to the allowed TCP port ranges.
-    ${concatMapStrings (rangeAttr:
+    ${concatStrings (mapAttrsToList (iface: cfg:
+      concatMapStrings (rangeAttr:
         let range = toString rangeAttr.from + ":" + toString rangeAttr.to; in
         ''
-          ip46tables -A nixos-fw -p tcp --dport ${range} -j nixos-fw-accept
+          ip46tables -A nixos-fw -p tcp --dport ${range} -j nixos-fw-accept ${optionalString (iface != "default") "-i ${iface}"}
         ''
       ) cfg.allowedTCPPortRanges
-    }
+    ) cfg.interfaces)}
 
     # Accept packets on the allowed UDP ports.
-    ${concatMapStrings (port:
+    ${concatStrings (mapAttrsToList (iface: cfg:
+      concatMapStrings (port:
         ''
-          ip46tables -A nixos-fw -p udp --dport ${toString port} -j nixos-fw-accept
+          ip46tables -A nixos-fw -p udp --dport ${toString port} -j nixos-fw-accept ${optionalString (iface != "default") "-i ${iface}"}
         ''
       ) cfg.allowedUDPPorts
-    }
+    ) cfg.interfaces)}
 
     # Accept packets on the allowed UDP port ranges.
-    ${concatMapStrings (rangeAttr:
+    ${concatStrings (mapAttrsToList (iface: cfg:
+      concatMapStrings (rangeAttr:
         let range = toString rangeAttr.from + ":" + toString rangeAttr.to; in
         ''
-          ip46tables -A nixos-fw -p udp --dport ${range} -j nixos-fw-accept
+          ip46tables -A nixos-fw -p udp --dport ${range} -j nixos-fw-accept ${optionalString (iface != "default") "-i ${iface}"}
         ''
       ) cfg.allowedUDPPortRanges
-    }
+    ) cfg.interfaces)}
 
     # Accept IPv4 multicast.  Not a big security risk since
     # probably nobody is listening anyway.
@@ -254,106 +258,30 @@ let
     fi
   '';
 
-in
-
-{
-
-  ###### interface
-
-  options = {
-
-    networking.firewall.enable = mkOption {
-      type = types.bool;
-      default = true;
-      description =
-        ''
-          Whether to enable the firewall.  This is a simple stateful
-          firewall that blocks connection attempts to unauthorised TCP
-          or UDP ports on this machine.  It does not affect packet
-          forwarding.
-        '';
-    };
-
-    networking.firewall.logRefusedConnections = mkOption {
-      type = types.bool;
-      default = true;
-      description =
-        ''
-          Whether to log rejected or dropped incoming connections.
-        '';
-    };
-
-    networking.firewall.logRefusedPackets = mkOption {
-      type = types.bool;
-      default = false;
-      description =
-        ''
-          Whether to log all rejected or dropped incoming packets.
-          This tends to give a lot of log messages, so it's mostly
-          useful for debugging.
-        '';
-    };
-
-    networking.firewall.logRefusedUnicastsOnly = mkOption {
-      type = types.bool;
-      default = true;
-      description =
-        ''
-          If <option>networking.firewall.logRefusedPackets</option>
-          and this option are enabled, then only log packets
-          specifically directed at this machine, i.e., not broadcasts
-          or multicasts.
-        '';
-    };
-
-    networking.firewall.rejectPackets = mkOption {
-      type = types.bool;
-      default = false;
-      description =
-        ''
-          If set, refused packets are rejected rather than dropped
-          (ignored).  This means that an ICMP "port unreachable" error
-          message is sent back to the client (or a TCP RST packet in
-          case of an existing connection).  Rejecting packets makes
-          port scanning somewhat easier.
-        '';
-    };
-
-    networking.firewall.trustedInterfaces = mkOption {
-      type = types.listOf types.str;
-      default = [ ];
-      example = [ "enp0s2" ];
-      description =
-        ''
-          Traffic coming in from these interfaces will be accepted
-          unconditionally.  Traffic from the loopback (lo) interface
-          will always be accepted.
-        '';
-    };
-
-    networking.firewall.allowedTCPPorts = mkOption {
+  commonOptions = {
+    allowedTCPPorts = mkOption {
       type = types.listOf types.int;
       default = [ ];
       example = [ 22 80 ];
       description =
-        ''
+        '' 
           List of TCP ports on which incoming connections are
           accepted.
         '';
     };
 
-    networking.firewall.allowedTCPPortRanges = mkOption {
+    allowedTCPPortRanges = mkOption {
       type = types.listOf (types.attrsOf types.int);
       default = [ ];
       example = [ { from = 8999; to = 9003; } ];
       description =
-        ''
+        '' 
           A range of TCP ports on which incoming connections are
           accepted.
         '';
     };
 
-    networking.firewall.allowedUDPPorts = mkOption {
+    allowedUDPPorts = mkOption {
       type = types.listOf types.int;
       default = [ ];
       example = [ 53 ];
@@ -363,7 +291,7 @@ in
         '';
     };
 
-    networking.firewall.allowedUDPPortRanges = mkOption {
+    allowedUDPPortRanges = mkOption {
       type = types.listOf (types.attrsOf types.int);
       default = [ ];
       example = [ { from = 60000; to = 61000; } ];
@@ -372,133 +300,226 @@ in
           Range of open UDP ports.
         '';
     };
+  };
 
-    networking.firewall.allowPing = mkOption {
-      type = types.bool;
-      default = true;
-      description =
-        ''
-          Whether to respond to incoming ICMPv4 echo requests
-          ("pings").  ICMPv6 pings are always allowed because the
-          larger address space of IPv6 makes network scanning much
-          less effective.
-        '';
-    };
+in
 
-    networking.firewall.pingLimit = mkOption {
-      type = types.nullOr (types.separatedString " ");
-      default = null;
-      example = "--limit 1/minute --limit-burst 5";
-      description =
-        ''
-          If pings are allowed, this allows setting rate limits
-          on them.  If non-null, this option should be in the form of
-          flags like "--limit 1/minute --limit-burst 5"
-        '';
-    };
+{
 
-    networking.firewall.checkReversePath = mkOption {
-      type = types.either types.bool (types.enum ["strict" "loose"]);
-      default = kernelHasRPFilter;
-      example = "loose";
-      description =
-        ''
-          Performs a reverse path filter test on a packet.  If a reply
-          to the packet would not be sent via the same interface that
-          the packet arrived on, it is refused.
+  ###### interface
 
-          If using asymmetric routing or other complicated routing, set
-          this option to loose mode or disable it and setup your own
-          counter-measures.
+  options = {
 
-          This option can be either true (or "strict"), "loose" (only
-          drop the packet if the source address is not reachable via any
-          interface) or false.  Defaults to the value of
-          kernelHasRPFilter.
+    networking.firewall = {
+      enable = mkOption {
+        type = types.bool;
+        default = true;
+        description =
+          ''
+            Whether to enable the firewall.  This is a simple stateful
+            firewall that blocks connection attempts to unauthorised TCP
+            or UDP ports on this machine.  It does not affect packet
+            forwarding.
+          '';
+      };
 
-          (needs kernel 3.3+)
-        '';
-    };
+      logRefusedConnections = mkOption {
+        type = types.bool;
+        default = true;
+        description =
+          ''
+            Whether to log rejected or dropped incoming connections.
+          '';
+      };
 
-    networking.firewall.logReversePathDrops = mkOption {
-      type = types.bool;
-      default = false;
-      description =
-        ''
-          Logs dropped packets failing the reverse path filter test if
-          the option networking.firewall.checkReversePath is enabled.
-        '';
-    };
+      logRefusedPackets = mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            Whether to log all rejected or dropped incoming packets.
+            This tends to give a lot of log messages, so it's mostly
+            useful for debugging.
+          '';
+      };
 
-    networking.firewall.connectionTrackingModules = mkOption {
-      type = types.listOf types.str;
-      default = [ ];
-      example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
-      description =
-        ''
-          List of connection-tracking helpers that are auto-loaded.
-          The complete list of possible values is given in the example.
-
-          As helpers can pose as a security risk, it is advised to
-          set this to an empty list and disable the setting
-          networking.firewall.autoLoadConntrackHelpers unless you
-          know what you are doing. Connection tracking is disabled
-          by default.
-
-          Loading of helpers is recommended to be done through the
-          CT target.  More info:
-          https://home.regit.org/netfilter-en/secure-use-of-helpers/
-        '';
-    };
+      logRefusedUnicastsOnly = mkOption {
+        type = types.bool;
+        default = true;
+        description =
+          ''
+            If <option>networking.firewall.logRefusedPackets</option>
+            and this option are enabled, then only log packets
+            specifically directed at this machine, i.e., not broadcasts
+            or multicasts.
+          '';
+      };
 
-    networking.firewall.autoLoadConntrackHelpers = mkOption {
-      type = types.bool;
-      default = false;
-      description =
-        ''
-          Whether to auto-load connection-tracking helpers.
-          See the description at networking.firewall.connectionTrackingModules
+      rejectPackets = mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            If set, refused packets are rejected rather than dropped
+            (ignored).  This means that an ICMP "port unreachable" error
+            message is sent back to the client (or a TCP RST packet in
+            case of an existing connection).  Rejecting packets makes
+            port scanning somewhat easier.
+          '';
+      };
 
-          (needs kernel 3.5+)
-        '';
-    };
+      trustedInterfaces = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        example = [ "enp0s2" ];
+        description =
+          ''
+            Traffic coming in from these interfaces will be accepted
+            unconditionally.  Traffic from the loopback (lo) interface
+            will always be accepted.
+          '';
+      };
 
-    networking.firewall.extraCommands = mkOption {
-      type = types.lines;
-      default = "";
-      example = "iptables -A INPUT -p icmp -j ACCEPT";
-      description =
-        ''
-          Additional shell commands executed as part of the firewall
-          initialisation script.  These are executed just before the
-          final "reject" firewall rule is added, so they can be used
-          to allow packets that would otherwise be refused.
-        '';
-    };
+      allowPing = mkOption {
+        type = types.bool;
+        default = true;
+        description =
+          ''
+            Whether to respond to incoming ICMPv4 echo requests
+            ("pings").  ICMPv6 pings are always allowed because the
+            larger address space of IPv6 makes network scanning much
+            less effective.
+          '';
+      };
 
-    networking.firewall.extraPackages = mkOption {
-      type = types.listOf types.package;
-      default = [ ];
-      example = literalExample "[ pkgs.ipset ]";
-      description =
-        ''
-          Additional packages to be included in the environment of the system
-          as well as the path of networking.firewall.extraCommands.
-        '';
-    };
+      pingLimit = mkOption {
+        type = types.nullOr (types.separatedString " ");
+        default = null;
+        example = "--limit 1/minute --limit-burst 5";
+        description =
+          ''
+            If pings are allowed, this allows setting rate limits
+            on them.  If non-null, this option should be in the form of
+            flags like "--limit 1/minute --limit-burst 5"
+          '';
+      };
 
-    networking.firewall.extraStopCommands = mkOption {
-      type = types.lines;
-      default = "";
-      example = "iptables -P INPUT ACCEPT";
-      description =
-        ''
-          Additional shell commands executed as part of the firewall
-          shutdown script.  These are executed just after the removal
-          of the NixOS input rule, or if the service enters a failed
-          state.
-        '';
-    };
+      checkReversePath = mkOption {
+        type = types.either types.bool (types.enum ["strict" "loose"]);
+        default = kernelHasRPFilter;
+        example = "loose";
+        description =
+          ''
+            Performs a reverse path filter test on a packet.  If a reply
+            to the packet would not be sent via the same interface that
+            the packet arrived on, it is refused.
+
+            If using asymmetric routing or other complicated routing, set
+            this option to loose mode or disable it and setup your own
+            counter-measures.
+
+            This option can be either true (or "strict"), "loose" (only
+            drop the packet if the source address is not reachable via any
+            interface) or false.  Defaults to the value of
+            kernelHasRPFilter.
+
+            (needs kernel 3.3+)
+          '';
+      };
+
+      logReversePathDrops = mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            Logs dropped packets failing the reverse path filter test if
+            the option networking.firewall.checkReversePath is enabled.
+          '';
+      };
+
+      connectionTrackingModules = mkOption {
+        type = types.listOf types.str;
+        default = [ ];
+        example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
+        description =
+          ''
+            List of connection-tracking helpers that are auto-loaded.
+            The complete list of possible values is given in the example.
+
+            As helpers can pose as a security risk, it is advised to
+            set this to an empty list and disable the setting
+            networking.firewall.autoLoadConntrackHelpers unless you
+            know what you are doing. Connection tracking is disabled
+            by default.
+
+            Loading of helpers is recommended to be done through the
+            CT target.  More info:
+            https://home.regit.org/netfilter-en/secure-use-of-helpers/
+          '';
+      };
+
+      autoLoadConntrackHelpers = mkOption {
+        type = types.bool;
+        default = false;
+        description =
+          ''
+            Whether to auto-load connection-tracking helpers.
+            See the description at networking.firewall.connectionTrackingModules
+
+            (needs kernel 3.5+)
+          '';
+      };
+
+      extraCommands = mkOption {
+        type = types.lines;
+        default = "";
+        example = "iptables -A INPUT -p icmp -j ACCEPT";
+        description =
+          ''
+            Additional shell commands executed as part of the firewall
+            initialisation script.  These are executed just before the
+            final "reject" firewall rule is added, so they can be used
+            to allow packets that would otherwise be refused.
+          '';
+      };
+
+      extraPackages = mkOption {
+        type = types.listOf types.package;
+        default = [ ];
+        example = literalExample "[ pkgs.ipset ]";
+        description =
+          ''
+            Additional packages to be included in the environment of the system
+            as well as the path of networking.firewall.extraCommands.
+          '';
+      };
+
+      extraStopCommands = mkOption {
+        type = types.lines;
+        default = "";
+        example = "iptables -P INPUT ACCEPT";
+        description =
+          ''
+            Additional shell commands executed as part of the firewall
+            shutdown script.  These are executed just after the removal
+            of the NixOS input rule, or if the service enters a failed
+            state.
+          '';
+      };
+
+      interfaces = mkOption {
+        default = {
+          default = mapAttrs (name: value: cfg."${name}") commonOptions;
+        };
+        type = with types; attrsOf (submodule [ { options = commonOptions; } ]);
+        description =
+          ''
+            Interface-specific open ports. Setting this value will override
+            all values of the <literal>networking.firewall.allowed*</literal>
+            options.
+          '';
+      };
+    } // commonOptions;
 
   };