Nftables syntax
From wikinotes
Unlike iptables, nftables can be described in files.
- Tables are associated with a address-family (ip, arp, nat, ...), and contain chains of rules
- Packets are passed through chains of rules. This determines what to do with packets.
- Rules are composed of a matching-expression, and a statement that determines the action to be taken
The man page for nft is excellent, but I find it useful to also look at examples for more context.
Documentation
Documentation man 8 nftables (best) https://manpages.debian.org/testing/nftables/nft.8.en.html archwiki https://wiki.archlinux.org/index.php/Nftables ManPage Headers file syntax https://manpages.debian.org/testing/nftables/nft.8.en.html#INPUT_FILE_FORMATS conntrack types (state, status, ..) https://manpages.debian.org/testing/nftables/nft.8.en.html#CONNTRACK_TYPES expressions (ip, ct state, ...) https://manpages.debian.org/testing/nftables/nft.8.en.html#EXPRESSIONS statements (accept, drop, masquerade, ...) https://manpages.debian.org/testing/nftables/nft.8.en.html#STATEMENTS
Tutorials
netfilter logging framework https://home.regit.org/2014/02/nftables-and-netfilter-logging-framework/
Overview
- Tables hold chains. Tables are associated to an address-familiy (ip, ip6, arp, bridge, inet(ip+ip6).
- Chains contain collections of rules that traffic flows through. (ex: input, forward, output)
- Rules match traffic, and determine what to do with it. Their composition:
- expressions/constants defines target traffic (ex:
ct state established
,tcp port 22
)- statement determine action (ex:
accept, drop
)Example
# flush current rules on load flush ruleset table inet filter { chain input { policy drop; # ===== # RULES # ===== #{constant} {statement} tcp port 22 accept ip protocol icmp drop ip6 nexthdr icmpv6 drop #{expression} {statement} ct state established accept # conntrack }
Defaults
NOTE:
If using the default ruleset, you should probably prepend
flush ruleset
to the top so that your rules are reloaded every time.default
/etc/nftables.conf
#!/usr/bin/nft -f # ipv4/ipv6 Simple & Safe Firewall # you can find examples in /usr/share/nftables/ table inet filter { chain input { type filter hook input priority 0; policy drop; # allow established/related connections ct state {established, related} accept # early drop of invalid connections ct state invalid drop # allow from loopback iifname lo accept # allow icmp ip protocol icmp accept meta l4proto ipv6-icmp accept # allow ssh tcp dport ssh accept # everything else reject with icmpx type port-unreachable } chain forward { type filter hook forward priority 0; policy drop; } chain output { type filter hook output priority 0; policy accept; } } # vim:set ts=2 sw=2 et:
Include
You can include other nftable files.
include ./relative/path.conf include /absolute/path.conf include /widldcard/*.conf include repative/to/include/paths.conf # see nft --include-path
Variables
define int_if1 = eth0 define int_if2 = eth1 define mosh_ports = 60000-61000 define int_ifs = { $int_if1, $int_if2 } filter input iif $int_ifs accept
Rules
- Rules match traffic, and determine what to do with it. Their composition:
- expressions/constants defines target traffic (ex:
ct state established
,tcp port 22
)- statement determine action (ex:
accept, drop
)Expressions (matching)
expressions (all expression types) payload expressions tcp port 22
ip protocol icmp
conntrack types ct state {new, establishd}
ct event new
Cheatsheet
Originally taken from ArchWiki
meta: oif <output interface NAME/INDEX> iif <input interface NAME/INDEX> oifname <output interface NAME> # slower than oif, string matching iifname <input interface NAME> # slower than lif, string matching (oif and iif accept string arguments and are converted to interface indexes) (oifname and iifname are more dynamic, but slower because of string matching) icmp: type <icmp type> icmpv6: type <icmpv6 type> ip: protocol <protocol> daddr <destination address> saddr <source address> ip6: daddr <destination address> saddr <source address> tcp: dport <destination port> sport <source port> udp: dport <destination port> sport <source port> sctp: dport <destination port> sport <source port> ct: state <new | established | related | invalid># ========= # Constants # ========= tcp dport ssh #{statement} tcp dport {22, 33, 44} #{statement} ip protocol icmp #{statement} ip6 nexthdr icmpv6 #{statement} ct state invalid #{statement} ct state {established, related} #{statement} # ========================= # Constants can be Combined # ========================= udp sport 1900 \ udp dport >= 1024 \ ip6 saddr { fd00::/8, fe80::/10 } \ meta pkttype unicast limit rate 4/second burst 20 packets \ accept \ comment "Accept UPnP IGD port mapping reply"Examples
iif lo accept \ comment "accept everything on lo" udp dport 53 accept \ comment "simple protocol based rule" tcp sport 2222 ip saddr 1.1.1.1 ip daddr 2.2.2.2 accept \ comment "rule with src host/port and dest host"Statements
statements verdict statements accept
drop
nat statements masquerade
(rewrite source addr to appear from here)redirect to 8888
fwd statements fwd to eth0
log statements
nftables logginglog prefix "strange behaviour: " level "info"
limit statements limit rate over 10/second <statement>
Examples