Configuring the Firewall with nftables
This chapter describes configuring the firewall with nftables. It also
provides examples for configuring nftables tables, chains, and rules that
enforce network security on a system with the nft command. These examples are
appropriate for learning about nftables; however, for more advanced users, consider editing
nftables configurations from a file. For more information about
nftables file syntax, see the nft(8) manual page.
Do the following:
-
For Oracle Linux 8, this chapter also describes how to convert
iptablesandip6tablesto thenftablesframework. -
For Oracle Linux 9 and Oracle Linux 10, use the conversion guidance in the release-specific firewall documentation instead.
When you create nftables configurations using nft
commands, these configurations reside in the system's memory until you flush the memory or
restart the system. To make these configurations persistent across system boots, consider
exporting the configurations to an .nft file and setup the system to
include the file when starting the nftables service. For more information
about exporting configurations to a file, see Disabling the firewalld Service. For more
information about loading a configuration file into nftables either
manually or automatically, see Disabling the firewalld Service.
When working with nftables, it's good practice to keep a local connection (for example, with a serial console if possible) to recover from mistakes that might lock you out of the system.
Disabling the firewalld Service
In Oracle Linux, nftables isn't enabled by default because the firewalld service uses it as its backend. Disable firewalld before beginning to work with nftables.
Do the following:
-
For Oracle Linux 8, the output resembles:
firewalld.service Loaded: masked (Reason: Unit firewalld.service is masked.) Active: inactive (dead) Jan 20 15:16:07 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon... Jan 20 15:16:08 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon. Jan 20 15:16:08 localhost.localdomain firewalld[1635]: WARNING: AllowZoneDrifting is enabled. This is considered an insecure configuration option. It will be removed in a future release. Please consider disabling it now. Jan 20 15:52:27 localhost.localdomain systemd[1]: Stopping firewalld - dynamic firewall daemon... Jan 20 15:52:27 localhost.localdomain systemd[1]: firewalld.service: Succeeded. Jan 20 15:52:27 localhost.localdomain systemd[1]: Stopped firewalld - dynamic firewall daemon.
-
For Oracle Linux 9, the output resembles:
firewalld.service Loaded: masked (Reason: Unit firewalld.service is masked.) Active: inactive (dead) Jan 20 15:10:08 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon... Jan 20 15:10:08 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon. Jan 20 15:26:25 localhost.localdomain systemd[1]: Stopping firewalld - dynamic firewall daemon... Jan 20 15:26:25 localhost.localdomain systemd[1]: firewalld.service: Deactivated successfully. Jan 20 15:26:25 localhost.localdomain systemd[1]: Stopped firewalld - dynamic firewall daemon. -
For Oracle Linux 10, the output resembles:
firewalld.service Loaded: masked (Reason: Unit firewalld.service is masked.) Active: inactive (dead) Jan 20 16:05:39 localhost.localdomain systemd[1]: Starting firewalld.service - firewalld - dynamic firewall daemon... Jan 20 16:05:40 localhost.localdomain systemd[1]: Started firewalld.service - firewalld - dynamic firewall daemon. Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon... Jan 20 16:08:33 localhost.localdomain systemd[1]: firewalld.service: Deactivated successfully. Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.
-
Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon... Jan 20 16:08:33 localhost.localdomain systemd[1]: firewalld.service: Deactivated successfully. Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.
About Rulesets and Tables
nftables includes rulesets that contain all configuration structures within
nftables. Tables are the top level structure in rulesets within which are contained various
objects such as chains, rules, and so on.
Managing Rulesets and Tables
nftable rulesets and tables in memory, do the following: Create a table for a specific address family type using the following syntax:
sudo nft add table <address_family> <table_name>
In the previous,- <address_family> can be
ip,ip6,inet,arp,bridge, ornetdev. Allnftablesobjects are in one of these address families. For more information about these address families, see thenft(8)manual page. - <table_name> is the name of the table. Tables contain chains, which in turn contain rules.
For example, the following command creates a table calledmytablewith the inet family, which includes addresses for IP version 4 and 6:sudo nft add table inet mytable- <address_family> can be
- Do the following:
- To view all rulesets, do the following:
sudo nft list ruleset - To view a single table, do the following:
sudo nft list table <address_family> <table_name>
- To view all rulesets, do the following:
About Hooks and Chains
Hooks are points in a system where packets can be intercepted for processing. These hooks are
where nftables applies chains and rules that decide what happens to a packet.
Different hooks are available depending on the address family applied to a table.
The following table shows the hooks available to each address family.
|
Address Family |
Hook |
Description |
|---|---|---|
|
IP, IPv6, inet / Bridge |
prerouting |
Processes all incoming packets before routing decisions. |
|
input |
Handles packets destined for the local system. |
|
|
forward |
Manages packets being forwarded to another host. |
|
|
output |
Processes packets originating from the local system. |
|
|
postrouting |
Deals with all outgoing packets after routing. |
|
|
ingress |
Manages incoming packets before the prerouting, available from Linux kernel 5.10 for inet family. |
|
|
ARP |
input |
Processes packets for the local system. |
|
output |
Handles packets sent from the local system. |
|
|
Netdev |
ingress |
Processes incoming packets after network taps, such as tcpdump, before layer 3 handling. |
|
egress |
Manages outgoing packets after layer 3 handling but before final network exit. |
nftables includes
the following chain types: - Base Chains: These are chains directly built on a hook. For example, a base chain
named
myinputmight be linked to the inet input hook for IPv4 or IPv6 packets arriving at the local system. - Regular Chains: These are chains that jump from base chains or other regular chains. They aren't built directly at a hook but can be part of the decision-making process within a base chain.
filter: Primarily used for packet filtering, such as whether to permit or block packets based on various criteria such as source and destination IP, ports, protocols, and so on. This chain type works with all address families and their hooks.nat: Primarily used to change IP addresses, ports, or both in packet headers for NAT operations. This includes changes to Source NAT (SNAT) for outgoing traffic and Destination NAT (DNAT) for incoming traffic. This chain type can be configured with ip, ipv6, and inet address families and can take the prerouting, input, output, and postrouting hooks.route: Primarily used for routing decisions such as altering a routing table or marking packets for specific routing policies. This chain type can be used with ip and ipv6 address families and can take the output hook only.
When using the ingress or egress hooks, specify a network interface name as a string with the
device parameter. Any ingress or egress chains only filters traffic from
the interface specified in the device parameter.
The priority parameter uses a signed integer or a standard priority name to determine the order in which chains with the same hook are processed. Chains process from lower priority values or names to higher priority values or names.
The following table shows priority names and values for each associated address family and hook type.
|
Name |
Value |
Family | Hooks |
|---|---|---|---|
|
raw |
-300 |
ip, ip6, inet | all |
|
mangle |
-150 |
ip, ip6, inet | all |
|
dsnat |
-100 |
ip, ip6, inet | prerouting |
|
filter |
0 |
ip, ip6, inet, arp, netdev | all |
|
security |
50 |
ip, ip6, inet | all |
|
srcnat |
100 |
ip, ip6, inet | postrouting |
The following table shows priority names and values for the bridge address family and hook type.
|
Name |
Value |
Hooks |
|---|---|---|
|
dsnat |
-300 |
prerouting |
|
filter |
-200 |
all |
|
out |
100 |
output |
|
srcnat |
300 |
postrouting |
You can also choose to set a policy on a chain that defines whether to
accept or drop a packet when none of the rules defined on
the chain matches the packet. By default, base chains accept all packets. However, setting a
policy to drop all traffic not explicitly allowed by a chain is good practice for security
reasons.
Creating Base Chains
nftable base chains in memory, do the following: Create a chain for a specific address family type and table using the following syntax:
sudo nft add chain <address_family> <table_name> <chain_name>{ type <chain_type> hook <hook_type> device <network_interface_name> priority <priority> policy <policy> comment <comment> ; }In the previous,- <address_family> can be
ip,ip6,inet,arp,bridge, ornetdev. Allnftablesobjects are in one of these address family. For more information about these address families, see thenft(8)manual page. - <table_name> is the name of the table. Tables are containers for chains, which in turn are containers for rules.
- <chain_name> is an arbitrary name for the chain. People migrating from iptables based firewalls often use traditional iptables naming.
- <chain_type> is the chain type. Valid values for base chains are
filter,nat, androute. For more information, see About Hooks and Chains. - <hook_type> is the hook type. Possible values depend on the selected address family and chain type. For more information, see About Hooks and Chains.
- <network_interface_name> is the network interface name for the device parameter. This parameter is only required when using the ingress or egress hooks.
- <priority> is the priority value or name for the chain. Priority depends on the selected address family and hook type. For more information, see About Hooks and Chains.
- <policy> is the action taken if all rules defined on the chain fail to
match the packet. Valid values are
acceptordrop. If not specified, the default value isaccept.
For example, the following command creates a chain in themytabletable calledmychainwith theinetfamily. The chain type isfilter, the hook isinput, and the priority is0. Finally, the policy is set to drop all packets that don't match a rule:sudo nft add chain inet mytable mychain "{ type filter hook input priority 0 ; policy drop ; }"- <address_family> can be
- Do the following:
- To view all chains, do the following:
sudo nft list chains - To view a single chain, do the following:
sudo nft list chain <address_family> <table_name><chain_name>
- To view all chains, do the following:
About Rules
- Sets, which are collections of elements used for the matching.
- Expressions, which are building blocks for rules that define how packets are matched or
manipulated. Examples include:
- Protocol-specific matches (for example, ip, ip6, tcp, udp).
- Address matching (saddr, daddr).
- Port matching (sport, dport).
- Network interface matches (iifname, oifname).
- Maps, which are similar to sets but can map one value to another. Maps are used for more complex matching or transformation scenarios.
- Verdict maps, which can change verdicts based on packet content, enable more dynamic policy decisions.
- Counters, which track the number of packets matching a rule and display when running a
list
nftcommand that includes the rule. Counters are a useful way to test whether a rule is working. - Quotas, which limit the amount of data that can pass through a rule before an action
changes (for example, from
accepttodrop). - Flowtables, which allows fast path packet forwarding, improving performance by bypassing regular packet processing for certain traffic.
- Statements, which includes operations such as
log,reject,jump,gotowhich change packet handling behavior.
Rules added to a chain are evaluated from top to bottom and from left to right.
For more information about configuring these instructions, see the nft(8)
manual page.
Creating Rules - Examples
This section includes some common example of rules created within chains.
Allow local traffic
mytable within
mychain for the inet family that allows local traffic to
enter through the loopback interface (iff lo):
sudo nft add rule inet mytable mychain iif lo acceptAllow incoming traffic for an existing connection or related to an existing connection
mytable's mychain chain
that accepts all incoming traffic that are part of or related to an existing
connection:sudo nft add rule inet mytable mychain ct state established, related acceptctis a connection tracking helper for IPv4, IPv6, or inet which is part of thenf_conntrackmodule. This module is typically loaded by default on most systems. You can list the state of all connections to the system using the following command:sudo cat /proc/net/nf_conntrackPossible connection states are:NEW: The packet has started a new connection, or is associated with a connection that hasn't received and sent packets.ESTABLISHED: The packet is associated with a connection which has received and sent packets.RELATED: The packet is starting a new connection, but is associated with an existing connection.INVALID: The packet is associated with no known connection.
state established, relatedindicates that the command applies only to connections in theESTABLISHEDorRELATEDstate.acceptindicates that any packet with the appropriate state can be accepted.
This is a common rule in firewall configurations to ensure that responses to outgoing traffic are allowed back in, enabling normal operations of network services such as web browsing, SSH connectivity, and so on, without needing to explicitly open all ports for incoming connections.
Allow incoming SSH traffic
mytable's mychain chain
that accepts all incoming TCP traffic on destination port 22.
sudo nft add rule inet mytable mychain tcp dport 22 acceptThis port is typically used for SSH traffic and assumes that the SSH daemon is setup and running on the system.
Restricting all IPv4 and IPv6 traffic (Panic button)
mytable table that drops all incoming and
outgoing IPv4 and IPv6 and acts as a kind of panic button.
sudo nft add rule inet mytable dropExporting Configurations to a File
To keep nftable configurations across boots or to switch from one
configuration to another, you can export an nftable in memory to a file.
nftable configurations to a file, do the following: List the rulesets and save the output to a file:
sudo nft list ruleset > /etc/nftables/<export_file_name>.nft
In the previous, <export_file_name> is the name of the file for the exported information. This file now contains all the tables, chains, and rules available in memory.
List a table and save the output to a file:
sudo nft list table <address_family> <table_name> > /etc/nftables/<export_file_name>.nft
This file now contains a table and all associated chains and rules available in memory.
List a chain and save the output to a file:
sudo nft list chain <address_family> <table_name> <chain_name> > /etc/nftables/<export_file_name>.nft
This file now contains a chain in a table and all associated rules within the chain available in memory.
- Ensure the files included in
/etc/nftablesare executable:sudo chmod +x /etc/nftables/<export_file_name>.nft
Loading Configurations from a File
To load an nftable ruleset, table, or chain from a file into memory, you can
perform this task manually or automatically when rebooting a system.
nftables file, do the following: - Before loading a new configuration from a file, drop the existing
tables:
sudo nft flush rulesetNote
This step is crucial to avoid conflicts between the new and old configurations and ensures a clean and consistent application of the new rules. Run the following command to load the file into memory:
sudo nft -f /etc/nftables/<import_file_name>.nft
In the previous, <import_file_name> is the name of the file with the information to be imported. This file might contain a ruleset, one or more tables, one or more chains within a table, and any associated rules.Note
The atomic reload is annftablesfeature that ensures that connection tracking is preserved during rule reloading, providing a seamless transition to the new configuration.List a ruleset to verify that the file imported correctly:
sudo nft list rulesets
Edit the
/etc/sysconfig/nftables.conffile to include the .nft table files you want to include at startup. If this file doesn't exist, create it. For example, the following shows that the/etc/sysconfig/nftables.confnow includes the exported/etc/nftables/myruleset.nftfile.# Uncomment the include statement here to load the default config sample # in /etc/nftables for nftables service. include "/etc/nftables/myruleset.nft" # To customize, either edit the samples in /etc/nftables, append further # commands to the end of this file or overwrite it after first service # start by calling: 'nft list ruleset >/etc/sysconfig/nftables.conf'.
Enable and start the
nftablesservice:sudo systemctl enable --now nftables