* Put the NixOS firewall ruleset in its own chain (‘nixos-fw’). This
should make it easier to compose with packages that set their own firewall rules, such as Nova or Libvirt. * Provide a chain for accepted packets (‘nixos-fw-accept’), requested by Nicolas Pierron. svn path=/nixos/trunk/; revision=27607
This commit is contained in:
parent
1d09ad240a
commit
3bc3dc3940
@ -1,4 +1,24 @@
|
||||
# This module enables a simple firewall.
|
||||
/* This module enables a simple firewall.
|
||||
|
||||
The firewall can be customised in arbitrary ways by setting
|
||||
‘networking.firewall.extraCommands’. For modularity, the firewall
|
||||
uses several chains:
|
||||
|
||||
- ‘nixos-fw-input’ is the main chain for input packet processing.
|
||||
|
||||
- ‘nixos-fw-log-refuse’ and ‘nixos-fw-refuse’ are called for
|
||||
refused packets. (The former jumps to the latter after logging
|
||||
the packet.) If you want additional logging, or want to accept
|
||||
certain packets anyway, you can insert rules at the start of
|
||||
these chain.
|
||||
|
||||
- ‘nixos-fw-accept’ is called for accepted packets. If you want
|
||||
additional logging, or want to reject certain packets anyway, you
|
||||
can insert rules at the start of this chain.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
@ -8,6 +28,15 @@ let
|
||||
|
||||
cfg = config.networking.firewall;
|
||||
|
||||
helpers =
|
||||
''
|
||||
# Helper command to manipulate both the IPv4 and IPv6 tables.
|
||||
ip46tables() {
|
||||
iptables "$@"
|
||||
ip6tables "$@"
|
||||
}
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
@ -36,7 +65,7 @@ in
|
||||
};
|
||||
|
||||
networking.firewall.logRefusedPackets = mkOption {
|
||||
default = false;
|
||||
default = true;
|
||||
description =
|
||||
''
|
||||
Whether to log all rejected or dropped incoming packets.
|
||||
@ -45,6 +74,17 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
networking.firewall.logRefusedUnicastsOnly = mkOption {
|
||||
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 {
|
||||
default = false;
|
||||
description =
|
||||
@ -124,50 +164,72 @@ in
|
||||
|
||||
preStart =
|
||||
''
|
||||
# Helper command to manipulate both the IPv4 and IPv6 tables.
|
||||
ip46tables() {
|
||||
iptables "$@"
|
||||
ip6tables "$@"
|
||||
}
|
||||
${helpers}
|
||||
set -x
|
||||
|
||||
ip46tables -F INPUT
|
||||
ip46tables -F FW_REFUSE || true
|
||||
ip46tables -X # flush unused chains
|
||||
ip46tables -P INPUT ACCEPT
|
||||
# Flush the old firewall rules. !!! Ideally, updating the
|
||||
# firewall would be atomic. Apparently that's possible
|
||||
# with iptables-restore.
|
||||
ip46tables -D INPUT -j nixos-fw || true
|
||||
for chain in nixos-fw nixos-fw-accept nixos-fw-log-refuse nixos-fw-refuse FW_REFUSE; do
|
||||
ip46tables -F "$chain" || true
|
||||
ip46tables -X "$chain" || true
|
||||
done
|
||||
|
||||
|
||||
# The "FW_REFUSE" chain performs logging and
|
||||
# rejecting/dropping of packets.
|
||||
ip46tables -N FW_REFUSE
|
||||
# The "nixos-fw-accept" chain just accepts packets.
|
||||
ip46tables -N nixos-fw-accept
|
||||
ip46tables -A nixos-fw-accept -j ACCEPT
|
||||
|
||||
${optionalString cfg.logRefusedConnections ''
|
||||
ip46tables -A FW_REFUSE -p tcp --syn -j LOG --log-level info --log-prefix "rejected connection: "
|
||||
''}
|
||||
${optionalString cfg.logRefusedPackets ''
|
||||
ip46tables -A FW_REFUSE -j LOG --log-level info --log-prefix "rejected packet: "
|
||||
''}
|
||||
|
||||
# The "nixos-fw-refuse" chain rejects or drops packets.
|
||||
ip46tables -N nixos-fw-refuse
|
||||
|
||||
${if cfg.rejectPackets then ''
|
||||
# Send a reset for existing TCP connections that we've
|
||||
# somehow forgotten about. Send ICMP "port unreachable"
|
||||
# for everything else.
|
||||
ip46tables -A FW_REFUSE -p tcp ! --syn -j REJECT --reject-with tcp-reset
|
||||
ip46tables -A FW_REFUSE -j REJECT
|
||||
ip46tables -A nixos-fw-refuse -p tcp ! --syn -j REJECT --reject-with tcp-reset
|
||||
ip46tables -A nixos-fw-refuse -j REJECT
|
||||
'' else ''
|
||||
ip46tables -A FW_REFUSE -j DROP
|
||||
ip46tables -A nixos-fw-refuse -j DROP
|
||||
''}
|
||||
|
||||
|
||||
# The "nixos-fw-log-refuse" chain performs logging, then
|
||||
# jumps to the "nixos-fw-refuse" chain.
|
||||
ip46tables -N nixos-fw-log-refuse
|
||||
|
||||
${optionalString cfg.logRefusedConnections ''
|
||||
ip46tables -A nixos-fw-log-refuse -p tcp --syn -j LOG --log-level info --log-prefix "rejected connection: "
|
||||
''}
|
||||
${optionalString (cfg.logRefusedPackets && !cfg.logRefusedUnicastsOnly) ''
|
||||
ip46tables -A nixos-fw-log-refuse -m pkttype --pkt-type broadcast \
|
||||
-j LOG --log-level info --log-prefix "rejected broadcast: "
|
||||
ip46tables -A nixos-fw-log-refuse -m pkttype --pkt-type multicast \
|
||||
-j LOG --log-level info --log-prefix "rejected multicast: "
|
||||
''}
|
||||
ip46tables -A nixos-fw-log-refuse -m pkttype ! --pkt-type unicast -j nixos-fw-refuse
|
||||
${optionalString cfg.logRefusedPackets ''
|
||||
ip46tables -A nixos-fw-log-refuse \
|
||||
-j LOG --log-level info --log-prefix "rejected packet: "
|
||||
''}
|
||||
ip46tables -A nixos-fw-log-refuse -j nixos-fw-refuse
|
||||
|
||||
|
||||
# The "nixos-fw" chain does the actual work.
|
||||
ip46tables -N nixos-fw
|
||||
|
||||
# Accept all traffic on the loopback interface.
|
||||
ip46tables -A INPUT -i lo -j ACCEPT
|
||||
ip46tables -A nixos-fw -i lo -j nixos-fw-accept
|
||||
|
||||
# Accept packets from established or related connections.
|
||||
ip46tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept
|
||||
|
||||
# Accept connections to the allowed TCP ports.
|
||||
${concatMapStrings (port:
|
||||
''
|
||||
ip46tables -A INPUT -p tcp --dport ${toString port} -j ACCEPT
|
||||
ip46tables -A nixos-fw -p tcp --dport ${toString port} -j nixos-fw-accept
|
||||
''
|
||||
) cfg.allowedTCPPorts
|
||||
}
|
||||
@ -175,39 +237,42 @@ in
|
||||
# Accept packets on the allowed UDP ports.
|
||||
${concatMapStrings (port:
|
||||
''
|
||||
ip46tables -A INPUT -p udp --dport ${toString port} -j ACCEPT
|
||||
ip46tables -A nixos-fw -p udp --dport ${toString port} -j nixos-fw-accept
|
||||
''
|
||||
) cfg.allowedUDPPorts
|
||||
}
|
||||
|
||||
# Accept IPv4 multicast. Not a big security risk since
|
||||
# probably nobody is listening anyway.
|
||||
iptables -A INPUT -d 224.0.0.0/4 -j ACCEPT
|
||||
#iptables -A nixos-fw -d 224.0.0.0/4 -j nixos-fw-accept
|
||||
|
||||
# Optionally respond to ICMPv4 pings.
|
||||
${optionalString cfg.allowPing ''
|
||||
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
|
||||
iptables -A nixos-fw -p icmp --icmp-type echo-request -j nixos-fw-accept
|
||||
''}
|
||||
|
||||
# Accept all ICMPv6 messages except redirects and node
|
||||
# information queries (type 139). See RFC 4890, section
|
||||
# 4.4.
|
||||
ip6tables -A INPUT -p icmpv6 --icmpv6-type redirect -j DROP
|
||||
ip6tables -A INPUT -p icmpv6 --icmpv6-type 139 -j DROP
|
||||
ip6tables -A INPUT -p icmpv6 -j ACCEPT
|
||||
ip6tables -A nixos-fw -p icmpv6 --icmpv6-type redirect -j DROP
|
||||
ip6tables -A nixos-fw -p icmpv6 --icmpv6-type 139 -j DROP
|
||||
ip6tables -A nixos-fw -p icmpv6 -j nixos-fw-accept
|
||||
|
||||
${cfg.extraCommands}
|
||||
|
||||
# Reject/drop everything else.
|
||||
ip46tables -A INPUT -j FW_REFUSE
|
||||
ip46tables -A nixos-fw -j nixos-fw-log-refuse
|
||||
|
||||
|
||||
# Enable the firewall.
|
||||
ip46tables -A INPUT -j nixos-fw
|
||||
'';
|
||||
|
||||
postStop =
|
||||
''
|
||||
iptables -F INPUT
|
||||
iptables -P INPUT ACCEPT
|
||||
ip6tables -F INPUT
|
||||
ip6tables -P INPUT ACCEPT
|
||||
${helpers}
|
||||
ip46tables -D INPUT -j nixos-fw || true
|
||||
#ip46tables -P INPUT ACCEPT
|
||||
'';
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user