nixos/firewall: per-interface port options
This commit is contained in:
parent
0450c7f5f3
commit
c60c8aa759
@ -148,38 +148,42 @@ let
|
|||||||
ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept
|
ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept
|
||||||
|
|
||||||
# Accept connections to the allowed TCP ports.
|
# 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.allowedTCPPorts
|
||||||
}
|
) cfg.interfaces)}
|
||||||
|
|
||||||
# Accept connections to the allowed TCP port ranges.
|
# 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
|
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.allowedTCPPortRanges
|
||||||
}
|
) cfg.interfaces)}
|
||||||
|
|
||||||
# Accept packets on the allowed UDP ports.
|
# 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.allowedUDPPorts
|
||||||
}
|
) cfg.interfaces)}
|
||||||
|
|
||||||
# Accept packets on the allowed UDP port ranges.
|
# 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
|
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.allowedUDPPortRanges
|
||||||
}
|
) cfg.interfaces)}
|
||||||
|
|
||||||
# Accept IPv4 multicast. Not a big security risk since
|
# Accept IPv4 multicast. Not a big security risk since
|
||||||
# probably nobody is listening anyway.
|
# probably nobody is listening anyway.
|
||||||
@ -254,106 +258,30 @@ let
|
|||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in
|
commonOptions = {
|
||||||
|
allowedTCPPorts = mkOption {
|
||||||
{
|
|
||||||
|
|
||||||
###### 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 {
|
|
||||||
type = types.listOf types.int;
|
type = types.listOf types.int;
|
||||||
default = [ ];
|
default = [ ];
|
||||||
example = [ 22 80 ];
|
example = [ 22 80 ];
|
||||||
description =
|
description =
|
||||||
''
|
''
|
||||||
List of TCP ports on which incoming connections are
|
List of TCP ports on which incoming connections are
|
||||||
accepted.
|
accepted.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedTCPPortRanges = mkOption {
|
allowedTCPPortRanges = mkOption {
|
||||||
type = types.listOf (types.attrsOf types.int);
|
type = types.listOf (types.attrsOf types.int);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
example = [ { from = 8999; to = 9003; } ];
|
example = [ { from = 8999; to = 9003; } ];
|
||||||
description =
|
description =
|
||||||
''
|
''
|
||||||
A range of TCP ports on which incoming connections are
|
A range of TCP ports on which incoming connections are
|
||||||
accepted.
|
accepted.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedUDPPorts = mkOption {
|
allowedUDPPorts = mkOption {
|
||||||
type = types.listOf types.int;
|
type = types.listOf types.int;
|
||||||
default = [ ];
|
default = [ ];
|
||||||
example = [ 53 ];
|
example = [ 53 ];
|
||||||
@ -363,7 +291,7 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedUDPPortRanges = mkOption {
|
allowedUDPPortRanges = mkOption {
|
||||||
type = types.listOf (types.attrsOf types.int);
|
type = types.listOf (types.attrsOf types.int);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
example = [ { from = 60000; to = 61000; } ];
|
example = [ { from = 60000; to = 61000; } ];
|
||||||
@ -372,133 +300,226 @@ in
|
|||||||
Range of open UDP ports.
|
Range of open UDP ports.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
networking.firewall.allowPing = mkOption {
|
in
|
||||||
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.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 {
|
###### interface
|
||||||
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
|
options = {
|
||||||
this option to loose mode or disable it and setup your own
|
|
||||||
counter-measures.
|
|
||||||
|
|
||||||
This option can be either true (or "strict"), "loose" (only
|
networking.firewall = {
|
||||||
drop the packet if the source address is not reachable via any
|
enable = mkOption {
|
||||||
interface) or false. Defaults to the value of
|
type = types.bool;
|
||||||
kernelHasRPFilter.
|
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 {
|
logRefusedPackets = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description =
|
description =
|
||||||
''
|
''
|
||||||
Logs dropped packets failing the reverse path filter test if
|
Whether to log all rejected or dropped incoming packets.
|
||||||
the option networking.firewall.checkReversePath is enabled.
|
This tends to give a lot of log messages, so it's mostly
|
||||||
'';
|
useful for debugging.
|
||||||
};
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
networking.firewall.connectionTrackingModules = mkOption {
|
logRefusedUnicastsOnly = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.bool;
|
||||||
default = [ ];
|
default = true;
|
||||||
example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
|
description =
|
||||||
description =
|
''
|
||||||
''
|
If <option>networking.firewall.logRefusedPackets</option>
|
||||||
List of connection-tracking helpers that are auto-loaded.
|
and this option are enabled, then only log packets
|
||||||
The complete list of possible values is given in the example.
|
specifically directed at this machine, i.e., not broadcasts
|
||||||
|
or multicasts.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
As helpers can pose as a security risk, it is advised to
|
rejectPackets = mkOption {
|
||||||
set this to an empty list and disable the setting
|
type = types.bool;
|
||||||
networking.firewall.autoLoadConntrackHelpers unless you
|
default = false;
|
||||||
know what you are doing. Connection tracking is disabled
|
description =
|
||||||
by default.
|
''
|
||||||
|
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.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
Loading of helpers is recommended to be done through the
|
trustedInterfaces = mkOption {
|
||||||
CT target. More info:
|
type = types.listOf types.str;
|
||||||
https://home.regit.org/netfilter-en/secure-use-of-helpers/
|
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.autoLoadConntrackHelpers = mkOption {
|
allowPing = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = true;
|
||||||
description =
|
description =
|
||||||
''
|
''
|
||||||
Whether to auto-load connection-tracking helpers.
|
Whether to respond to incoming ICMPv4 echo requests
|
||||||
See the description at networking.firewall.connectionTrackingModules
|
("pings"). ICMPv6 pings are always allowed because the
|
||||||
|
larger address space of IPv6 makes network scanning much
|
||||||
|
less effective.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
(needs kernel 3.5+)
|
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.extraCommands = mkOption {
|
checkReversePath = mkOption {
|
||||||
type = types.lines;
|
type = types.either types.bool (types.enum ["strict" "loose"]);
|
||||||
default = "";
|
default = kernelHasRPFilter;
|
||||||
example = "iptables -A INPUT -p icmp -j ACCEPT";
|
example = "loose";
|
||||||
description =
|
description =
|
||||||
''
|
''
|
||||||
Additional shell commands executed as part of the firewall
|
Performs a reverse path filter test on a packet. If a reply
|
||||||
initialisation script. These are executed just before the
|
to the packet would not be sent via the same interface that
|
||||||
final "reject" firewall rule is added, so they can be used
|
the packet arrived on, it is refused.
|
||||||
to allow packets that would otherwise be refused.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.extraPackages = mkOption {
|
If using asymmetric routing or other complicated routing, set
|
||||||
type = types.listOf types.package;
|
this option to loose mode or disable it and setup your own
|
||||||
default = [ ];
|
counter-measures.
|
||||||
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.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.extraStopCommands = mkOption {
|
This option can be either true (or "strict"), "loose" (only
|
||||||
type = types.lines;
|
drop the packet if the source address is not reachable via any
|
||||||
default = "";
|
interface) or false. Defaults to the value of
|
||||||
example = "iptables -P INPUT ACCEPT";
|
kernelHasRPFilter.
|
||||||
description =
|
|
||||||
''
|
(needs kernel 3.3+)
|
||||||
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.
|
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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user