6c36d9fa20
reason: - We currently have an open discussion regarding a more modular firewall (https://github.com/NixOS/nixpkgs/issues/23181) and leaving null makes future extension easier. - the current default might not cover all use cases (different ssh port) and might break setups, if applied blindly
125 lines
3.9 KiB
Nix
125 lines
3.9 KiB
Nix
{ config, pkgs, lib, ... }:
|
|
with lib;
|
|
let
|
|
cfg = config.networking.nftables;
|
|
in
|
|
{
|
|
###### interface
|
|
|
|
options = {
|
|
networking.nftables.enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description =
|
|
''
|
|
Whether to enable nftables. nftables is a Linux-based packet
|
|
filtering framework intended to replace frameworks like iptables.
|
|
|
|
This conflicts with the standard networking firewall, so make sure to
|
|
disable it before using nftables.
|
|
'';
|
|
};
|
|
networking.nftables.ruleset = mkOption {
|
|
type = types.lines;
|
|
example = ''
|
|
# Check out https://wiki.nftables.org/ for better documentation.
|
|
# Table for both IPv4 and IPv6.
|
|
table inet filter {
|
|
# Block all incomming connections traffic except SSH and "ping".
|
|
chain input {
|
|
type filter hook input priority 0;
|
|
|
|
# accept any localhost traffic
|
|
iifname lo accept
|
|
|
|
# accept traffic originated from us
|
|
ct state {established, related} accept
|
|
|
|
# ICMP
|
|
# routers may also want: mld-listener-query, nd-router-solicit
|
|
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept
|
|
ip protocol icmp icmp type { destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept
|
|
|
|
# allow "ping"
|
|
ip6 nexthdr icmp icmpv6 type echo-request accept
|
|
ip protocol icmp icmp type echo-request accept
|
|
|
|
# accept SSH connections (required for a server)
|
|
tcp dport 22 accept
|
|
|
|
# count and drop any other traffic
|
|
counter drop
|
|
}
|
|
|
|
# Allow all outgoing connections.
|
|
chain output {
|
|
type filter hook output priority 0;
|
|
accept
|
|
}
|
|
|
|
chain forward {
|
|
type filter hook forward priority 0;
|
|
accept
|
|
}
|
|
}
|
|
'';
|
|
description =
|
|
''
|
|
The ruleset to be used with nftables. Should be in a format that
|
|
can be loaded using "/bin/nft -f". The ruleset is updated atomically.
|
|
'';
|
|
};
|
|
networking.nftables.rulesetFile = mkOption {
|
|
type = types.path;
|
|
default = pkgs.writeTextFile {
|
|
name = "nftables-rules";
|
|
text = cfg.ruleset;
|
|
};
|
|
description =
|
|
''
|
|
The ruleset file to be used with nftables. Should be in a format that
|
|
can be loaded using "nft -f". The ruleset is updated atomically.
|
|
'';
|
|
};
|
|
};
|
|
|
|
###### implementation
|
|
|
|
config = mkIf cfg.enable {
|
|
assertions = [{
|
|
assertion = config.networking.firewall.enable == false;
|
|
message = "You can not use nftables with services.networking.firewall.";
|
|
}];
|
|
boot.blacklistedKernelModules = [ "ip_tables" ];
|
|
environment.systemPackages = [ pkgs.nftables ];
|
|
systemd.services.nftables = {
|
|
description = "nftables firewall";
|
|
before = [ "network-pre.target" ];
|
|
wants = [ "network-pre.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
reloadIfChanged = true;
|
|
serviceConfig = let
|
|
rulesScript = pkgs.writeScript "nftables-rules" ''
|
|
#! ${pkgs.nftables}/bin/nft -f
|
|
flush ruleset
|
|
include "${cfg.rulesetFile}"
|
|
'';
|
|
checkScript = pkgs.writeScript "nftables-check" ''
|
|
#! ${pkgs.stdenv.shell} -e
|
|
if $(${pkgs.kmod}/bin/lsmod | grep -q ip_tables); then
|
|
echo "Unload ip_tables before using nftables!" 1>&2
|
|
exit 1
|
|
else
|
|
${rulesScript}
|
|
fi
|
|
'';
|
|
in {
|
|
Type = "oneshot";
|
|
RemainAfterExit = true;
|
|
ExecStart = checkScript;
|
|
ExecReload = checkScript;
|
|
ExecStop = "${pkgs.nftables}/bin/nft flush ruleset";
|
|
};
|
|
};
|
|
};
|
|
}
|