Chains
nft add chain inet <table> input '{ type filter
hook input priority 0; policy drop; }'
Base chain on a hook
Hooks: prerouting, input, forward, output, postrouting. Policy
defaults to accept.
nft add chain inet <table> <chain>
Regular chain (jump target)
nft delete chain inet <table> <chain>
Delete an empty chain
nft flush chain inet <table> <chain>
Remove all rules in chain
nft rename chain inet <table> <chain>
<new>
Rename a chain
nft add chain inet <table> input '{ type filter
hook input priority 0; policy accept; }'
Change the policy (redeclare)
jump <chain> / goto <chain>
Continue in another chain
jump returns after the chain ends; goto does not.
Rules
nft add rule inet <table> <chain> <match>
<statement>
Append a rule
nft insert rule inet <table> <chain>
<match> <statement>
Insert at top of chain
nft add rule inet <table> <chain> position
<n> <rule>
Add after handle n
The position is a handle, not a line number. insert places
before it.
nft delete rule inet <table> <chain> handle
<n>
Delete a rule by handle
Get handles with nft -a list. Deleting by rule text is not
supported.
nft replace rule inet <table> <chain> handle
<n> <rule>
Replace a rule
nft add rule inet <table> input tcp dport 22
accept
Allow SSH
nft add rule inet <table> input tcp dport { 80, 443 }
accept
Allow several ports
nft add rule inet <table> input ip saddr 10.0.0.0/8
drop
Block a network
nft add rule inet <table> input iifname lo
accept
Allow loopback
nft add rule inet <table> input ct state
established,related accept
Allow replies
nft add rule inet <table> input ct state invalid
drop
Drop invalid packets
nft add rule inet <table> input icmp type
echo-request accept
Allow ping
Matches
ip saddr / ip daddr <addr>
IPv4 source / destination
ip6 saddr / ip6 daddr <addr>
IPv6 source / destination
tcp dport / udp dport <port>
Destination port
tcp sport <port>
Source port
tcp dport 1000-2000
Port range
tcp flags syn
TCP flag set
iifname "eth0" / oifname "eth0"
Interface by name
Wildcard works: iifname "eth*". Use iif / oif for an
interface that always exists.
meta l4proto tcp
Transport protocol
ct state new
Connection tracking state
<field> != <value>
Negate a match
<field> { a, b, c }
Match any of several values
Sets and maps
nft add set inet <table> <set> '{ type
ipv4_addr; }'
Create a named set
Types: ipv4_addr, ipv6_addr, ether_addr, inet_service,
inet_proto, mark, ifname.
nft add set inet <table> <set> '{ type
ipv4_addr; flags interval; }'
Set that holds ranges/CIDRs
nft add set inet <table> <set> '{ type
ipv4_addr; flags timeout; timeout 1h; }'
Set with expiring entries
nft add element inet <table> <set> { 1.2.3.4,
5.6.7.8 }
Add elements
nft delete element inet <table> <set> { 1.2.3.4
}
Remove an element
nft add rule inet <table> input ip saddr @<set>
drop
Use a set in a rule
nft list set inet <table> <set>
Show a set
nft get element inet <table> <set> { 1.2.3.4
}
Is it in the set?
nft add map ip nat <map> '{ type inet_service :
ipv4_addr; }'
Create a map
tcp dport vmap { 22 : accept, 23 : drop }
Verdict map in a rule
dnat to tcp dport map { 80 : 10.0.0.5, 8080 : 10.0.0.6
}
Port to host map for DNAT
NAT
nft add table ip nat
Table for NAT
nft add chain ip nat postrouting '{ type nat hook
postrouting priority 100; }'
Source NAT chain
nft add chain ip nat prerouting '{ type nat hook
prerouting priority -100; }'
Destination NAT chain
nft add rule ip nat postrouting oifname "eth0"
masquerade
Share an uplink
Needs IP forwarding: sysctl net.ipv4.ip_forward=1. Masquerade
suits dynamic addresses.
nft add rule ip nat postrouting ip saddr 192.168.1.0/24
snat to <ip>
Source NAT to fixed IP
nft add rule ip nat prerouting tcp dport 8080 dnat to
<ip>:80
Port forward to a host
Also accept the traffic in the forward chain if its policy is
drop.
nft add rule ip nat prerouting tcp dport 80 redirect to
:8080
Redirect to a local port
nft add rule inet nat prerouting dnat ip to
<ip>
DNAT in the inet family
In inet chains name the family: dnat ip to ... or dnat ip6 to
...