The Funtoo Linux project has transitioned to "Hobby Mode" and this wiki is now read-only.
Package:Nftables
Nftables
We welcome improvements to this page. To edit this page, Create a Funtoo account. Then log in and then click here to edit this page. See our editing guidelines to becoming a wiki-editing pro.
What is nftables?
nftables is the successor to iptables. It replaces the existing iptables, ip6tables, arptables and ebtables framework. It uses the Linux kernel and a new userspace utility called nft. nftables provides a compatibility layer for the ip(6)tables and framework.
Introduction
As with the iptables framework, nftables is build upon rules which specify the actions. These rules are attached to chains. A chain can contain a collection of rules and is registered into the netfilter hooks. Chains are stored inside tables. A table is specific for one of the layer 3 protocols. One of the main differences with iptables is that there are no predefined tables and chains anymore.
Tables
A table is nothing more than a container for your chains. With nftables there are no predefined tables (filter, raw, mangle...) anymore. You are free to recreate the iptables-like structure, but anything might do. Currently there are 5 different families of tables:
- ip: Used for IPv4 related chains;
- ip6: Used for IPv6 related chains;
- arp: Used for ARP related chains;
- bridge: Used for bridging related chains;
- inet: Mixed ipv4/ipv6 chains (kernel 3.14 and up).
It is not hard to recognize the old tables framework in these tables. The only new one is the inet table which is used for both IPv4 and IPv6 traffic. It should make firewalling for dual-stack hosts easier by combining the rules for IPv4 and IPv6.
Chains
Chains are used to group together rules. As with the tables, nftables does not have any predefined chains. Chains are grouped in base and non-base types. Base chains are registered in one of the netfilter hooks. A base chain has a hook its registered with, a type and a priority. Non-base chains are not attached to a hook and they don't see any traffic by default. They can be used to arrange a rule-set in a tree of chains. There are currently three types of chains:
- filter: for filtering packets
- route: for rerouting packets
- nat: for performing Network Address Translation. Only the first packet of a flow hits this chain, making it impossible to use it for filtering.
The hooks that can be used are:
- prerouting: This is before the routing decision, all packets entering the machine hits this chain
- input: All packets for the local system hits this hook
- forward: Packets not for the local system, those that need to be forwarded hits this hook
- output: Packets that originate from the local system pass this hook
- postrouting: This hook is after the routing decision, all packets leaving the machine hits this chain
The ARP address family only supports the input and output hook
The bridge address family only seems to supports the input, forward and output hook
Priorities
Priorities do not currently appear to have any effect on which chain sees packets first.
Since the priority seems to be an unsigned integer, negative priorities will be converted into very high priorities.
Rules
Rules specify which action has to be taken for which packets. Rules are attached to chains. Each rule can has an expression to match packets with and one or multiple actions when matching. Main differences with iptables is that it is possible to specify multiple actions and that by default counters are off. It must be specified explicitly in rules if you want packet- and byte-counters for a rule. Each rule has a unique handle number by which it can be distinguished. The following matches are available:
- ip: IP protocol
- ip6: IPv6 protocol
- tcp: TCP protocol
- udp: UDP protocol
- udplite: UDP-lite protocol
- sctp: SCTP protocol
- dccp: DCCP protocol
- ah: Authentication headers
- esp: Encrypted security payload headers
- ipcomp: IPcomp headers
- icmp: icmp protocol
- icmpv6: icmpv6 protocol
- ct: Connection tracking
- meta: meta properties such as interfaces
Matches
Match | Arguments | Description/Example |
ip | version | Ip Header version |
hdrlength | IP header length | |
tos | Type of Service | |
length | Total packet length | |
id | IP ID | |
frag-off | Fragmentation offset | |
ttl | Time to live | |
protocol | Upper layer protocol | |
checksum | IP header checksum | |
saddr | Source address | |
daddr | Destination address | |
ip6 | version | IP header version |
priority | ||
flowlabel | Flow label | |
length | Payload length | |
nexthdr | Next header type (Upper layer protocol number) | |
hoplimit | Hop limit | |
saddr | Source Address | |
daddr | Destination Address | |
tcp | sport | Source port |
dport | Destination port | |
sequence | Sequence number | |
ackseq | Acknowledgement number | |
doff | Data offset | |
flags | TCP flags | |
window | Window | |
checksum | Checksum | |
urgptr | Urgent pointer | |
udp | sport | Source port |
dport | destination port | |
length | Total packet length | |
checksum | Checksum | |
udplite | sport | Source port |
dport | destination port | |
cscov | Checksum coverage | |
checksum | Checksum | |
sctp | sport | Source port |
dport | destination port | |
vtag | Verification tag | |
checksum | Checksum | |
dccp | sport | Source port |
dport | destination port | |
ah | nexthdr | Next header protocol (Upper layer protocol) |
hdrlength | AH header length | |
spi | Security Parameter Index | |
sequence | Sequence Number | |
esp | spi | Security Parameter Index |
sequence | Sequence Number | |
ipcomp | nexthdr | Next header protocol (Upper layer protocol) |
flags | Flags | |
cfi | Compression Parameter Index | |
icmp | type | icmp packet type |
icmpv6 | type | icmpv6 packet type |
ct | state | State of the connection |
direction | Direction of the packet relative to the connection | |
status | Status of the connection | |
mark | Connection mark | |
expiration | Connection expiration time | |
helper | Helper associated with the connection | |
l3proto | Layer 3 protocol of the connection | |
saddr | Source address of the connection for the given direction | |
daddr | Destination address of the connection for the given direction | |
protocol | Layer 4 protocol of the connection for the given direction | |
proto-src | Layer 4 protocol source for the given direction | |
proto-dst | Layer 4 protocol destination for the given direction | |
meta | length | Length of the packet in bytes: meta length > 1000 |
protocol | ethertype protocol: meta protocol vlan | |
priority | TC packet priority | |
mark | Packet mark | |
iif | Input interface index | |
iifname | Input interface name | |
iiftype | Input interface type | |
oif | Output interface index | |
oifname | Output interface name | |
oiftype | Output interface hardware type | |
skuid | UID associated with originating socket | |
skgid | GID associated with originating socket | |
rtclassid | Routing realm |
Statements
Statements represent the action to be performed when the rule matches. They exist in two kinds: Terminal statements, unconditionally terminate the evaluation of the current rules and non-terminal statements that either conditionally or never terminate the current rules. There can be an arbitrary amount of non-terminal statements, but there must be only a single terminal statement. The terminal statements can be:
- accept: Accept the packet and stop the ruleset evaluation.
- drop: Drop the packet and stop the ruleset evaluation.
- reject: Reject the packet with an icmp message
- queue: Queue the packet to userspace and stop the ruleset evaluation.
- continue:
- return: Return from the current chain and continue at the next rule of the last chain. In a base chain it is equivalent to accept
- jump <chain>: Continue at the first rule of <chain>. It will continue at the next rule after a return statement is issued
- goto <chain>: Similar to jump, but after the new chain the evaluation will continue at the last chain instead of the one containing the goto statement
Installing nftables
Kernel
These kernel options must be set Under Network support:
Networking options [*] Network packet filtering framework (Netfilter) ---> Core Netfilter Configuration ---> <M> Netfilter nf_tables support <M> Netfilter nf_tables IPv6 exthdr module <M> Netfilter nf_tables meta module <M> Netfilter nf_tables conntrack module <M> Netfilter nf_tables rbtree set module <M> Netfilter nf_tables hash set module <M> Netfilter nf_tables counter module <M> Netfilter nf_tables log module <M> Netfilter nf_tables limit module <M> Netfilter nf_tables nat module <M> Netfilter x_tables over nf_tables module <M> Netfilter nf_tables set infrastructure IP: Netfilter Configuration ---> <M> IPv4 nf_tables support <M> nf_tables IPv4 reject support <M> IPv4 nf_tables route chain support <M> IPv4 nf_tables nat chain support IPv6: Netfilter Configuration ---> <M> IPv6 nf_tables support <M> IPv6 nf_tables route chain support <M> IPv6 nf_tables nat chain support <M> Ethernet Bridge nf_tables support
Emerging
To install nftables, run the following command:
root # emerge net-firewall/nftables
OpenRC configuration
Don't forget to add nftables service to startup:
root # rc-update add nftables default
You cannot use iptables and nft to perform NAT at the same time. So make sure that the iptable_nat module is unloaded. But, using nf nat and iptables nat at same time is supported only as of kernel 4.18. If you use kernel older than 4.18, please remove iptables_nat module:
root # rmmod iptable_nat
First create some rules then run:
root # rc-service nftables save
Start nftables:
root # /etc/init.d/nftables start
Using nftables
All nftable commands are done with the nft ultility from net-firewall/nftables.
Tables
Creating tables
The following command adds a table called filter for the ip(v4) layer
root # nft add table ip filter
Likewise a table for arp can be created with
root # nft add table arp filter
The name "filter" used here is completly arbitrary. It could have any name
Listing tables
The following command lists all tables for the ip(v4) layer
root # nft list tables ip
table filter
The contents of the table filter can be listed with:
root # nft list table ip filter
table ip filter { chain input { type filter hook input priority 0; ct state established,related accept iifname "lo" accept ip protocol icmp accept drop } }
using -a with the nft command, it shows the handle of each rule. Handles are used for various operations on specific rules:
root # nft -a list table ip filter
table ip filter { chain input { type filter hook input priority 0; ct state established,related accept # handle 2 iifname "lo" accept # handle 3 ip protocol icmp accept # handle 4 drop # handle 5 } }
Deleting tables
The following command deletes the table called filter for the ip(v4) layer:
root # nft delete table ip filter
chains
Adding chains
The following command adds a chain called input to the ip filter table and registered to the input hook with priority 0. It is of the type filter.
root # nft add chain ip filter input { type filter hook input priority 0 \; }
If You're running this command from Bash you need to escape the semicolon
A non-base chain can be added by not specifying the chain configurations between the curly braces.
Removing chains
The following command deletes the chain called input
root # nft delete chain ip filter input
Chains can only be deleted if there are no rules in them.
rules
Adding rules
The following command adds a rule to the chain called input, on the ip filter table, dropping all traffic to port 80:
root # nft add rule ip filter input tcp dport 80 drop
Deleting Rules
To delete a rule, you first need to get the handle number of the rule. This can be done by using the -a flag on nft:
root # nft rule ip filter input tcp dport 80 drop
table ip filter { chain input { type filter hook input priority 0; tcp dport http drop # handle 2 } }
It is then possible to delete the rule with:
root # nft delete rule ip filter input handle 2
Management
Backup
You can also backup your rules:
root # echo "nft flush ruleset" > backup.nft
root # nft list ruleset >> backup.nft
Restoration
And load it atomically:
root # nft -f backup.nft
OpenRC configuration
Don't forget to add nftables service to startup:
root # rc-update add nftables default
Init script
Firewall nftables like a iptables:
#!/sbin/runscript # Raphael Bastos aka coffnix # # Init Script for Funtoo Linux # ########################################## depend() { need net need nftables } start(){ ##################### PARTE 1 ##################### ebegin "Starting Firewall NFTables" ####################################################################### ### Incompatibilities ### # You cannot use iptables and nft to perform NAT at the same time. # So make sure that the iptable_nat module is unloaded rmmod iptable_nat ####################################################################### echo 1 > /proc/sys/net/ipv4/ip_forward echo 1 > /proc/sys/net/ipv4/ip_dynaddr echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done ####################################################################### iptables -t nat -F ####################################################################### # ipv4 nft -f /etc/nftables/ipv4-filter # ipv4 nat nft -f /etc/nftables/ipv4-nat # ipv6 nft -f /etc/nftables/ipv6-filter # Rules firewall NTFtables nft -f /etc/nftables/firewall.rules ####################################################################### } stop(){ ebegin "Stoping Firewall NFTables" nft flush ruleset } status(){ nft list ruleset } # End
Personal Rules
And configure your personal rules:
/etc/nftables/firewall.rules
# A simple firewall # table ip filter { chain input { type filter hook input priority 0; ct state established,related accept ct state invalid drop # invalid connections iifname "lo" accept # loopback interface ip daddr 127.0.0.0/8 accept ip protocol icmp accept ip protocol gre accept tcp dport {8888, http} accept # open ports ip saddr 8.28.87.174 ct state new counter accept # Funtoo Host udp sport 53 accept ip daddr 192.168.100.0/24 accept ip daddr 192.168.200.0/24 accept ip daddr 192.168.5.0/24 accept ip saddr 192.168.5.0/24 accept drop # everything else } chain forward { ip daddr 127.0.0.0/8 accept ip daddr 192.168.100.0/24 accept ip daddr 192.168.5.0/24 accept ip daddr 192.168.200.0/24 accept } } table ip6 filter { chain input { type filter hook input priority 0; # established/related connections ct state established,related accept # invalid connections ct state invalid drop # loopback interface iifname lo accept ip6 saddr ::1 accept # icmp ip6 nexthdr icmpv6 accept # open tcp ports: sshd (22), httpd (80) #tcp dport 22 accept #open tcp ports: httpd (80) tcp dport {http} accept udp dport {5060} accept udp dport {4000-20000} accept # everything else drop } } table ip nat { chain pre-briding { type nat hook prerouting priority 0; tcp dport 8888 ip saddr hq.lns.com.br ip protocol tcp counter dnat 192.168.200.100:22 #acesso rasp-2 via ssh #tcp dport 8080 ip protocol tcp counter dnat 192.168.100.24 } chain post-bridging { type nat hook postrouting priority 0; #ip saddr 192.168.200.0/24 oif wlan0 snat 192.168.100.20 ip saddr 192.168.200.0/24 masquerade } }
Version 0.4 and earlier does not have the functionality "flush". If you use older versions proceed as follows to clean the tables:
NFT=nft FAMILIES="ip ip6 arp bridge" for FAMILY in $FAMILIES; do TABLES=$($NFT list tables $FAMILY | grep "^table\s" | cut -d' ' -f2) for TABLE in $TABLES; do CHAINS=$($NFT list table $FAMILY $TABLE | grep "^\schain\s" | cut -d' ' -f2) for CHAIN in $CHAINS; do echo "Flushing chain: $FAMILY->$TABLE->$CHAIN" $NFT flush chain $FAMILY $TABLE $CHAIN $NFT delete chain $FAMILY $TABLE $CHAIN done echo "Flushing table: $FAMILY->$TABLE" $NFT flush table $FAMILY $TABLE $NFT delete table $FAMILY $TABLE done done
If you use version 0.5 or higher use the new feature:
root # nft flush ruleset