at 17.09-beta 4.5 kB view raw
1{ config, pkgs, lib, ... }: 2with lib; 3let 4 cfg = config.networking.nftables; 5in 6{ 7 ###### interface 8 9 options = { 10 networking.nftables.enable = mkOption { 11 type = types.bool; 12 default = false; 13 description = 14 '' 15 Whether to enable nftables. nftables is a Linux-based packet 16 filtering framework intended to replace frameworks like iptables. 17 18 This conflicts with the standard networking firewall, so make sure to 19 disable it before using nftables. 20 21 Note that if you have Docker enabled you will not be able to use 22 nftables without intervention. Docker uses iptables internally to 23 setup NAT for containers. This module disables the ip_tables kernel 24 module, however Docker automatically loads the module. Please see [1] 25 for more information. 26 27 There are other programs that use iptables internally too, such as 28 libvirt. 29 30 [1]: https://github.com/NixOS/nixpkgs/issues/24318#issuecomment-289216273 31 ''; 32 }; 33 networking.nftables.ruleset = mkOption { 34 type = types.lines; 35 example = '' 36 # Check out https://wiki.nftables.org/ for better documentation. 37 # Table for both IPv4 and IPv6. 38 table inet filter { 39 # Block all incomming connections traffic except SSH and "ping". 40 chain input { 41 type filter hook input priority 0; 42 43 # accept any localhost traffic 44 iifname lo accept 45 46 # accept traffic originated from us 47 ct state {established, related} accept 48 49 # ICMP 50 # routers may also want: mld-listener-query, nd-router-solicit 51 ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept 52 ip protocol icmp icmp type { destination-unreachable, router-advertisement, time-exceeded, parameter-problem } accept 53 54 # allow "ping" 55 ip6 nexthdr icmp icmpv6 type echo-request accept 56 ip protocol icmp icmp type echo-request accept 57 58 # accept SSH connections (required for a server) 59 tcp dport 22 accept 60 61 # count and drop any other traffic 62 counter drop 63 } 64 65 # Allow all outgoing connections. 66 chain output { 67 type filter hook output priority 0; 68 accept 69 } 70 71 chain forward { 72 type filter hook forward priority 0; 73 accept 74 } 75 } 76 ''; 77 description = 78 '' 79 The ruleset to be used with nftables. Should be in a format that 80 can be loaded using "/bin/nft -f". The ruleset is updated atomically. 81 ''; 82 }; 83 networking.nftables.rulesetFile = mkOption { 84 type = types.path; 85 default = pkgs.writeTextFile { 86 name = "nftables-rules"; 87 text = cfg.ruleset; 88 }; 89 description = 90 '' 91 The ruleset file to be used with nftables. Should be in a format that 92 can be loaded using "nft -f". The ruleset is updated atomically. 93 ''; 94 }; 95 }; 96 97 ###### implementation 98 99 config = mkIf cfg.enable { 100 assertions = [{ 101 assertion = config.networking.firewall.enable == false; 102 message = "You can not use nftables with services.networking.firewall."; 103 }]; 104 boot.blacklistedKernelModules = [ "ip_tables" ]; 105 environment.systemPackages = [ pkgs.nftables ]; 106 systemd.services.nftables = { 107 description = "nftables firewall"; 108 before = [ "network-pre.target" ]; 109 wants = [ "network-pre.target" ]; 110 wantedBy = [ "multi-user.target" ]; 111 reloadIfChanged = true; 112 serviceConfig = let 113 rulesScript = pkgs.writeScript "nftables-rules" '' 114 #! ${pkgs.nftables}/bin/nft -f 115 flush ruleset 116 include "${cfg.rulesetFile}" 117 ''; 118 checkScript = pkgs.writeScript "nftables-check" '' 119 #! ${pkgs.stdenv.shell} -e 120 if $(${pkgs.kmod}/bin/lsmod | grep -q ip_tables); then 121 echo "Unload ip_tables before using nftables!" 1>&2 122 exit 1 123 else 124 ${rulesScript} 125 fi 126 ''; 127 in { 128 Type = "oneshot"; 129 RemainAfterExit = true; 130 ExecStart = checkScript; 131 ExecReload = checkScript; 132 ExecStop = "${pkgs.nftables}/bin/nft flush ruleset"; 133 }; 134 }; 135 }; 136}