Menu Close
Red Hat Training
A Red Hat training course is available for RHEL 8
Chapter 8. Getting started with nftables
The nftables
framework provides packet classification facilities. The most notable features are:
- built-in lookup tables instead of linear processing
-
a single framework for both the
IPv4
andIPv6
protocols - rules all applied atomically instead of fetching, updating, and storing a complete rule set
-
support for debugging and tracing in the rule set (
nftrace
) and monitoring trace events (in thenft
tool) - more consistent and compact syntax, no protocol-specific extensions
- a Netlink API for third-party applications
The nftables
framework uses tables to store chains. The chains contain individual rules for performing actions. The libnftnl
library can be used for low-level interaction with nftables
Netlink API over the libmnl
library.
To display the effect of rule set changes, use the nft list ruleset
command. Since these tools add tables, chains, rules, sets, and other objects to the nftables
rule set, be aware that nftables
rule-set operations, such as the nft flush ruleset
command, might affect rule sets installed using the formerly separate legacy commands.
8.1. Migrating from iptables to nftables
If your firewall configuration still uses iptables
rules, you can migrate your iptables
rules to nftables
.
8.1.1. When to use firewalld, nftables, or iptables
The following is a brief overview in which scenario you should use one of the following utilities:
-
firewalld
: Use thefirewalld
utility for simple firewall use cases. The utility is easy to use and covers the typical use cases for these scenarios. -
nftables
: Use thenftables
utility to set up complex and performance critical firewalls, such as for a whole network. -
iptables
: Theiptables
utility on Red Hat Enterprise Linux uses thenf_tables
kernel API instead of thelegacy
back end. Thenf_tables
API provides backward compatibility so that scripts that useiptables
commands still work on Red Hat Enterprise Linux. For new firewall scripts, Red Hat recommends to usenftables
.
To avoid that the different firewall services influence each other, run only one of them on a RHEL host, and disable the other services.
8.1.2. Converting iptables rules to nftables rules
Red Hat Enterprise Linux provides the iptables-translate
and ip6tables-translate
tools to convert existing iptables
or ip6tables
rules into the equivalent ones for nftables
.
Note that some extensions lack translation support. If such an extension exists, the tool prints the untranslated rule prefixed with the #
sign. For example:
# iptables-translate -A INPUT -j CHECKSUM --checksum-fill nft # -A INPUT -j CHECKSUM --checksum-fill
Additionally, users can use the iptables-restore-translate
and ip6tables-restore-translate
tools to translate a dump of rules. Note that before that, users can use the iptables-save
or ip6tables-save
commands to print a dump of current rules. For example:
# iptables-save >/tmp/iptables.dump # iptables-restore-translate -f /tmp/iptables.dump # Translated by iptables-restore-translate v1.8.0 on Wed Oct 17 17:00:13 2018 add table ip nat ...
For more information and a list of possible options and values, enter the iptables-translate --help
command.
8.1.3. Comparison of common iptables and nftables commands
The following is a comparison of common iptables
and nftables
commands:
Listing all rules:
iptables nftables iptables-save
nft list ruleset
Listing a certain table and chain:
iptables nftables iptables -L
nft list table ip filter
iptables -L INPUT
nft list chain ip filter INPUT
iptables -t nat -L PREROUTING
nft list chain ip nat PREROUTING
The
nft
command does not pre-create tables and chains. They exist only if a user created them manually.Example: Listing rules generated by firewalld
#
nft list table inet firewalld
#nft list table ip firewalld
#nft list table ip6 firewalld
8.2. Writing and executing nftables scripts
The nftables
framework provides a native scripting environment that brings a major benefit over using shell scripts to maintain firewall rules: the execution of scripts is atomic. This means that the system either applies the whole script or prevents the execution if an error occurs. This guarantees that the firewall is always in a consistent state.
Additionally, the nftables
script environment enables administrators to:
- add comments
- define variables
- include other rule set files
This section explains how to use these features, as well as creating and executing nftables
scripts.
When you install the nftables
package, Red Hat Enterprise Linux automatically creates *.nft
scripts in the /etc/nftables/
directory. These scripts contain commands that create tables and empty chains for different purposes.
8.2.1. Supported nftables script formats
The nftables
scripting environment supports scripts in the following formats:
You can write a script in the same format as the
nft list ruleset
command displays the rule set:#!/usr/sbin/nft -f # Flush the rule set flush ruleset table inet example_table { chain example_chain { # Chain for incoming packets that drops all packets that # are not explicitly allowed by any rule in this chain type filter hook input priority 0; policy drop; # Accept connections to port 22 (ssh) tcp dport ssh accept } }
You can use the same syntax for commands as in
nft
commands:#!/usr/sbin/nft -f # Flush the rule set flush ruleset # Create a table add table inet example_table # Create a chain for incoming packets that drops all packets # that are not explicitly allowed by any rule in this chain add chain inet example_table example_chain { type filter hook input priority 0 ; policy drop ; } # Add a rule that accepts connections to port 22 (ssh) add rule inet example_table example_chain tcp dport ssh accept
8.2.2. Running nftables scripts
You can run nftables
script either by passing it to the nft
utility or execute the script directly.
Prerequisites
-
The procedure of this section assumes that you stored an
nftables
script in the/etc/nftables/example_firewall.nft
file.
Procedure
To run an
nftables
script by passing it to thenft
utility, enter:#
nft -f /etc/nftables/example_firewall.nft
To run an
nftables
script directly:Steps that are required only once:
Ensure that the script starts with the following shebang sequence:
#!/usr/sbin/nft -f
ImportantIf you omit the
-f
parameter, thenft
utility does not read the script and displays:Error: syntax error, unexpected newline, expecting string
.Optional: Set the owner of the script to
root
:#
chown root /etc/nftables/example_firewall.nft
Make the script executable for the owner:
#
chmod u+x /etc/nftables/example_firewall.nft
Run the script:
#
/etc/nftables/example_firewall.nft
If no output is displayed, the system executed the script successfully.
Even if nft
executes the script successfully, incorrectly placed rules, missing parameters, or other problems in the script can cause that the firewall behaves not as expected.
Additional resources
-
chown(1)
man page -
chmod(1)
man page - Automatically loading nftables rules when the system boots
8.2.3. Using comments in nftables scripts
The nftables
scripting environment interprets everything to the right of a #
character as a comment.
Example 8.1. Comments in an nftables script
Comments can start at the beginning of a line, as well as next to a command:
... # Flush the rule set flush ruleset add table inet example_table # Create a table ...
8.2.4. Using variables in an nftables script
To define a variable in an nftables
script, use the define
keyword. You can store single values and anonymous sets in a variable. For more complex scenarios, use sets or verdict maps.
- Variables with a single value
The following example defines a variable named
INET_DEV
with the valueenp1s0
:define INET_DEV = enp1s0
You can use the variable in the script by writing the
$
sign followed by the variable name:... add rule inet example_table example_chain iifname $INET_DEV tcp dport ssh accept ...
- Variables that contain an anonymous set
The following example defines a variable that contains an anonymous set:
define DNS_SERVERS = { 192.0.2.1, 192.0.2.2 }
You can use the variable in the script by writing the
$
sign followed by the variable name:add rule inet example_table example_chain ip daddr $DNS_SERVERS accept
NoteNote that curly braces have special semantics when you use them in a rule because they indicate that the variable represents a set.
Additional resources
8.2.5. Including files in an nftables script
The nftables
scripting environment enables administrators to include other scripts by using the include
statement.
If you specify only a file name without an absolute or relative path, nftables
includes files from the default search path, which is set to /etc
on Red Hat Enterprise Linux.
Example 8.2. Including files from the default search directory
To include a file from the default search directory:
include "example.nft"
Example 8.3. Including all *.nft files from a directory
To include all files ending with *.nft
that are stored in the /etc/nftables/rulesets/
directory:
include "/etc/nftables/rulesets/*.nft"
Note that the include
statement does not match files beginning with a dot.
Additional resources
-
The
Include files
section in thenft(8)
man page
8.2.6. Automatically loading nftables rules when the system boots
The nftables
systemd service loads firewall scripts that are included in the /etc/sysconfig/nftables.conf
file. This section explains how to load firewall rules when the system boots.
Prerequisites
-
The
nftables
scripts are stored in the/etc/nftables/
directory.
Procedure
Edit the
/etc/sysconfig/nftables.conf
file.-
If you enhance
*.nft
scripts created in/etc/nftables/
when you installed thenftables
package, uncomment theinclude
statement for these scripts. If you write scripts from scratch, add
include
statements to include these scripts. For example, to load the/etc/nftables/example.nft
script when thenftables
service starts, add:include "/etc/nftables/example.nft"
-
If you enhance
Optionally, start the
nftables
service to load the firewall rules without rebooting the system:# systemctl start nftables
Enable the
nftables
service.# systemctl enable nftables
Additional resources
8.3. Creating and managing nftables tables, chains, and rules
This section explains how to display nftables
rule sets, and how to manage them.
8.3.1. Standard chain priority values and textual names
When you create a chain, the priority
you can either set an integer value or a standard name that specifies the order in which chains with the same hook
value traverse.
The names and values are defined based on what priorities are used by xtables
when registering their default chains.
The nft list chains
command displays textual priority values by default. You can view the numeric value by passing the -y
option to the command.
Example 8.4. Using a textual value to set the priority
The following command creates a chain named example_chain
in example_table
using the standard priority value 50
:
# nft add chain inet example_table example_chain { type filter hook input priority 50 \; policy accept \; }
Because the priority is a standard value, you can alternatively use the textual value:
# nft add chain inet example_table example_chain { type filter hook input priority security \; policy accept \; }
Table 8.1. Standard priority names, family, and hook compatibility matrix
Name | Value | Families | Hooks |
---|---|---|---|
| -300 |
| all |
| -150 |
| all |
| -100 |
| prerouting |
| 0 |
| all |
| 50 |
| all |
| 100 |
| postrouting |
All families use the same values, but the bridge
family uses following values:
Table 8.2. Standard priority names, and hook compatibility for the bridge family
Name | Value | Hooks |
---|---|---|
| -300 | prerouting |
| -200 | all |
| 100 | output |
| 300 | postrouting |
Additional resources
-
The
Chains
section in thenft(8)
man page
8.3.2. Displaying the nftables rule set
The rule sets of nftables
contain tables, chains, and rules. This section explains how to display the rule set.
Procedure
To display the rule set, enter:
# nft list ruleset table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport http accept tcp dport ssh accept } }
NoteBy default,
nftables
does not pre-create tables. As a consequence, displaying the rule set on a host without any tables, thenft list ruleset
command shows no output.
8.3.3. Creating an nftables table
A table in nftables
is a name space that contains a collection of chains, rules, sets, and other objects. This section explains how to create a table.
Each table must have an address family defined. The address family of a table defines what address types the table processes. You can set one of the following address families when you create a table:
-
ip
: Matches only IPv4 packets. This is the default if you do not specify an address family. -
ip6
: Matches only IPv6 packets. -
inet
: Matches both IPv4 and IPv6 packets. -
arp
: Matches IPv4 address resolution protocol (ARP) packets. -
bridge
: Matches packets that traverse a bridge device. -
netdev
: Matches packets from ingress.
Procedure
Use the
nft add table
command to create a new table. For example, to create a table namedexample_table
that processes IPv4 and IPv6 packets:# nft add table inet example_table
Optionally, list all tables in the rule set:
# nft list tables table inet example_table
Additional resources
-
The
Address families
section in thenft(8)
man page -
The
Tables
section in thenft(8)
man page
8.3.4. Creating an nftables chain
Chains are containers for rules. The following two rule types exists:
- Base chain: You can use base chains as an entry point for packets from the networking stack.
-
Regular chain: You can use regular chains as a
jump
target and to better organize rules.
The procedure describes how to add a base chain to an existing table.
Prerequisites
- The table to which you want to add the new chain exists.
Procedure
Use the
nft add chain
command to create a new chain. For example, to create a chain namedexample_chain
inexample_table
:# nft add chain inet example_table example_chain { type filter hook input priority 0 \; policy accept \; }
ImportantTo avoid that the shell interprets the semicolons as the end of the command, prepend the semicolons the
\
escape character.This chain filters incoming packets. The
priority
parameter specifies the order in whichnftables
processes chains with the same hook value. A lower priority value has precedence over higher ones. Thepolicy
parameter sets the default action for rules in this chain. Note that if you are logged in to the server remotely and you set the default policy todrop
, you are disconnected immediately if no other rule allows the remote access.Optionally, display all chains:
# nft list chains table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; } }
Additional resources
-
The
Address families
section in thenft(8)
man page -
The
Chains
section in thenft(8)
man page
8.3.5. Appending a rule to the end of an nftables chain
This section explains how to append a rule to the end of an existing nftables
chain.
Prerequisites
- The chain to which you want to add the rule exists.
Procedure
To add a new rule, use the
nft add rule
command. For example, to add a rule to theexample_chain
in theexample_table
that allows TCP traffic on port 22:# nft add rule inet example_table example_chain tcp dport 22 accept
Instead of the port number, you can alternatively specify the name of the service. In the example, you could use
ssh
instead of the port number22
. Note that a service name is resolved to a port number based on its entry in the/etc/services
file.Optionally, display all chains and their rules in
example_table
:# nft list table inet example_table table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; ... tcp dport ssh accept } }
Additional resources
-
The
Address families
section in thenft(8)
man page -
The
Rules
section in thenft(8)
man page
8.3.6. Inserting a rule at the beginning of an nftables chain
This section explains how to insert a rule at the beginning of an existing nftables
chain.
Prerequisites
- The chain to which you want to add the rule exists.
Procedure
To insert a new rule, use the
nft insert rule
command. For example, to insert a rule to theexample_chain
in theexample_table
that allows TCP traffic on port 22:# nft insert rule inet example_table example_chain tcp dport 22 accept
You can alternatively specify the name of the service instead of the port number. In the example, you could use
ssh
instead of the port number22
. Note that a service name is resolved to a port number based on its entry in the/etc/services
file.Optionally, display all chains and their rules in
example_table
:# nft list table inet example_table table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport ssh accept ... } }
Additional resources
-
The
Address families
section in thenft(8)
man page -
The
Rules
section in thenft(8)
man page
8.3.7. Inserting a rule at a specific position of an nftables chain
This section explains how to insert rules before and after an existing rule in an nftables
chain. This way you can place new rules at the right position.
Prerequisites
- The chain to which you want to add the rules exists.
Procedure
Use the
nft -a list ruleset
command to display all chains and their rules in theexample_table
including their handle:# nft -a list table inet example_table table inet example_table { # handle 1 chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport 22 accept # handle 2 tcp dport 443 accept # handle 3 tcp dport 389 accept # handle 4 } }
Using the
-a
displays the handles. You require this information to position the new rules in the next steps.Insert the new rules to the
example_chain
chain in theexample_table
:To insert a rule that allows TCP traffic on port
636
before handle3
, enter:# nft insert rule inet example_table example_chain position 3 tcp dport 636 accept
To add a rule that allows TCP traffic on port
80
after handle3
, enter:# nft add rule inet example_table example_chain position 3 tcp dport 80 accept
Optionally, display all chains and their rules in
example_table
:# nft -a list table inet example_table table inet example_table { # handle 1 chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport 22 accept # handle 2 tcp dport 636 accept # handle 5 tcp dport 443 accept # handle 3 tcp dport 80 accept # handle 6 tcp dport 389 accept # handle 4 } }
Additional resources
-
The
Address families
section in thenft(8)
man page -
The
Rules
section in thenft(8)
man page
8.4. Configuring NAT using nftables
With nftables
, you can configure the following network address translation (NAT) types:
- Masquerading
- Source NAT (SNAT)
- Destination NAT (DNAT)
- Redirect
You can only use real interface names in iifname
and oifname
parameters, and alternative names (altname
) are not supported.
8.4.1. The different NAT types: masquerading, source NAT, destination NAT, and redirect
These are the different network address translation (NAT) types:
- Masquerading and source NAT (SNAT)
Use one of these NAT types to change the source IP address of packets. For example, Internet Service Providers do not route private IP ranges, such as
10.0.0.0/8
. If you use private IP ranges in your network and users should be able to reach servers on the Internet, map the source IP address of packets from these ranges to a public IP address.Both masquerading and SNAT are very similar. The differences are:
- Masquerading automatically uses the IP address of the outgoing interface. Therefore, use masquerading if the outgoing interface uses a dynamic IP address.
- SNAT sets the source IP address of packets to a specified IP and does not dynamically look up the IP of the outgoing interface. Therefore, SNAT is faster than masquerading. Use SNAT if the outgoing interface uses a fixed IP address.
- Destination NAT (DNAT)
- Use this NAT type to rewrite the destination address and port of incoming packets. For example, if your web server uses an IP address from a private IP range and is, therefore, not directly accessible from the Internet, you can set a DNAT rule on the router to redirect incoming traffic to this server.
- Redirect
- This type is a special case of DNAT that redirects packets to the local machine depending on the chain hook. For example, if a service runs on a different port than its standard port, you can redirect incoming traffic from the standard port to this specific port.
8.4.2. Configuring masquerading using nftables
Masquerading enables a router to dynamically change the source IP of packets sent through an interface to the IP address of the interface. This means that if the interface gets a new IP assigned, nftables
automatically uses the new IP when replacing the source IP.
The following procedure describes how to replace the source IP of packets leaving the host through the ens3
interface to the IP set on ens3
.
Procedure
Create a table:
# nft add table nat
Add the
prerouting
andpostrouting
chains to the table:# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
ImportantEven if you do not add a rule to the
prerouting
chain, thenftables
framework requires this chain to match incoming packet replies.Note that you must pass the
--
option to thenft
command to avoid that the shell interprets the negative priority value as an option of thenft
command.Add a rule to the
postrouting
chain that matches outgoing packets on theens3
interface:# nft add rule nat postrouting oifname "ens3" masquerade
8.4.3. Configuring source NAT using nftables
On a router, Source NAT (SNAT) enables you to change the IP of packets sent through an interface to a specific IP address.
The following procedure describes how to replace the source IP of packets leaving the router through the ens3
interface to 192.0.2.1
.
Procedure
Create a table:
# nft add table nat
Add the
prerouting
andpostrouting
chains to the table:# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
ImportantEven if you do not add a rule to the
postrouting
chain, thenftables
framework requires this chain to match outgoing packet replies.Note that you must pass the
--
option to thenft
command to avoid that the shell interprets the negative priority value as an option of thenft
command.Add a rule to the
postrouting
chain that replaces the source IP of outgoing packets throughens3
with192.0.2.1
:# nft add rule nat postrouting oifname "ens3" snat to 192.0.2.1
Additional resources
8.4.4. Configuring destination NAT using nftables
Destination NAT enables you to redirect traffic on a router to a host that is not directly accessible from the Internet.
The following procedure describes how to redirect incoming traffic sent to port 80
and 443
of the router to the host with the 192.0.2.1
IP address.
Procedure
Create a table:
# nft add table nat
Add the
prerouting
andpostrouting
chains to the table:# nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain nat postrouting { type nat hook postrouting priority 100 \; }
ImportantEven if you do not add a rule to the
postrouting
chain, thenftables
framework requires this chain to match outgoing packet replies.Note that you must pass the
--
option to thenft
command to avoid that the shell interprets the negative priority value as an option of thenft
command.Add a rule to the
prerouting
chain that redirects incoming traffic on theens3
interface sent to port80
and443
to the host with the192.0.2.1
IP:# nft add rule nat prerouting iifname ens3 tcp dport { 80, 443 } dnat to 192.0.2.1
Depending on your environment, add either a SNAT or masquerading rule to change the source address:
If the
ens3
interface used dynamic IP addresses, add a masquerading rule:# nft add rule nat postrouting oifname "ens3" masquerade
If the
ens3
interface uses a static IP address, add a SNAT rule. For example, if theens3
uses the198.51.100.1
IP address:# nft add rule nat postrouting oifname "ens3" snat to 198.51.100.1
Additional resources
8.4.5. Configuring a redirect using nftables
The redirect
feature is a special case of destination network address translation (DNAT) that redirects packets to the local machine depending on the chain hook.
The following procedure describes how to redirect incoming and forwarded traffic sent to port 22
of the local host to port 2222
.
Procedure
Create a table:
#
nft add table nat
Add the
prerouting
chain to the table:#
nft -- add chain nat prerouting { type nat hook prerouting priority -100 \; }
Note that you must pass the
--
option to thenft
command to avoid that the shell interprets the negative priority value as an option of thenft
command.Add a rule to the
prerouting
chain that redirects incoming traffic on port22
to port2222
:#
nft add rule nat prerouting tcp dport 22 redirect to 2222
Additional resources
8.5. Using sets in nftables commands
The nftables
framework natively supports sets. You can use sets, for example, if a rule should match multiple IP addresses, port numbers, interfaces, or any other match criteria.
8.5.1. Using anonymous sets in nftables
An anonymous set contain comma-separated values enclosed in curly brackets, such as { 22, 80, 443 }
, that you use directly in a rule. You can also use anonymous sets also for IP addresses or any other match criteria.
The drawback of anonymous sets is that if you want to change the set, you must replace the rule. For a dynamic solution, use named sets as described in Using named sets in nftables.
Prerequisites
-
The
example_chain
chain and theexample_table
table in theinet
family exists.
Procedure
For example, to add a rule to
example_chain
inexample_table
that allows incoming traffic to port22
,80
, and443
:# nft add rule inet example_table example_chain tcp dport { 22, 80, 443 } accept
Optionally, display all chains and their rules in
example_table
:# nft list table inet example_table table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport { ssh, http, https } accept } }
8.5.2. Using named sets in nftables
The nftables
framework supports mutable named sets. A named set is a list or range of elements that you can use in multiple rules within a table. Another benefit over anonymous sets is that you can update a named set without replacing the rules that use the set.
When you create a named set, you must specify the type of elements the set contains. You can set the following types:
-
ipv4_addr
for a set that contains IPv4 addresses or ranges, such as192.0.2.1
or192.0.2.0/24
. -
ipv6_addr
for a set that contains IPv6 addresses or ranges, such as2001:db8:1::1
or2001:db8:1::1/64
. -
ether_addr
for a set that contains a list of media access control (MAC) addresses, such as52:54:00:6b:66:42
. -
inet_proto
for a set that contains a list of Internet protocol types, such astcp
. -
inet_service
for a set that contains a list of Internet services, such asssh
. -
mark
for a set that contains a list of packet marks. Packet marks can be any positive 32-bit integer value (0
to2147483647
).
Prerequisites
-
The
example_chain
chain and theexample_table
table exists.
Procedure
Create an empty set. The following examples create a set for IPv4 addresses:
To create a set that can store multiple individual IPv4 addresses:
# nft add set inet example_table example_set { type ipv4_addr \; }
To create a set that can store IPv4 address ranges:
# nft add set inet example_table example_set { type ipv4_addr \; flags interval \; }
ImportantTo avoid that the shell interprets the semicolons as the end of the command, you must escape the semicolons with a backslash.
Optionally, create rules that use the set. For example, the following command adds a rule to the
example_chain
in theexample_table
that will drop all packets from IPv4 addresses inexample_set
.# nft add rule inet example_table example_chain ip saddr @example_set drop
Because
example_set
is still empty, the rule has currently no effect.Add IPv4 addresses to
example_set
:If you create a set that stores individual IPv4 addresses, enter:
# nft add element inet example_table example_set { 192.0.2.1, 192.0.2.2 }
If you create a set that stores IPv4 ranges, enter:
# nft add element inet example_table example_set { 192.0.2.0-192.0.2.255 }
When you specify an IP address range, you can alternatively use the Classless Inter-Domain Routing (CIDR) notation, such as
192.0.2.0/24
in the above example.
8.5.3. Additional resources
-
The
Sets
section in thenft(8)
man page
8.6. Using verdict maps in nftables commands
Verdict maps, which are also known as dictionaries, enable nft
to perform an action based on packet information by mapping match criteria to an action.
8.6.1. Using anonymous maps in nftables
An anonymous map is a { match_criteria : action }
statement that you use directly in a rule. The statement can contain multiple comma-separated mappings.
The drawback of an anonymous map is that if you want to change the map, you must replace the rule. For a dynamic solution, use named maps as described in Using named maps in nftables.
The example describes how to use an anonymous map to route both TCP and UDP packets of the IPv4 and IPv6 protocol to different chains to count incoming TCP and UDP packets separately.
Procedure
Create the
example_table
:# nft add table inet example_table
Create the
tcp_packets
chain inexample_table
:# nft add chain inet example_table tcp_packets
Add a rule to
tcp_packets
that counts the traffic in this chain:# nft add rule inet example_table tcp_packets counter
Create the
udp_packets
chain inexample_table
# nft add chain inet example_table udp_packets
Add a rule to
udp_packets
that counts the traffic in this chain:# nft add rule inet example_table udp_packets counter
Create a chain for incoming traffic. For example, to create a chain named
incoming_traffic
inexample_table
that filters incoming traffic:# nft add chain inet example_table incoming_traffic { type filter hook input priority 0 \; }
Add a rule with an anonymous map to
incoming_traffic
:# nft add rule inet example_table incoming_traffic ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets }
The anonymous map distinguishes the packets and sends them to the different counter chains based on their protocol.
To list the traffic counters, display
example_table
:# nft list table inet example_table table inet example_table { chain tcp_packets { counter packets 36379 bytes 2103816 } chain udp_packets { counter packets 10 bytes 1559 } chain incoming_traffic { type filter hook input priority filter; policy accept; ip protocol vmap { tcp : jump tcp_packets, udp : jump udp_packets } } }
The counters in the
tcp_packets
andudp_packets
chain display both the number of received packets and bytes.
8.6.2. Using named maps in nftables
The nftables
framework supports named maps. You can use these maps in multiple rules within a table. Another benefit over anonymous maps is that you can update a named map without replacing the rules that use it.
When you create a named map, you must specify the type of elements:
-
ipv4_addr
for a map whose match part contains an IPv4 address, such as192.0.2.1
. -
ipv6_addr
for a map whose match part contains an IPv6 address, such as2001:db8:1::1
. -
ether_addr
for a map whose match part contains a media access control (MAC) address, such as52:54:00:6b:66:42
. -
inet_proto
for a map whose match part contains an Internet protocol type, such astcp
. -
inet_service
for a map whose match part contains an Internet services name port number, such asssh
or22
. -
mark
for a map whose match part contains a packet mark. A packet mark can be any positive 32-bit integer value (0
to2147483647
). -
counter
for a map whose match part contains a counter value. The counter value can be any positive 64-bit integer value. -
quota
for a map whose match part contains a quota value. The quota value can be any positive 64-bit integer value.
The example describes how to allow or drop incoming packets based on their source IP address. Using a named map, you require only a single rule to configure this scenario while the IP addresses and actions are dynamically stored in the map. The procedure also describes how to add and remove entries from the map.
Procedure
Create a table. For example, to create a table named
example_table
that processes IPv4 packets:# nft add table ip example_table
Create a chain. For example, to create a chain named
example_chain
inexample_table
:# nft add chain ip example_table example_chain { type filter hook input priority 0 \; }
ImportantTo avoid that the shell interprets the semicolons as the end of the command, you must escape the semicolons with a backslash.
Create an empty map. For example, to create a map for IPv4 addresses:
# nft add map ip example_table example_map { type ipv4_addr : verdict \; }
Create rules that use the map. For example, the following command adds a rule to
example_chain
inexample_table
that applies actions to IPv4 addresses which are both defined inexample_map
:# nft add rule example_table example_chain ip saddr vmap @example_map
Add IPv4 addresses and corresponding actions to
example_map
:# nft add element ip example_table example_map { 192.0.2.1 : accept, 192.0.2.2 : drop }
This example defines the mappings of IPv4 addresses to actions. In combination with the rule created above, the firewall accepts packet from
192.0.2.1
and drops packets from192.0.2.2
.Optionally, enhance the map by adding another IP address and action statement:
# nft add element ip example_table example_map { 192.0.2.3 : accept }
Optionally, remove an entry from the map:
# nft delete element ip example_table example_map { 192.0.2.1 }
Optionally, display the rule set:
# nft list ruleset table ip example_table { map example_map { type ipv4_addr : verdict elements = { 192.0.2.2 : drop, 192.0.2.3 : accept } } chain example_chain { type filter hook input priority filter; policy accept; ip saddr vmap @example_map } }
8.6.3. Additional resources
-
The
Maps
section in thenft(8)
man page
8.7. Configuring port forwarding using nftables
Port forwarding enables administrators to forward packets sent to a specific destination port to a different local or remote port.
For example, if your web server does not have a public IP address, you can set a port forwarding rule on your firewall that forwards incoming packets on port 80
and 443
on the firewall to the web server. With this firewall rule, users on the internet can access the web server using the IP or host name of the firewall.
8.7.1. Forwarding incoming packets to a different local port
This section describes an example of how to forward incoming IPv4 packets on port 8022
to port 22
on the local system.
Procedure
Create a table named
nat
with theip
address family:# nft add table ip nat
Add the
prerouting
andpostrouting
chains to the table:# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
NotePass the
--
option to thenft
command to avoid that the shell interprets the negative priority value as an option of thenft
command.Add a rule to the
prerouting
chain that redirects incoming packets on port8022
to the local port22
:# nft add rule ip nat prerouting tcp dport 8022 redirect to :22
8.7.2. Forwarding incoming packets on a specific local port to a different host
You can use a destination network address translation (DNAT) rule to forward incoming packets on a local port to a remote host. This enables users on the Internet to access a service that runs on a host with a private IP address.
The procedure describes how to forward incoming IPv4 packets on the local port 443
to the same port number on the remote system with the 192.0.2.1
IP address.
Prerequisites
-
You are logged in as the
root
user on the system that should forward the packets.
Procedure
Create a table named
nat
with theip
address family:# nft add table ip nat
Add the
prerouting
andpostrouting
chains to the table:# nft -- add chain ip nat prerouting { type nat hook prerouting priority -100 \; } # nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }
NotePass the
--
option to thenft
command to avoid that the shell interprets the negative priority value as an option of thenft
command.Add a rule to the
prerouting
chain that redirects incoming packets on port443
to the same port on192.0.2.1
:# nft add rule ip nat prerouting tcp dport 443 dnat to 192.0.2.1
Add a rule to the
postrouting
chain to masquerade outgoing traffic:# nft add rule ip nat postrouting daddr 192.0.2.1 masquerade
Enable packet forwarding:
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/95-IPv4-forwarding.conf # sysctl -p /etc/sysctl.d/95-IPv4-forwarding.conf
8.8. Using nftables to limit the amount of connections
You can use nftables
to limit the number of connections or to block IP addresses that attempt to establish a given amount of connections to prevent them from using too many system resources.
8.8.1. Limiting the number of connections using nftables
The ct count
parameter of the nft
utility enables administrators to limit the number of connections. The procedure describes a basic example of how to limit incoming connections.
Prerequisites
-
The base
example_chain
inexample_table
exists.
Procedure
Create a dynamic set for IPv4 addresses:
# nft add set inet example_table example_meter { type ipv4_addr\; flags dynamic \;}
Add a rule that allows only two simultaneous connections to the SSH port (22) from an IPv4 address and rejects all further connections from the same IP:
# nft add rule ip example_table example_chain tcp dport ssh meter example_meter { ip saddr ct count over 2 } counter reject
Optionally, display the set created in the previous step:
# nft list set inet example_table example_meter table inet example_table { meter example_meter { type ipv4_addr size 65535 elements = { 192.0.2.1 ct count over 2 , 192.0.2.2 ct count over 2 } } }
The
elements
entry displays addresses that currently match the rule. In this example,elements
lists IP addresses that have active connections to the SSH port. Note that the output does not display the number of active connections or if connections were rejected.
8.8.2. Blocking IP addresses that attempt more than ten new incoming TCP connections within one minute
This section explains how you temporarily block hosts that are establishing more than ten IPv4 TCP connections within one minute.
Procedure
Create the
filter
table with theip
address family:# nft add table ip filter
Add the
input
chain to thefilter
table:# nft add chain ip filter input { type filter hook input priority 0 \; }
Add a rule that drops all packets from source addresses that attempt to establish more than ten TCP connections within one minute:
# nft add rule ip filter input ip protocol tcp ct state new, untracked meter ratemeter { ip saddr timeout 5m limit rate over 10/minute } drop
The
timeout 5m
parameter defines thatnftables
automatically removes entries after five minutes to prevent that the meter fills up with stale entries.
Verification
To display the meter’s content, enter:
# nft list meter ip filter ratemeter table ip filter { meter ratemeter { type ipv4_addr size 65535 flags dynamic,timeout elements = { 192.0.2.1 limit rate over 10/minute timeout 5m expires 4m58s224ms } } }
8.9. Debugging nftables rules
The nftables
framework provides different options for administrators to debug rules and if packets match them. This section describes these options.
8.9.1. Creating a rule with a counter
To identify if a rule is matched, you can use a counter. This section describes how to create a new rule with a counter.
-
For more information on a procedure that adds a counter to an existing rule, see Adding a counter to an existing rule in
Configuring and managing networking
Prerequisites
- The chain to which you want to add the rule exists.
Procedure
Add a new rule with the
counter
parameter to the chain. The following example adds a rule with a counter that allows TCP traffic on port 22 and counts the packets and traffic that match this rule:# nft add rule inet example_table example_chain tcp dport 22 counter accept
To display the counter values:
# nft list ruleset table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport ssh counter packets 6872 bytes 105448565 accept } }
8.9.2. Adding a counter to an existing rule
To identify if a rule is matched, you can use a counter. This section describes how to add a counter to an existing rule.
-
For more information on a procedure that adds a new rule with a counter, see Creating a rule with the counter in
Configuring and managing networking
Prerequisites
- The rule to which you want to add the counter exists.
Procedure
Display the rules in the chain including their handles:
# nft --handle list chain inet example_table example_chain table inet example_table { chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport ssh accept # handle 4 } }
Add the counter by replacing the rule but with the
counter
parameter. The following example replaces the rule displayed in the previous step and adds a counter:# nft replace rule inet example_table example_chain handle 4 tcp dport 22 counter accept
To display the counter values:
# nft list ruleset table inet example_table { chain example_chain { type filter hook input priority filter; policy accept; tcp dport ssh counter packets 6872 bytes 105448565 accept } }
8.9.3. Monitoring packets that match an existing rule
The tracing feature in nftables
in combination with the nft monitor
command enables administrators to display packets that match a rule. The procedure describes how to enable tracing for a rule as well as monitoring packets that match this rule.
Prerequisites
- The rule to which you want to add the counter exists.
Procedure
Display the rules in the chain including their handles:
# nft --handle list chain inet example_table example_chain table inet example_table { chain example_chain { # handle 1 type filter hook input priority filter; policy accept; tcp dport ssh accept # handle 4 } }
Add the tracing feature by replacing the rule but with the
meta nftrace set 1
parameters. The following example replaces the rule displayed in the previous step and enables tracing:# nft replace rule inet example_table example_chain handle 4 tcp dport 22 meta nftrace set 1 accept
Use the
nft monitor
command to display the tracing. The following example filters the output of the command to display only entries that containinet example_table example_chain
:# nft monitor | grep "inet example_table example_chain" trace id 3c5eb15e inet example_table example_chain packet: iif "enp1s0" ether saddr 52:54:00:17:ff:e4 ether daddr 52:54:00:72:2f:6e ip saddr 192.0.2.1 ip daddr 192.0.2.2 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 49710 ip protocol tcp ip length 60 tcp sport 56728 tcp dport ssh tcp flags == syn tcp window 64240 trace id 3c5eb15e inet example_table example_chain rule tcp dport ssh nftrace set 1 accept (verdict accept) ...
WarningDepending on the number of rules with tracing enabled and the amount of matching traffic, the
nft monitor
command can display a lot of output. Usegrep
or other utilities to filter the output.
8.10. Backing up and restoring the nftables rule set
This section describes how to backup nftables
rules to a file, as well as restoring rules from a file.
Administrators can use a file with the rules to, for example, transfer the rules to a different server.
8.10.1. Backing up the nftables rule set to a file
This section describes how to back up the nftables
rule set to a file.
Procedure
To backup
nftables
rules:In a format produced by
nft list ruleset
format:# nft list ruleset > file.nft
In JSON format:
# nft -j list ruleset > file.json
8.10.2. Restoring the nftables rule set from a file
This section describes how to restore the nftables
rule set.
Procedure
To restore
nftables
rules:If the file to restore is in the format produced by
nft list ruleset
or containsnft
commands directly:# nft -f file.nft
If the file to restore is in JSON format:
# nft -j -f file.json