flush ruleset # remove all existing rules table inet firewall { chain input_ipv4 { # Accept ping (icmp-echo-request) for diagnostic purposes. Allows discover if host is alive. Accept with rate limit icmp type echo-request limit rate 5/minute burst 20 packets counter accept } chain input_ipv6 { # accept neighbour discovery otherwise connectivity breaks count the number of hits to this rule icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } counter accept # accepting ping (icmpv6-echo-request) for diagnostic purposes. icmpv6 type echo-request limit rate 5/second accept } 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; # Allow traffic from established and related packets, drop invalid, keep this! ct state vmap { established : accept, related : accept, invalid : drop } # Only for new connections iifname lo counter accept # Allow loopback traffic use name for counter # Jump to chain according to layer 3 protocol using a verdict map meta protocol vmap { ip : jump input_ipv4, ip6 : jump input_ipv6 } tcp dport { 22, 80, 443} counter accept # Allow SSH on port TCP/22 and allow HTTP(S) TCP/80 and TCP/443 limit rate over 10/minute counter drop # Drop packets with rate > 10/minute, needed to limit logging rate log prefix "[nftables] input Denied: " counter drop # Enable logging of remaining input traffic } chain forward { type filter hook forward priority 0; policy drop; # Drop everything (assumes this device is not a router) } # no need to define output chain, default policy is accept if undefined. }