nftables replaces the popular {ip,ip6,arp,eb}tables. This software provides a new in-kernel packet classification framework that is based on a network-specific Virtual Machine (VM) and a new nft userspace command line tool. nftables reuses the existing Netfilter subsystems such as the existing hook infrastructure, the connection tracking system, NAT, userspace queueing and logging subsystem.
<work in progress>
Basic Firewall
- ens192: Internal Interface
- ens224: External Interface
- includes docker entrires, remove these if you don’t want/need them
#!/usr/sbin/nft -f flush ruleset table inet filter { chain input { # By default, drop all traffic unless it meets a filter # criteria specified by the rules that follow below. type filter hook input priority 0; policy drop; # accept any localhost traffic iif lo accept iifname != lo ip daddr 127.0.0.1/8 counter log prefix "[nftables] drop connections to loopback not coming from loopback: " drop iifname != lo ip6 daddr ::1/128 counter log prefix "[nftables] drop connections to loopback not coming from loopback: " drop # accept trafic originated from us ct state {established, related} accept comment "Accept traffic originated from us" # early drop of invalid connections ct state invalid counter drop comment "Drop invalid connections" # mitigate ping floods ip protocol icmp icmp type {echo-reply, echo-request} limit rate over 7/second burst 4 packets drop ip6 nexthdr icmpv6 icmpv6 type {echo-reply, echo-request} limit rate over 7/second burst 4 packets drop # Allow following ICMPv4 ip protocol icmp icmp type { echo-reply, # type 0 destination-unreachable, # type 3 echo-request, # type 8 time-exceeded, # type 11 parameter-problem, # type 12 } accept \ comment "Accept basic IPv4 functionality" # Allow following ICMPv6 ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, # type 1 packet-too-big, # type 2 time-exceeded, # type 3 parameter-problem, # type 4 echo-request, # type 128 echo-reply, # type 129 } accept \ comment "Accept basic IPv6 functionality" # allow auto configuration support ip6 nexthdr icmpv6 icmpv6 type { nd-neighbor-solicit, # type 135 nd-neighbor-advert, # type 136 nd-router-advert, # type 134 nd-router-solicit # type 133 } ip6 hoplimit 255 accept; \ comment "Allow IPv6 sollicit" # allow link-local discovery # see https://ao2.it/it/blog/2018/04/27/nftables-experiments-icmpv6-hop-hop-options-header hbh nexthdr ipv6-icmp icmpv6 type { mld-listener-query, # type 130 mld-listener-report, # type 131 mld-listener-reduction, # type 132 mld2-listener-report, # type 143 } ip6 saddr fe80::/10 accept \ comment "Allow IPv6 multicast listener discovery on link-local" # allow multicast router discovery messages on link-local addresses (hop limit 1) ip6 nexthdr icmpv6 icmpv6 type { nd-router-advert, nd-router-solicit } ip6 hoplimit 1 ip6 saddr fe80::/10 accept; # accept ssh on internal interfaces, mitigate brute force login attempts iffname ens192 tcp dport ssh ct state new limit rate 7/minute counter log prefix "[nftables] accept ssh: " accept # log denied counter log prefix "[nftables] Inbound Denied: " } chain forward { # Drop everything (assumes this device is not a router) type filter hook forward priority 0; policy drop; # Uncomment to enable logging of denied forwards counter log prefix "[nftables] Forward Denied: " } chain output { # Allow all outbound traffic type filter hook output priority 0; policy accept; } chain DOCKER { } chain DOCKER-ISOLATION-STAGE-1 { iifname "docker0" oifname != "docker0" counter jump DOCKER-ISOLATION-STAGE-2 counter return } chain DOCKER-ISOLATION-STAGE-2 { oifname "docker0" counter drop counter return } chain DOCKER-USER { counter return } } table ip nat { chain PREROUTING { type nat hook prerouting priority -100; policy accept; fib daddr type local counter jump DOCKER } chain INPUT { type nat hook input priority 100; policy accept; } chain POSTROUTING { type nat hook postrouting priority 100; policy accept; oifname != "docker0" ip saddr 172.17.0.0/16 counter masquerade } chain OUTPUT { type nat hook output priority -100; policy accept; ip daddr != 127.0.0.0/8 fib daddr type local counter jump DOCKER } chain DOCKER { iifname "docker0" counter return } }