NFTables comes as the successor of IPTables. Despite it being the successor of NFTables, the syntax is quite different from IPTables, though IPTables can still be usable as it has backward compatibility. Before going further about NFTables, it is recommended to learn about IPTables and have a good understanding about it which can be learned here.
What is NFTables?
NFTables or Net Filter Tables is a Linux kernel packet framework providing
network filtering on multiple networking levels. The syntax used for nftables
is nft
. In case you need a format to work with, you can find it in
/etc/nftables.conf
.
Why use NFTable?
There are several reasons why it is better to use NFTable rather than IPTables. Some prominent reasons are duplication and simplicity and dual stack IPv4/IPv6 administration.
Duplication and simplicity
Iptables only allows a single rule with a single action, which leads to inefficiency and possible duplication. On the contrary, the nftables can contain multiple conditions at once. For example, you may open multiple ports at once by setting up the ruleset like this.
tcp dport { 22, 53, 80, 123, 443 } accept
Dual stack IPv4/IPv6 administration
As mentioned from the previous post, the iptables only supports IPv4. On the other hand, nftables allows IPv4 for and IPv6 which you will be using most of the time with inet family.
The Concept
Just like iptables, there are also three terms to understand when using nftables. However, it is quite different as it doesn’t have predefined tables or chains. There are also more things to cover on each term.
Tables
In nftables, there are six types of configurable tables. These are known as family which refers to: ip (for IPv4), ip6(for IPv6), arp (for ARP), bridge (for packet that traverse bridge device), inet(dual stack ipv4/IPv6), netdev (packet handler for ingress).
Chains
Type
Some chains are only supported by certain families. There are three possible types as follows.
- filter : supported by ip, ip6, arp, bridge, and inet.
- route : used for mark packets (like the OUTPUT chain of mangle), supported by ip and ip6.
- nat : supported by ip and ip6.
Hook
Hook is used to specify a specific stage while the packet is being processed. Different families may have different usable hooks.
- prerouting, input, forward, output, postrouting : for ip, ip6, and inet.
- input, output : for arp.
- ingress : for netdev.
Priority
Priority is the number of orders to use between several netfilter operations. The order is ascending, so the lower the number will be executed earlier.
Policy
Policy is the decision to be made when a packet flows in a particular stage if no rules are matched. Possible values are accept and drop.
Rules
Rules and filters can be set based on certain packet information in a particular protocol. Possible protocols to match are ip, ip6, tcp, udp, udplite, sctp, dccp, ah, esp, comp, icmp, icmpv6, ether, dst, frag, hbh, mh, rt, vlan, and arp. The rules can also be set with connection tracking using ct or by the packet metainformation using meta.
Statement
Statement is the action to be made if rules are matched. There are some possible statements.
- accept : allow packet then stop the rules evaluation.
- drop : drop packet then stop the rules evaluation.
- continue : queue packet then stop the rules evaluation.
- return : return and then proceed to the next rule of the last chain.
- jump
: jump to the other chain rule and then going back to last chain rule - goto
: goto another and skip last chain rule if any
Either jump or goto only works on regular chains (user-defined chains). It is also possible to use scripts for setting up the ruleset. Predefined script is already available in /etc/nftables.conf so you can use it as a base framework.
The Script and Syntax
Setting up the ruleset can be done using two methods: typing directly in
terminal or using script which is more recommended. In this example, we will
use script.
First, we need to check the active rulesets by one of the following commands.
List tables
sudo nft list tables
List chains
sudo nft list chains
List ruleset
sudo nft list ruleset
In order to block all connections and only allow some particular packets like ping requests, loopback traffic, http requests, and ssh, use the code below.
#usr/sbin/nft -f
flush ruleset
table inet firewall {
chain incoming {
type filter hook input priority 0; policy drop;
ct state established,related accept
iifname lo accept
icmp type echo-request accept
tcp dport {ssh, http} accept
}
}
Here is the breakdown of the above example.
The shebang (#usr/sbin/nft -f
) means that we want to execute the script
using the nft command located in usr/sbin/nft. The flush ruleset
is there in
order to flush (remove) prior rulesets settings so it doesn’t interfere with
our new ruleset.
Unlike the iptables, we need to define the name of the table
before making
one. Here we give the name firewall
to it. If we don’t set any families, it
will be set to ip by default. We use inet
, so it is supposed to cover both
IPv4 and IPv6. Besides, we also need to give the name of the chain. Here we
use incoming
.
Next, we need to define the type and we use filter
because we need it for
filtering the incoming and outgoing packet which you are most likely to use as
well. For the hook, we bind this incoming
chain with the input
hook as we
want to filter the incoming packet.
Priority order is ascending by default, so setting it to 0
means that it was
given the highest priority. Policy is set to drop
, thus it will block any
packets that do not match the ruleset by default. The next one ct state established,related accept
is basically saying that the existing packet
(established
) and the new packet requested by the already existing
connection (related
) will be allowed and tracked using the connection
tracking module.
Since we drop all the connections by default, we want to allow the loopback
traffic. Therefore we set the rules to accept it using iifname lo accept
.
Iifname
defines the input interface name. As we want to set it for loopback
we use lo
.
Next, we set the protocol. Ping is based on icmp
which is also known as
echo-request
traffic. So, we set it the way it is. Since we want to allow
http connection and ssh, we should open the ports. Both are based on tcp
.
Opening some particular ports can be done by using the name of the network
protocol like the example above (ssh
and http
). Otherwise you may also use
the actual port, like 22 for ssh and 80 for http. We use curly brackets so we
can use multiple protocols at once.
Executing the script
To execute the aforementioned script, you have to use nft extension on your file. Say that you name your file rules.nft in the current location so the command would be like this.
sudo nft -f rules.nft
The rule set is just temporary and will reset after you reboot your system. To make it persistent, you have to overwrite the existing file of nftables.conf and enable the nftables service.
nft list ruleset > /etc/nftables.conf
systemctl enable nftables
Before doing this, you have to use a root account. Switch from your current
account with su
and enter the root password.
After executing these two commands, you can reboot your system. If it was
successful, you will have your previous setting show up when you enter the
command sudo nft list ruleset
right after rebooting.
Testing the script
The easiest way to test if the script works is just modifying the statement to
drop
and see if it still works. The above script can be modified to block
loopback traffic by changing this rule iifname lo accept
into this iifname lo drop
.
Now, try to ping to your own localhost. If you don’t get any reply, it means
that the above rule works using the following command. Change it back to
accept
and you are supposed to get a reply now.
ping 127.0.0.1
Removing the rules with handle
To remove or delete all rules simply use this command.
sudo nft flush ruleset
Handle in nftables works similarly to a line number in iptables. It basically tells you what the identifier number of a certain rule is. To check, use the command below.
sudo nft -a list ruleset
In my Linux box, the above example results in an output like this.
table inet firewall { # handle 5
chain incoming { # handle 1
type filter hook input priority 0; policy drop;
ct state established,related accept # handle 3
iifname lo accept # handle 4
icmp type echo-request accept # handle 5
tcp dport {ssh, http} accept # handle 6
}
}
For example, in order to get rid of a rule with the handle
number 5 you use
this.
sudo nft delete rule inet firewall incoming handle 5
Adding new rules with position
In another case, you may also want to add a new rule without modifying the script. You can use position to achieve this. Let’s try to bring back the deleted rule into its original position.
sudo nft add rule inet firewall incoming position 4 icmp type echo-request accept
Conclusion
As a framework, nftables covers multiple layers at once like layer 4 (TCP, UDP, AH, ESP), layer 3 (IPv4, IPv6) and even layer 2 (ARP). Although it seems quite intimidating at first, it really offers better flexibility and efficiency as compared to its predecessor. However, both nftables and itpables, requires you to have at least a good underlying networking knowledge.