📙 Nftables#
Note
nftables is a subsystem of the Linux kernel providing filtering and classification of network packets/datagrams/frames.
nftables replaces the legacy iptables component of Netfilter.
Basic concepts#
table refers to a container of chains.
chain within a table refers to a container of rules.
rule refers to an action to be configured within a chain.
Table family#
ip, arp, ip6, bridge, inet, netdev
% nft list tables [<family>]
% nft list table [<family>] <name> [-n] [-a]
% nft (add | delete | flush) table [<family>] <name>
Netfilter hooks#

Chains#
type refers to the kind of chain : filter, route, nat.
hook refers to an specific stage.
priority refers to a number used to order the chains
% nft (add | create) chain [<family>] <table> <name> [ { type <type> hook <hook> [device <device>] priority <priority> \; [policy <policy> \;] } ]
% nft (delete | list | flush) chain [<family>] <table> <name>
% nft rename chain [<family>] <table> <name> <newname>
Rules#
% nft add rule [<family>] <table> <chain> <matches> <statements>
% nft insert rule [<family>] <table> <chain> [position <position>] <matches> <statements>
% nft replace rule [<family>] <table> <chain> [handle <handle>] <matches> <statements>
% nft delete rule [<family>] <table> <chain> [handle <handle>]
Configuring on Debian11#
Default#
systemctl status nftables.service
/etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
}
}
Load/Flush on service Start/Stop#
> grep Exec <(systemctl cat nftables.service)
ExecStart=/usr/sbin/nft -f /etc/nftables.conf
ExecReload=/usr/sbin/nft -f /etc/nftables.conf
ExecStop=/usr/sbin/nft flush ruleset
> nft list tables
table inet filter
> nft list ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Creating your own Table/Chain/Rule#
nft add table inet ipv4_filter
for i in input output forward; do nft add chain inet ipv4_filter "$i" { type filter hook "$i" priority 0 \; } ; done
nft add rule inet ipv4_filter input tcp dport 80 accept
nft add rule inet ipv4_filter input tcp dport 443 accept
nft add rule inet ipv4_filter input tcp dport 22 accept
nft add rule inet ipv4_filter input drop
nft add rule inet ipv4_filter output tcp sport 80 accept
nft add rule inet ipv4_filter output tcp sport 443 accept
nft add rule inet ipv4_filter output tcp sport 22 accept
nft add rule inet ipv4_filter output drop
Listing table/chain/rule#
root@debian01:~# nft -a list table inet ipv4_filter
table inet ipv4_filter { # handle 2
chain input { # handle 1
type filter hook input priority filter; policy accept;
tcp dport 80 accept # handle 5
tcp dport 443 accept # handle 6
tcp dport 22 accept # handle 7
drop # handle 8
}
chain output { # handle 2
type filter hook output priority filter; policy accept;
tcp sport 80 accept # handle 9
tcp sport 443 accept # handle 10
tcp sport 22 accept # handle 11
drop # handle 12
}
chain forward { # handle 3
type filter hook forward priority filter; policy accept;
}
}
root@debian01:~# nft -a list ruleset
table inet filter { # handle 1
chain input { # handle 1
type filter hook input priority filter; policy accept;
}
chain forward { # handle 2
type filter hook forward priority filter; policy accept;
}
chain output { # handle 3
type filter hook output priority filter; policy accept;
}
}
table inet ipv4_filter { # handle 2
chain input { # handle 1
type filter hook input priority filter; policy accept;
tcp dport 80 accept # handle 5
tcp dport 443 accept # handle 6
tcp dport 22 accept # handle 7
drop # handle 8
}
chain output { # handle 2
type filter hook output priority filter; policy accept;
tcp sport 80 accept # handle 9
tcp sport 443 accept # handle 10
tcp sport 22 accept # handle 11
drop # handle 12
}
chain forward { # handle 3
type filter hook forward priority filter; policy accept;
}
}
Edition mode#
nft --help | awk '/-[if]/'
-f, file <filename> Read input from <filename>
-i, interactive Read input from interactive CLI
Templates#
ls -C /usr/share/doc/nftables/examples
all-in-one.nft ipv4-filter.nft ipv6-nat.nft pf.os
arp-filter.nft ipv4-mangle.nft ipv6-raw.nft README
bridge-filter.nft ipv4-nat.nft load_balancing.nft secmark.nft
ct_helpers.nft ipv4-raw.nft nat.nft sets_and_maps.nft
inet-filter.nft ipv6-filter.nft netdev-ingress.nft sysvinit
inet-nat.nft ipv6-mangle.nft overview.nft workstation.nft
Web Server Filter#
cp /etc/nftables.conf{,.back_20220924}
/etc/nftables.conf
#!/usr/sbin/nft -f
# vim: ts=4:
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
ct state established,related accept
tcp dport http accept
tcp dport https accept
ip saddr 192.168.0.0/16 tcp dport 22 accept
ip saddr 192.168.122.16 tcp dport 5044 accept
tcp flags & (fin | syn | rst | psh | ack | urg) > urg counter packets 0 bytes 0
tcp flags & (fin | syn | rst | psh | ack | urg) < fin counter packets 0 bytes 0
icmp type echo-reply accept
drop
}
chain output {
type filter hook output priority 0;
ct state established,related accept
tcp dport http accept
tcp dport https accept
udp dport domain accept
udp dport ntp accept
tcp dport 587 accept
ip daddr 192.168.122.16 tcp dport 5044 accept
icmp type echo-request accept
drop
}
chain forward {
type filter hook forward priority filter; policy drop;
# Drop everything forwarded to us. We do not forward. That is routers job.
}
}
nft -f /etc/nftables.conf
nft flush ruleset
Source NAT#
Masquerade#
nft add table ip filt
nft add chain ip filt postrouting { type nat hook postrouting priority 0\; }
nft add rule ip filt postrouting masquerade
Unidirectional#
nft -a list table filt
nft delete rule ip filt postrouting handle 5
nft add rule ip filt postrouting ip saddr 192.168.122.0/24 oif enp1s0 snat 192.168.122.73
Destination NAT#
nft add table ip filt
nft add chain ip filt prerouting { type nat hook prerouting priority 0\; }
nft add rule ip filt prerouting iif enp1s0 tcp dport 21 dnat 192.168.122.73
nft -a list ruleset
nft delete rule ip filt prerouting handle 2
nft add rule ip filt prerouting iif enp1s0 tcp dport 2121 dnat 192.168.122.73:21