<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://wiki.nftables.org/wiki-nftables/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Plushkava</id>
	<title>nftables wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.nftables.org/wiki-nftables/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Plushkava"/>
	<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php/Special:Contributions/Plushkava"/>
	<updated>2026-05-26T23:12:45Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1151</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1151"/>
		<updated>2024-10-08T22:35:39Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Remove a superfluous newline&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing &#039;&#039;nftables&#039;&#039; commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (U+23) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as either synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page, or as examples of complete rulesets, if so indicated.&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; commands within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before passing it on to the nft(8) utility as a single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
Examples describing &#039;&#039;nftables&#039;&#039; grammar shall employ square brackets (U+5B, U+5D) to denote optional components of syntax, and angle brackets (U+3C, U+3D) to denote user-specified values.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;filter&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;br /&gt;
&lt;br /&gt;
Here is the exact same policy, only shown in the declarative style. That is, in the same format as would be employed upon issuing the &amp;quot;list ruleset&amp;quot; command. Despite the marked difference in style, it constitutes valid &#039;&#039;nftables&#039;&#039; syntax and is equivalent to the combination of &amp;quot;add table&amp;quot; and &amp;quot;add chain&amp;quot; commands shown above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain output {&lt;br /&gt;
		type filter hook output priority filter; policy accept;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1150</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1150"/>
		<updated>2024-10-08T22:31:45Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Have the syntactic conventions account for the presence of ruleset samples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing &#039;&#039;nftables&#039;&#039; commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (U+23) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as either synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page, or as examples of complete rulesets, if so indicated.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; commands within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before passing it on to the nft(8) utility as a single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
Examples describing &#039;&#039;nftables&#039;&#039; grammar shall employ square brackets (U+5B, U+5D) to denote optional components of syntax, and angle brackets (U+3C, U+3D) to denote user-specified values.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;filter&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;br /&gt;
&lt;br /&gt;
Here is the exact same policy, only shown in the declarative style. That is, in the same format as would be employed upon issuing the &amp;quot;list ruleset&amp;quot; command. Despite the marked difference in style, it constitutes valid &#039;&#039;nftables&#039;&#039; syntax and is equivalent to the combination of &amp;quot;add table&amp;quot; and &amp;quot;add chain&amp;quot; commands shown above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain output {&lt;br /&gt;
		type filter hook output priority filter; policy accept;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1149</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1149"/>
		<updated>2024-10-08T22:24:43Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Show the example ruleset at the end in the &amp;quot;list ruleset&amp;quot; style as well as a series of incremental commands&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing &#039;&#039;nftables&#039;&#039; commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (U+23) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page.&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; commands within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before passing it on to the nft(8) utility as a single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
Examples describing &#039;&#039;nftables&#039;&#039; grammar shall employ square brackets (U+5B, U+5D) to denote optional components of syntax, and angle brackets (U+3C, U+3D) to denote user-specified values.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;filter&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;br /&gt;
&lt;br /&gt;
Here is the exact same policy, only shown in the declarative style. That is, in the same format as would be employed upon issuing the &amp;quot;list ruleset&amp;quot; command. Despite the marked difference in style, it constitutes valid &#039;&#039;nftables&#039;&#039; syntax and is equivalent to the combination of &amp;quot;add table&amp;quot; and &amp;quot;add chain&amp;quot; commands shown above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
	chain input {&lt;br /&gt;
		type filter hook input priority filter; policy accept;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	chain output {&lt;br /&gt;
		type filter hook output priority filter; policy accept;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1148</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1148"/>
		<updated>2024-10-08T22:10:31Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Replace a stray instance of &amp;quot;foo&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing &#039;&#039;nftables&#039;&#039; commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (U+23) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page.&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; commands within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before passing it on to the nft(8) utility as a single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
Examples describing &#039;&#039;nftables&#039;&#039; grammar shall employ square brackets (U+5B, U+5D) to denote optional components of syntax, and angle brackets (U+3C, U+3D) to denote user-specified values.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;filter&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1147</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1147"/>
		<updated>2024-10-08T22:08:57Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Describe the conventions for examples of nftables grammar&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing &#039;&#039;nftables&#039;&#039; commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (U+23) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page.&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; commands within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before passing it on to the nft(8) utility as a single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
Examples describing &#039;&#039;nftables&#039;&#039; grammar shall employ square brackets (U+5B, U+5D) to denote optional components of syntax, and angle brackets (U+3C, U+3D) to denote user-specified values.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1146</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1146"/>
		<updated>2024-10-08T21:59:23Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Extremely minor changes to Syntactic conventions&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing &#039;&#039;nftables&#039;&#039; commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (#) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page.&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; commands within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before passing it on to the nft(8) utility as a single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1145</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1145"/>
		<updated>2024-10-08T21:56:30Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Add a &amp;quot;Syntactic conventions&amp;quot; section in an attempt to bring the standard closer to that of formal documentation; have it subsume the aside regarding matters of shell quoting that was previously in the &amp;quot;Adding base chains&amp;quot; section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Syntactic conventions =&lt;br /&gt;
&lt;br /&gt;
Naturally, in order to make use of &#039;&#039;nftables&#039;&#039; commands and directives, it is necessary to become familiar with them, along with their supported grammar. Even with that knowledge, users sometimes experience difficulties where passing nftables commands as arguments to the nft(8) utility. That&#039;s because shells recognise certain characters as metacharacters and treat them in a special way unless they are quoted.&lt;br /&gt;
&lt;br /&gt;
Throughout this article, examples that begin with the hash character (#) can be taken as examples of valid shell code. That is, they are syntactically valid if entered into any implementation of the Shell Command Language, including bash. By contrast, examples that do not begin with the hash character can be interpreted as synopses of &#039;&#039;nftables&#039;&#039; grammar, similar in style to the nft(8) man page.&lt;br /&gt;
&lt;br /&gt;
As such, examples of shell code shall generally be of the following form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;nftables commands go here&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that enclosing the &#039;&#039;nftables&#039;&#039; command(s) within single quotes is a straightforward way of preventing the shell from interpreting characters as metacharacters, most notably the semicolon. Rather, the shell will consider all that is between the pair of single quotes as a single word before it on to the nft(8) utility as single argument, verbatim. Another way to prevent the shell from attempting to parse metacharacters is to run nft(8) in its interactive mode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, nft(8) will directly interpret any further input given until such time as it is either interrupted, encounters the end-of-file (EOF) condition, or encounters the &amp;quot;quit&amp;quot; command. In most terminal emulators, EOF can be conveyed with the Ctrl+D key combination.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1144</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1144"/>
		<updated>2024-10-08T21:22:05Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Introduce nft grammar with a consistent style of English; make the flush chain example an example of grammar rather than an example of a shell command (just like how the section on deleting begins)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack. The syntax for adding base chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: &#039;&#039;nft&#039;&#039; re-uses special characters, such as curly braces and the semicolon. If you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need to be escaped. The simplest way to prevent the shell from attempting to parse the &#039;&#039;nft&#039;&#039; syntax is to quote everything within single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains, the syntax for which is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
The syntax for deleting chains is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush a chain means to delete all of the rules that it contains, if any. The syntax for doing so is as follows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
flush chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1143</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1143"/>
		<updated>2024-10-08T20:57:10Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Employ a chain name of eth0_filter rather than dev0filter in the ingress hook example (it seems a little clearer)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The syntax to add a base chain is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: &#039;&#039;nft&#039;&#039; re-uses special characters, such as curly braces and the semicolon. If you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need to be escaped. The simplest way to prevent the shell from attempting to parse the &#039;&#039;nft&#039;&#039; syntax is to quote everything within single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter eth0_filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete chains as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush (delete all of the rules in) the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;filter&#039;&#039; table associated with the &#039;&#039;ip&#039; family:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;flush chain ip filter input&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1142</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1142"/>
		<updated>2024-10-08T20:49:22Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Consistently use table/chain names that reflect iptables norms, just as the final &amp;lt;source&amp;gt; block already does&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The syntax to add a base chain is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: &#039;&#039;nft&#039;&#039; re-uses special characters, such as curly braces and the semicolon. If you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need to be escaped. The simplest way to prevent the shell from attempting to parse the &#039;&#039;nft&#039;&#039; syntax is to quote everything within single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev filter dev0filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table ip filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete chains as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip filter input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip filter input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush (delete all of the rules in) the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;filter&#039;&#039; table associated with the &#039;&#039;ip&#039; family:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;flush chain ip filter input&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1141</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1141"/>
		<updated>2024-10-08T20:40:01Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Use # to denote a shell prompt (as is typical for a root session in virtually any sh implementation, including the ever-popular bash); only include a faux-prompt in examples intended to show shell commands rather than those that act as synopses of nft(8) grammar; don&amp;#039;t apply bash syntax highlighting (it hinders more than it helps); employ shell quoting consistently in all examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The syntax to add a base chain is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip foo input { type filter hook input priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: &#039;&#039;nft&#039;&#039; re-uses special characters, such as curly braces and the semicolon. If you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need to be escaped. The simplest way to prevent the shell from attempting to parse the &#039;&#039;nft&#039;&#039; syntax is to quote everything within single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip foo output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain ip foo output { type filter hook output priority 0; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete chains as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;delete chain ip foo input&#039;&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush (delete all of the rules in) the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;flush chain foo input&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft &#039;add table ip filter&#039;&lt;br /&gt;
# nft &#039;add chain ip filter input { type filter hook input priority 0; }&#039;&lt;br /&gt;
# nft &#039;add chain ip filter output { type filter hook output priority 0; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1140</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1140"/>
		<updated>2024-10-08T20:29:08Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Clean up the synopsis for adding base chains; have it cover &amp;quot;device&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The syntax to add a base chain is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# nft add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; ; [policy &amp;lt;policy&amp;gt; ;] [comment &amp;lt;comment&amp;gt; ;] }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: &#039;&#039;nft&#039;&#039; re-uses special characters, such as curly braces and the semicolon. If you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need to be escaped. The simplest way to prevent the shell from attempting to parse the &#039;&#039;nft&#039;&#039; syntax is to quote everything within single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete chains as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush (delete all of the rules in) the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft flush chain foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft &#039;add chain ip filter input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
% nft &#039;add chain ip filter output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1139</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=1139"/>
		<updated>2024-10-08T20:20:07Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Correct the synopsis for adding &amp;#039;regular&amp;#039; chains&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, with &#039;&#039;nftables&#039;&#039; you attach your [[Simple rule management|rules]] to chains. Unlike in &#039;&#039;iptables&#039;&#039;, there are no predefined chains like INPUT, OUTPUT, etc. Instead, to filter packets at a particular processing step, you explicitly create a &#039;&#039;&#039;base chain&#039;&#039;&#039; with name of your choosing, and attach it to the appropriate [[Netfilter hooks | Netfilter hook]]. This allows very flexible configurations without slowing Netfilter down with built-in chains not needed by your ruleset.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], i.e. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The syntax to add a base chain is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain [&amp;lt;family&amp;gt;] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; priority &amp;lt;value&amp;gt; \; [policy &amp;lt;policy&amp;gt; \;] [comment \&amp;quot;text comment\&amp;quot; \;] } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The following example shows how to add a new base chain &#039;&#039;input&#039;&#039; to the &#039;&#039;foo&#039;&#039; table (which must have been previously created):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: &#039;&#039;nft&#039;&#039; re-uses special characters, such as curly braces and the semicolon. If you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need to be escaped. The simplest way to prevent the shell from attempting to parse the &#039;&#039;nft&#039;&#039; syntax is to quote everything within single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another. For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order. It&#039;s possible to give two base chains the same priority, but there is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, i.e. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a regular chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). Only the first packet of a given flow hits this chain; subsequent packets bypass it. Therefore, never use this chain for filtering. The &#039;&#039;nat&#039;&#039; chain type is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible [[Netfilter_hooks | &#039;&#039;&#039;hooks&#039;&#039;&#039;]] that you can use when you configure your base chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only in &#039;&#039;netdev&#039;&#039; family since Linux kernel 4.2, and &#039;&#039;inet&#039;&#039; family since Linux kernel 5.10): sees packets immediately after they are passed up from the NIC driver, before even prerouting. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: sees all incoming packets, before any routing decision has been made. Packets may be addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: sees incoming packets that are addressed to and have now been routed to the local system and processes running there.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: sees incoming packets that are not addressed to the local system.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: sees packets that originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: sees all packets after routing, just before they leave the local system.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
Each nftables base chain is assigned a [[Netfilter_hooks#Priority_within_hook|&#039;&#039;&#039;priority&#039;&#039;&#039;]] that defines its ordering among other base chains, flowtables, and Netfilter internal operations at the same hook. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
Netfilter&#039;s hook execution mechanism is described in more detail in [http://people.netfilter.org/pablo/docs/login.pdf Pablo&#039;s paper on connection tracking].&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding regular chains =&lt;br /&gt;
&lt;br /&gt;
You can also create regular chains, analogous to &#039;&#039;iptables&#039;&#039; user-defined chains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
# nft add chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt; [comment &amp;lt;comment&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
Note that no &#039;&#039;hook&#039;&#039; keyword is included when adding a regular chain. Because it is not attached to a Netfilter hook, &#039;&#039;&#039;by itself a regular chain does not see any traffic&#039;&#039;&#039;. But one or more base chains can include rules that [[jumping to chain|jump]] or goto this chain -- following which, the regular chain processes packets in exactly the same way as the calling base chain. It can be very useful to arrange your ruleset into a tree of base and regular chains by using the [[jumping to chain|jump]] and/or goto actions. (Though we&#039;re getting a bit ahead of ourselves, nftables [[Verdict_Maps_(vmaps)|vmaps]] provide an even more powerful way to construct highly-efficient branched rulesets.)&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete chains as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain [family] &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will complain that the chain is still in use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chains =&lt;br /&gt;
&lt;br /&gt;
To flush (delete all of the rules in) the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft flush chain foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft &#039;add chain ip filter input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
% nft &#039;add chain ip filter output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1113</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1113"/>
		<updated>2024-02-07T22:51:16Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Refrain from over-using &amp;quot;note that&amp;quot; as a phrase&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform [https://en.wikipedia.org/wiki/Network_address_translation NAT]. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking. This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot. If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets. This can be accomplished by incorporating the &#039;&#039;&#039;notrack&#039;&#039;&#039; keyword into the rule. Doing so attaches a template connection tracking entry to the packet that instructs the conntrack core not to initialize a new entry in the conntrack table. The use of a hook at - or below - a priority level of &#039;&#039;&#039;raw&#039;&#039;&#039; is required. Otherwise, &#039;&#039;&#039;notrack&#039;&#039;&#039; will not be dealt with prior to the consultation of the conntrack table.&lt;br /&gt;
&lt;br /&gt;
The ruleset below demonstrates how to rewrite both the destination IP and port for each packet (also covering IPv6). Note that the rules presented affect &#039;&#039;all&#039;&#039; TCP packets arriving at &#039;&#039;all&#039;&#039; interfaces and are intended only for demonstrative purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table inet raw {&lt;br /&gt;
	chain prerouting {&lt;br /&gt;
		type filter hook prerouting priority raw; policy accept;&lt;br /&gt;
		ip protocol tcp ip  daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
		ip6 nexthdr tcp ip6 daddr set fe00::1       tcp dport set 10 notrack&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangling_packet_headers|mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1112</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1112"/>
		<updated>2024-02-07T20:41:34Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Clarify wording regarding stateless rule specificity&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform [https://en.wikipedia.org/wiki/Network_address_translation NAT]. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking. This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot. If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets. This can be accomplished by incorporating the &#039;&#039;&#039;notrack&#039;&#039;&#039; keyword into the rule. Doing so attaches a template connection tracking entry to the packet that instructs the conntrack core not to initialize a new entry in the conntrack table. Note that this requires the use of a hook at - or below - a priority level of &#039;&#039;&#039;raw&#039;&#039;&#039;. Otherwise, &#039;&#039;&#039;notrack&#039;&#039;&#039; will not be dealt with prior to the consultation of the conntrack table.&lt;br /&gt;
&lt;br /&gt;
The ruleset below demonstrates how to rewrite both the destination IP and port for each packet (also covering IPv6). Note that the rules affect &#039;&#039;all&#039;&#039; TCP packets arriving at &#039;&#039;all&#039;&#039; interfaces and are intended only for demonstrative purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table inet raw {&lt;br /&gt;
	chain prerouting {&lt;br /&gt;
		type filter hook prerouting priority raw; policy accept;&lt;br /&gt;
		ip protocol tcp ip  daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
		ip6 nexthdr tcp ip6 daddr set fe00::1       tcp dport set 10 notrack&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangling_packet_headers|mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1111</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1111"/>
		<updated>2024-02-07T20:38:10Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Indicate that the sample stateless NAT rules are loose in nature&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform [https://en.wikipedia.org/wiki/Network_address_translation NAT]. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking. This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot. If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets. This can be accomplished by incorporating the &#039;&#039;&#039;notrack&#039;&#039;&#039; keyword into the rule. Doing so attaches a template connection tracking entry to the packet that instructs the conntrack core not to initialize a new entry in the conntrack table. Note that this requires the use of a hook at - or below - a priority level of &#039;&#039;&#039;raw&#039;&#039;&#039;. Otherwise, &#039;&#039;&#039;notrack&#039;&#039;&#039; will not be dealt with prior to the consultation of the conntrack table.&lt;br /&gt;
&lt;br /&gt;
The ruleset below demonstrates how to rewrite both the destination IP and port for each packet (also covering IPv6). Note that the rules affect &#039;&#039;all&#039;&#039; packets arriving at &#039;&#039;all&#039;&#039; interfaces and are intended only for demonstrative purposes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table inet raw {&lt;br /&gt;
	chain prerouting {&lt;br /&gt;
		type filter hook prerouting priority raw; policy accept;&lt;br /&gt;
		ip protocol tcp ip  daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
		ip6 nexthdr tcp ip6 daddr set fe00::1       tcp dport set 10 notrack&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangling_packet_headers|mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1110</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1110"/>
		<updated>2024-02-07T20:34:41Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Very minor wording change&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform [https://en.wikipedia.org/wiki/Network_address_translation NAT]. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking. This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot. If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets. This can be accomplished by incorporating the &#039;&#039;&#039;notrack&#039;&#039;&#039; keyword into the rule. Doing so attaches a template connection tracking entry to the packet that instructs the conntrack core not to initialize a new entry in the conntrack table. Note that this requires the use of a hook at - or below - a priority level of &#039;&#039;&#039;raw&#039;&#039;&#039;. Otherwise, &#039;&#039;&#039;notrack&#039;&#039;&#039; will not be dealt with prior to the consultation of the conntrack table.&lt;br /&gt;
&lt;br /&gt;
The ruleset below demonstrates how to rewrite both the destination IP and port for each packet (also covering IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table inet raw {&lt;br /&gt;
	chain prerouting {&lt;br /&gt;
		type filter hook prerouting priority raw; policy accept;&lt;br /&gt;
		ip protocol tcp ip  daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
		ip6 nexthdr tcp ip6 daddr set fe00::1       tcp dport set 10 notrack&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangling_packet_headers|mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1109</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1109"/>
		<updated>2024-02-07T20:32:57Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Further clarify the use of stateless NAT&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform [https://en.wikipedia.org/wiki/Network_address_translation NAT]. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking. This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot. If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets. This can be accomplished by incorporating the &#039;&#039;&#039;notrack&#039;&#039;&#039; keyword into the rule. Doing so attaches a template connection tracking entry to the packet that instructs the conntrack core not to initialize a new entry in the connection tracking table. Note that this requires the use of a hook at - or below - a priority level of &#039;&#039;&#039;raw&#039;&#039;&#039;. Otherwise, &#039;&#039;&#039;notrack&#039;&#039;&#039; will not be dealt with prior to the consultation of the conntrack table.&lt;br /&gt;
&lt;br /&gt;
The ruleset below demonstrates how to rewrite both the destination IP and port for each packet (also covering IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
table inet raw {&lt;br /&gt;
	chain prerouting {&lt;br /&gt;
		type filter hook prerouting priority raw; policy accept;&lt;br /&gt;
		ip protocol tcp ip  daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
		ip6 nexthdr tcp ip6 daddr set fe00::1       tcp dport set 10 notrack&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangling_packet_headers|mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1108</id>
		<title>Performing Network Address Translation (NAT)</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Performing_Network_Address_Translation_(NAT)&amp;diff=1108"/>
		<updated>2024-02-07T20:18:23Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Clarify the use of notrack&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;nat&#039;&#039; chain type allows you to perform [https://en.wikipedia.org/wiki/Network_address_translation NAT]. This chain type comes with special semantics:&lt;br /&gt;
&lt;br /&gt;
* The first packet of a flow is used to look up for a matching rule which sets up the NAT binding for this flow. This also manipulates this first packet accordingly.&lt;br /&gt;
* No rule lookup happens for follow up packets in the flow: the NAT engine uses the NAT binding information already set up by the first packet to perform the packet manipulation.&lt;br /&gt;
&lt;br /&gt;
Adding a NAT rule to a filter type chain will result in an error.&lt;br /&gt;
&lt;br /&gt;
= Stateful NAT =&lt;br /&gt;
&lt;br /&gt;
The stateful NAT involves the nf_conntrack kernel engine to match/set packet stateful information and will engage according to the state of connections.&lt;br /&gt;
This is the most common way of performing NAT and the approach we recommend you to follow.&lt;br /&gt;
&lt;br /&gt;
Be aware that &#039;&#039;&#039;with kernel versions before 4.18, you have to register the prerouting/postrouting chains even if you have no rules there&#039;&#039;&#039; since these chain will invoke the NAT engine for the packets coming in the reply direction. The remaining documentation in this article assumes a newer kernel which doesn&#039;t require this inconvenience anymore.&lt;br /&gt;
&lt;br /&gt;
== Source NAT ==&lt;br /&gt;
&lt;br /&gt;
If you want to source NAT the traffic that leaves from your local area network to the Internet, you can create a new table &#039;&#039;nat&#039;&#039; with the postrouting chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat postrouting { type nat hook postrouting priority 100 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This matches for all traffic from the 192.168.1.0/24 network to the interface &#039;&#039;eth0&#039;&#039;. The IPv4 address 1.2.3.4 is used as source for the packets that match this rule.&lt;br /&gt;
&lt;br /&gt;
=== NAT pooling ===&lt;br /&gt;
&lt;br /&gt;
It is possible to specify source NAT pooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.2/31&lt;br /&gt;
% nft add rule inet nat postrouting snat ip to 10.0.0.4-10.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With transport protocol source port mapping:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat postrouting ip protocol tcp snat ip to 10.0.0.1-10.0.0.100:3000-4000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Destination NAT ==&lt;br /&gt;
&lt;br /&gt;
You need to add the following table and chain configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table nat&lt;br /&gt;
% nft &#039;add chain nat prerouting { type nat hook prerouting priority -100; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you can add the following rule:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add rule nat prerouting iif eth0 tcp dport { 80, 443 } dnat to 192.168.1.120&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This redirects the incoming traffic for TCP ports 80 and 443 to 192.168.1.120.&lt;br /&gt;
&lt;br /&gt;
== Masquerading ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;masquerade&#039;&#039; is available starting with Linux Kernel 3.18.&lt;br /&gt;
&lt;br /&gt;
Masquerade is a special case of SNAT, where the source address is automagically set to the address of the output interface. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that &#039;&#039;masquerade&#039;&#039; only makes sense from postrouting chain of NAT type.&lt;br /&gt;
&lt;br /&gt;
== Redirect ==&lt;br /&gt;
&lt;br /&gt;
NOTE: &#039;&#039;redirect&#039;&#039; is available starting with Linux Kernel 3.19.&lt;br /&gt;
&lt;br /&gt;
By using redirect, packets will be forwarded to local machine. Is a special case of DNAT where the destination is the current machine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting redirect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects 22/tcp traffic to 2222/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat prerouting tcp dport 22 redirect to 2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example redirects outgoing 53/tcp traffic to a local proxy listening on port 10053/tcp:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat output tcp dport 853 redirect to 10053&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that: &#039;&#039;redirect&#039;&#039; only makes sense in prerouting and output chains of NAT type.&lt;br /&gt;
&lt;br /&gt;
== NAT flags ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 3.18, you can combine the following flags with your NAT statements:&lt;br /&gt;
&lt;br /&gt;
* random: randomize source port mapping.&lt;br /&gt;
* fully-random: full port randomization.&lt;br /&gt;
* persistent: gives a client the same source-/destination-address for each connection.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule nat postrouting masquerade random,persistent&lt;br /&gt;
% nft add rule nat postrouting ip saddr 192.168.1.0/24 oif eth0 snat to 1.2.3.4 fully-random&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inet family NAT ==&lt;br /&gt;
&lt;br /&gt;
Since Linux kernel 5.2, there is support for performing stateful NAT in &#039;&#039;inet&#039;&#039; family chains. Syntax and semantics are equivalent to &#039;&#039;ip&#039;&#039;/&#039;&#039;ip6&#039;&#039; families; the only exception being if IP addresses are specified, a prefix of either &#039;&#039;ip&#039;&#039; or &#039;&#039;ip6&#039;&#039; to clarify the address family is required:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip to 10.0.0.2&lt;br /&gt;
% nft add rule inet nat prerouting dnat ip6 to feed::c0fe&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Incompatibilities ==&lt;br /&gt;
&lt;br /&gt;
You cannot use iptables and nft to perform NAT at the same time before kernel 4.18. So make sure that the &#039;&#039;iptable_nat&#039;&#039; module is unloaded:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% rmmod iptable_nat&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With later kernels, it is possible to use iptables and nftables nat at the same time.&lt;br /&gt;
The nat chains are consulted according to their priorities, the first matching rule&lt;br /&gt;
that adds a nat mapping (dnat, snat, masquerade) is the one that will be used for the connection.&lt;br /&gt;
&lt;br /&gt;
= Stateless NAT =&lt;br /&gt;
&lt;br /&gt;
This type of NAT just modifies each packet according to your rules without any other state/connection tracking.&lt;br /&gt;
&lt;br /&gt;
This is valid for 1:1 mappings and is faster than stateful NAT. However, it&#039;s easy to shoot yourself in the foot.&lt;br /&gt;
If your environment doesn&#039;t require this approach, better stick to stateful NAT.&lt;br /&gt;
&lt;br /&gt;
You have to disable connection tracking for modified packets. This can be accomplished by incorporating the &amp;quot;notrack&amp;quot; keyword into the rule. Doing so attaches a template connection tracking entry to the packet that instructs the conntrack core not to initialize a new entry in the connection tracking table.&lt;br /&gt;
&lt;br /&gt;
The examples below set IP/port for each packet (also for IPv6):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule ip raw prerouting ip protocol tcp ip daddr set 192.168.1.100 tcp dport set 10 notrack&lt;br /&gt;
% nft add rule ip6 raw prerouting ip6 nexthdr tcp ip6 daddr set fe00::1 tcp dport set 10 notrack&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to check our documentation regarding [[Mangling_packet_headers|mangling packets]] and [[setting packet connection tracking metainformation]].&lt;br /&gt;
&lt;br /&gt;
To use this feature you require nftables &amp;gt;=0.7 and linux kernel &amp;gt;= 4.9.&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Multiple_NATs_using_nftables_maps | Example: multiple NATs using nftables maps]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Logging_traffic&amp;diff=1099</id>
		<title>Logging traffic</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Logging_traffic&amp;diff=1099"/>
		<updated>2023-12-19T13:24:05Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Employ the https:// scheme for the links&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note&#039;&#039;&#039;: Full logging support is available starting Linux kernel 3.17. If you run an older kernel, you have to modprobe ipt_LOG to enable logging.&lt;br /&gt;
&lt;br /&gt;
You can log packets using the &#039;&#039;log&#039;&#039; action. The most simple rule to log all incoming traffic is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input log&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A typical rule match, log and accept incoming &#039;&#039;ssh&#039;&#039; traffic looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input tcp dport 22 ct state new log prefix \&amp;quot;New SSH connection: \&amp;quot; accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The prefix indicates the initial string that is used as prefix for the log message.&lt;br /&gt;
&lt;br /&gt;
Note that nftables allows to perform two actions in one single rule, contrary to &#039;&#039;iptables&#039;&#039; which required two rules for this.&lt;br /&gt;
&lt;br /&gt;
Also note that the rule is evaluated from the left to the right. So the following rule:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter input iif lo log tcp dport 22 accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
will log all packets coming on lo interface and not only the ones with destination port 22.&lt;br /&gt;
&lt;br /&gt;
= Queueing logging to userspace =&lt;br /&gt;
&lt;br /&gt;
As in iptables, you can use the existing &#039;&#039;nflog&#039;&#039; infrastructure to send log messages to [https://www.netfilter.org/projects/ulogd/ ulogd] or your custom userspace application based on [https://www.netfilter.org/projects/libnetfilter_log/ libnetfilter_log].&lt;br /&gt;
&lt;br /&gt;
To do so, you only have to indicate the &#039;&#039;nflog&#039;&#039; group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input tcp dport 22 ct state new log prefix \&amp;quot;New SSH connection: \&amp;quot; group 0 accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, run the example test application:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
libnetfilter_log/utils% ./nfulnl_test&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you&#039;ll start seeing log messages for each new &#039;&#039;ssh&#039;&#039; connection.&lt;br /&gt;
&lt;br /&gt;
= Log flags =&lt;br /&gt;
&lt;br /&gt;
Since nftables v0.7, log flags are supported.&lt;br /&gt;
&lt;br /&gt;
Enable logging of TCP sequence and options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags tcp sequence,options&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable IP options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags ip options&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable socket UID:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags skuid&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable ethernet link layer address:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags ether&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable all flags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags all&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Additional options =&lt;br /&gt;
&lt;br /&gt;
Some additional options exist to fine-tune logging in different scenarios:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039;: Syslog level of logging, a string of value: emerg, alert, crit, err, warn [default], notice, info, debug&lt;br /&gt;
* &#039;&#039;&#039;snaplen&#039;&#039;&#039;: Length of packet payload to include in netlink message (unsigned integer, 32 bit)&lt;br /&gt;
* &#039;&#039;&#039;queue-threshold&#039;&#039;&#039;: If queing logging to userspace, number of packets to queue inside the kernel before sending them to userspace (unsigned integer, 32 bit)&lt;br /&gt;
&lt;br /&gt;
In the example below, a queue-threshold parameter is used to increment ulogd2 daemon performance in userspace:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward ct state invalid log queue-threshold 20 prefix &amp;quot;ct_invalid&amp;quot; group 0 drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Logging_traffic&amp;diff=1098</id>
		<title>Logging traffic</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Logging_traffic&amp;diff=1098"/>
		<updated>2023-12-19T13:21:53Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Correct the link to the ulogd project&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Note&#039;&#039;&#039;: Full logging support is available starting Linux kernel 3.17. If you run an older kernel, you have to modprobe ipt_LOG to enable logging.&lt;br /&gt;
&lt;br /&gt;
You can log packets using the &#039;&#039;log&#039;&#039; action. The most simple rule to log all incoming traffic is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input log&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A typical rule match, log and accept incoming &#039;&#039;ssh&#039;&#039; traffic looks like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input tcp dport 22 ct state new log prefix \&amp;quot;New SSH connection: \&amp;quot; accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The prefix indicates the initial string that is used as prefix for the log message.&lt;br /&gt;
&lt;br /&gt;
Note that nftables allows to perform two actions in one single rule, contrary to &#039;&#039;iptables&#039;&#039; which required two rules for this.&lt;br /&gt;
&lt;br /&gt;
Also note that the rule is evaluated from the left to the right. So the following rule:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft add rule filter input iif lo log tcp dport 22 accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
will log all packets coming on lo interface and not only the ones with destination port 22.&lt;br /&gt;
&lt;br /&gt;
= Queueing logging to userspace =&lt;br /&gt;
&lt;br /&gt;
As in iptables, you can use the existing &#039;&#039;nflog&#039;&#039; infrastructure to send log messages to [http://www.netfilter.org/projects/ulogd/ ulogd] or your custom userspace application based on [http://www.netfilter.org/projects/libnetfilter_log/ libnetfilter_log].&lt;br /&gt;
&lt;br /&gt;
To do so, you only have to indicate the &#039;&#039;nflog&#039;&#039; group:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule filter input tcp dport 22 ct state new log prefix \&amp;quot;New SSH connection: \&amp;quot; group 0 accept&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, run the example test application:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
libnetfilter_log/utils% ./nfulnl_test&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And you&#039;ll start seeing log messages for each new &#039;&#039;ssh&#039;&#039; connection.&lt;br /&gt;
&lt;br /&gt;
= Log flags =&lt;br /&gt;
&lt;br /&gt;
Since nftables v0.7, log flags are supported.&lt;br /&gt;
&lt;br /&gt;
Enable logging of TCP sequence and options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags tcp sequence,options&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable IP options:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags ip options&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable socket UID:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags skuid&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable ethernet link layer address:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags ether&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Enable all flags:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule x y log flags all&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Additional options =&lt;br /&gt;
&lt;br /&gt;
Some additional options exist to fine-tune logging in different scenarios:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;level&#039;&#039;&#039;: Syslog level of logging, a string of value: emerg, alert, crit, err, warn [default], notice, info, debug&lt;br /&gt;
* &#039;&#039;&#039;snaplen&#039;&#039;&#039;: Length of packet payload to include in netlink message (unsigned integer, 32 bit)&lt;br /&gt;
* &#039;&#039;&#039;queue-threshold&#039;&#039;&#039;: If queing logging to userspace, number of packets to queue inside the kernel before sending them to userspace (unsigned integer, 32 bit)&lt;br /&gt;
&lt;br /&gt;
In the example below, a queue-threshold parameter is used to increment ulogd2 daemon performance in userspace:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
% nft add rule filter forward ct state invalid log queue-threshold 20 prefix &amp;quot;ct_invalid&amp;quot; group 0 drop&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Quick_reference-nftables_in_10_minutes&amp;diff=1093</id>
		<title>Quick reference-nftables in 10 minutes</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Quick_reference-nftables_in_10_minutes&amp;diff=1093"/>
		<updated>2023-08-29T13:20:41Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Correct one of the udp sport examples&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Find below some basic concepts to know before using nftables.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;table&#039;&#039;&#039; refers to a container of [[Configuring chains|chains]] with no specific semantics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;chain&#039;&#039;&#039; within a [[Configuring tables|table]] refers to a container of [[Simple rule management|rules]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;rule&#039;&#039;&#039; refers to an action to be configured within a &#039;&#039;chain&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= nft command line =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;nft&#039;&#039; is the command line tool in order to interact with nftables at userspace.&lt;br /&gt;
&lt;br /&gt;
== Tables ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;family&#039;&#039;&#039; refers to a one of the following table types: &#039;&#039;ip&#039;&#039;, &#039;&#039;arp&#039;&#039;, &#039;&#039;ip6&#039;&#039;, &#039;&#039;bridge&#039;&#039;, &#039;&#039;inet&#039;&#039;, &#039;&#039;netdev&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list tables [&amp;lt;family&amp;gt;]&lt;br /&gt;
% nft list table [&amp;lt;family&amp;gt;] &amp;lt;name&amp;gt; [-n] [-a]&lt;br /&gt;
% nft (add | delete | flush) table [&amp;lt;family&amp;gt;] &amp;lt;name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The argument &#039;&#039;-n&#039;&#039; shows the addresses and other information that uses names in numeric format. The &#039;&#039;-a&#039;&#039; argument is used to display the &#039;&#039;handle&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Chains ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;type&#039;&#039;&#039; refers to the kind of chain to be created. Possible types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;filter&#039;&#039;: Supported by &#039;&#039;arp&#039;&#039;, &#039;&#039;bridge&#039;&#039;, &#039;&#039;ip&#039;&#039;, &#039;&#039;ip6&#039;&#039; and &#039;&#039;inet&#039;&#039; table families.&lt;br /&gt;
* &#039;&#039;route&#039;&#039;: Mark packets (like mangle for the &#039;&#039;output&#039;&#039; hook, for other hooks use the type &#039;&#039;filter&#039;&#039; instead), supported by &#039;&#039;ip&#039;&#039; and &#039;&#039;ip6&#039;&#039;.&lt;br /&gt;
* &#039;&#039;nat&#039;&#039;: In order to perform Network Address Translation, supported by &#039;&#039;ip&#039;&#039; and &#039;&#039;ip6&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;hook&#039;&#039;&#039; refers to an specific stage of the packet while it&#039;s being processed through the kernel. More info in [[Netfilter_hooks|Netfilter hooks]].&lt;br /&gt;
&lt;br /&gt;
* The hooks for &#039;&#039;ip&#039;&#039;, &#039;&#039;ip6&#039;&#039; and &#039;&#039;inet&#039;&#039; families are: &#039;&#039;prerouting&#039;&#039;, &#039;&#039;input&#039;&#039;, &#039;&#039;forward&#039;&#039;, &#039;&#039;output&#039;&#039;, &#039;&#039;postrouting&#039;&#039;.&lt;br /&gt;
* The hooks for &#039;&#039;arp&#039;&#039; family are: &#039;&#039; input&#039;&#039;, &#039;&#039;output&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;bridge&#039;&#039; family handles ethernet packets traversing bridge devices.&lt;br /&gt;
* The hook for &#039;&#039;netdev&#039;&#039; is: &#039;&#039;ingress&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;priority&#039;&#039;&#039; refers to a number used to order the chains or to set them between some Netfilter operations. Possible values are: &#039;&#039;NF_IP_PRI_CONNTRACK_DEFRAG (-400)&#039;&#039;, &#039;&#039;NF_IP_PRI_RAW (-300)&#039;&#039;, &#039;&#039;NF_IP_PRI_SELINUX_FIRST (-225)&#039;&#039;, &#039;&#039;NF_IP_PRI_CONNTRACK (-200)&#039;&#039;, &#039;&#039;NF_IP_PRI_MANGLE (-150)&#039;&#039;, &#039;&#039;NF_IP_PRI_NAT_DST (-100)&#039;&#039;, &#039;&#039;NF_IP_PRI_FILTER (0)&#039;&#039;, &#039;&#039;NF_IP_PRI_SECURITY (50)&#039;&#039;, &#039;&#039;NF_IP_PRI_NAT_SRC (100)&#039;&#039;, &#039;&#039;NF_IP_PRI_SELINUX_LAST (225)&#039;&#039;, &#039;&#039;NF_IP_PRI_CONNTRACK_HELPER (300)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;policy&#039;&#039;&#039; is the default verdict statement to control the flow in the base chain. Possible values are: &#039;&#039;accept&#039;&#039; (default) and &#039;&#039;drop&#039;&#039;. Warning: Setting the policy to &#039;&#039;drop&#039;&#039; discards all packets that&lt;br /&gt;
have not been accepted by the ruleset.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft (add | create) chain [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;name&amp;gt; [ { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; [device &amp;lt;device&amp;gt;] priority &amp;lt;priority&amp;gt; \; [policy &amp;lt;policy&amp;gt; \;] } ]&lt;br /&gt;
% nft (delete | list | flush) chain [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;name&amp;gt;&lt;br /&gt;
% nft rename chain [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;name&amp;gt; &amp;lt;newname&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Rules ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;handle&#039;&#039;&#039; is an internal number that identifies a certain &#039;&#039;rule&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;position&#039;&#039;&#039; is an internal number that is used to insert a &#039;&#039;rule&#039;&#039; before a certain &#039;&#039;handle&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; &amp;lt;matches&amp;gt; &amp;lt;statements&amp;gt;&lt;br /&gt;
% nft insert rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; [position &amp;lt;position&amp;gt;] &amp;lt;matches&amp;gt; &amp;lt;statements&amp;gt;&lt;br /&gt;
% nft replace rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; [handle &amp;lt;handle&amp;gt;] &amp;lt;matches&amp;gt; &amp;lt;statements&amp;gt;&lt;br /&gt;
% nft delete rule [&amp;lt;family&amp;gt;] &amp;lt;table&amp;gt; &amp;lt;chain&amp;gt; [handle &amp;lt;handle&amp;gt;]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Matches ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;matches&#039;&#039;&#039; are clues used to access to certain packet information and create filters according to them.&lt;br /&gt;
&lt;br /&gt;
==== Ip ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ip match&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;dscp &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip dscp cs1&lt;br /&gt;
ip dscp != cs1&lt;br /&gt;
ip dscp 0x38&lt;br /&gt;
ip dscp != 0x20&lt;br /&gt;
ip dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, &lt;br /&gt;
af22, af23, af31, af32, af33, af41, af42, af43, ef}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Total packet length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip length 232&lt;br /&gt;
ip length != 233&lt;br /&gt;
ip length 333-435&lt;br /&gt;
ip length != 333-453&lt;br /&gt;
ip length { 333, 553, 673, 838}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;id&amp;gt;&#039;&#039;&lt;br /&gt;
| IP ID&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip id 22&lt;br /&gt;
ip id != 233&lt;br /&gt;
ip id 33-45&lt;br /&gt;
ip id != 33-45&lt;br /&gt;
ip id { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;frag-off &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Fragmentation offset&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip frag-off 222&lt;br /&gt;
ip frag-off != 233&lt;br /&gt;
ip frag-off 33-45&lt;br /&gt;
ip frag-off != 33-45&lt;br /&gt;
ip frag-off { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;ttl &amp;lt;ttl&amp;gt;&#039;&#039;&lt;br /&gt;
| Time to live&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip ttl 0&lt;br /&gt;
ip ttl 233&lt;br /&gt;
ip ttl 33-55&lt;br /&gt;
ip ttl != 45-50&lt;br /&gt;
ip ttl { 43, 53, 45 }&lt;br /&gt;
ip ttl { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;protocol &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| Upper layer protocol&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip protocol tcp&lt;br /&gt;
ip protocol 6&lt;br /&gt;
ip protocol != tcp&lt;br /&gt;
ip protocol { icmp, esp, ah, comp, udp, udplite, tcp, dccp, sctp }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip checksum 13172&lt;br /&gt;
ip checksum 22&lt;br /&gt;
ip checksum != 233&lt;br /&gt;
ip checksum 33-45&lt;br /&gt;
ip checksum != 33-45&lt;br /&gt;
ip checksum { 33, 55, 67, 88 }&lt;br /&gt;
ip checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;saddr &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip saddr 192.168.2.0/24&lt;br /&gt;
ip saddr != 192.168.2.0/24&lt;br /&gt;
ip saddr 192.168.3.1 ip daddr 192.168.3.100&lt;br /&gt;
ip saddr != 1.1.1.1&lt;br /&gt;
ip saddr 1.1.1.1&lt;br /&gt;
ip saddr &amp;amp; 0xff == 1&lt;br /&gt;
ip saddr &amp;amp; 0.0.0.255 &amp;lt; 0.0.0.127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;daddr &amp;lt;ip destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip daddr 192.168.0.1&lt;br /&gt;
ip daddr != 192.168.0.1&lt;br /&gt;
ip daddr 192.168.0.1-192.168.0.250&lt;br /&gt;
ip daddr 10.0.0.0-10.255.255.255&lt;br /&gt;
ip daddr 172.16.0.0-172.31.255.255&lt;br /&gt;
ip daddr 192.168.3.1-192.168.4.250&lt;br /&gt;
ip daddr != 192.168.0.1-192.168.0.250&lt;br /&gt;
ip daddr { 192.168.0.1-192.168.0.250 }&lt;br /&gt;
ip daddr { 192.168.5.1, 192.168.5.2, 192.168.5.3 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;version &amp;lt;version&amp;gt;&#039;&#039;&lt;br /&gt;
| Ip Header version&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip version 4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;header length&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip hdrlength 0&lt;br /&gt;
ip hdrlength 15&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Ip6 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ip6 match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dscp &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 dscp cs1&lt;br /&gt;
ip6 dscp != cs1&lt;br /&gt;
ip6 dscp 0x38&lt;br /&gt;
ip6 dscp != 0x20&lt;br /&gt;
ip6 dscp {cs0, cs1, cs2, cs3, cs4, cs5, cs6, cs7, af11, af12, af13, af21, af22, af23, af31, af32, af33, af41, af42, af43, ef}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;flowlabel &amp;lt;label&amp;gt;&#039;&#039;&lt;br /&gt;
| Flow label&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 flowlabel 22&lt;br /&gt;
ip6 flowlabel != 233&lt;br /&gt;
ip6 flowlabel { 33, 55, 67, 88 }&lt;br /&gt;
ip6 flowlabel { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Payload length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 length 232&lt;br /&gt;
ip6 length != 233&lt;br /&gt;
ip6 length 333-435&lt;br /&gt;
ip6 length != 333-453&lt;br /&gt;
ip6 length { 333, 553, 673, 838}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;header&amp;gt;&#039;&#039;&lt;br /&gt;
| Next header type (Upper layer protocol number)&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 nexthdr {esp, udp, ah, comp, udplite, tcp, dccp, sctp, icmpv6}&lt;br /&gt;
ip6 nexthdr esp&lt;br /&gt;
ip6 nexthdr != esp&lt;br /&gt;
ip6 nexthdr { 33-44 }&lt;br /&gt;
ip6 nexthdr 33-44&lt;br /&gt;
ip6 nexthdr != 33-44&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hoplimit &amp;lt;hoplimit&amp;gt;&#039;&#039;&lt;br /&gt;
| Hop limit&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 hoplimit 1&lt;br /&gt;
ip6 hoplimit != 233&lt;br /&gt;
ip6 hoplimit 33-45&lt;br /&gt;
ip6 hoplimit != 33-45&lt;br /&gt;
ip6 hoplimit {33, 55, 67, 88}&lt;br /&gt;
ip6 hoplimit {33-55}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;saddr &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source Address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 saddr 1234:1234:1234:1234:1234:1234:1234:1234&lt;br /&gt;
ip6 saddr ::1234:1234:1234:1234:1234:1234:1234&lt;br /&gt;
ip6 saddr ::/64&lt;br /&gt;
ip6 saddr ::1 ip6 daddr ::2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;daddr &amp;lt;ip destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination Address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 daddr 1234:1234:1234:1234:1234:1234:1234:1234&lt;br /&gt;
ip6 daddr != ::1234:1234:1234:1234:1234:1234:1234-1234:1234::1234:1234:1234:1234:1234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;version &amp;lt;version&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header version&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6 version 6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Tcp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|tcp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp dport 22&lt;br /&gt;
tcp dport != 33-45&lt;br /&gt;
tcp dport { 33-55 }&lt;br /&gt;
tcp dport {telnet, http, https }&lt;br /&gt;
tcp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
tcp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp sport 22&lt;br /&gt;
tcp sport != 33-45&lt;br /&gt;
tcp sport { 33, 55, 67, 88}&lt;br /&gt;
tcp sport { 33-55}&lt;br /&gt;
tcp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
tcp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Sequence number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp sequence 22&lt;br /&gt;
tcp sequence != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;ackseq &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Acknowledgement number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp ackseq 22&lt;br /&gt;
tcp ackseq != 33-45&lt;br /&gt;
tcp ackseq { 33, 55, 67, 88 }&lt;br /&gt;
tcp ackseq { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;flags &amp;lt;flags&amp;gt;&#039;&#039;&lt;br /&gt;
| TCP flags&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp flags { fin, syn, rst, psh, ack, urg, ecn, cwr}&lt;br /&gt;
tcp flags cwr&lt;br /&gt;
tcp flags != cwr&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;window &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Window&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp window 22&lt;br /&gt;
tcp window != 33-45&lt;br /&gt;
tcp window { 33, 55, 67, 88 }&lt;br /&gt;
tcp window { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| IP header checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp checksum 22&lt;br /&gt;
tcp checksum != 33-45&lt;br /&gt;
tcp checksum { 33, 55, 67, 88 }&lt;br /&gt;
tcp checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;urgptr &amp;lt;pointer&amp;gt;&#039;&#039;&lt;br /&gt;
| Urgent pointer&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp urgptr 22&lt;br /&gt;
tcp urgptr != 33-45&lt;br /&gt;
tcp urgptr { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;doff &amp;lt;offset&amp;gt;&#039;&#039;&lt;br /&gt;
| Data offset&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcp doff 8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Udp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|udp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp dport 22&lt;br /&gt;
udp dport != 33-45&lt;br /&gt;
udp dport { 33-55 }&lt;br /&gt;
udp dport {telnet, http, https }&lt;br /&gt;
udp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
udp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp sport 22&lt;br /&gt;
udp sport != 33-45&lt;br /&gt;
udp sport { 33, 55, 67, 88}&lt;br /&gt;
udp sport { 33-55}&lt;br /&gt;
udp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
udp sport 1024 udp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Total packet length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp length 6666&lt;br /&gt;
udp length != 50-65&lt;br /&gt;
udp length { 50, 65 }&lt;br /&gt;
udp length { 35-50 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| UDP checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udp checksum 22&lt;br /&gt;
udp checksum != 33-45&lt;br /&gt;
udp checksum { 33, 55, 67, 88 }&lt;br /&gt;
udp checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Udplite ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|udplite match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udplite dport 22&lt;br /&gt;
udplite dport != 33-45&lt;br /&gt;
udplite dport { 33-55 }&lt;br /&gt;
udplite dport {telnet, http, https }&lt;br /&gt;
udplite dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
udplite dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udplite sport 22&lt;br /&gt;
udplite sport != 33-45&lt;br /&gt;
udplite sport { 33, 55, 67, 88}&lt;br /&gt;
udplite sport { 33-55}&lt;br /&gt;
udplite sport vmap { 25:accept, 28:drop }&lt;br /&gt;
udplite sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| Checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
udplite checksum 22&lt;br /&gt;
udplite checksum != 33-45&lt;br /&gt;
udplite checksum { 33, 55, 67, 88 }&lt;br /&gt;
udplite checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Sctp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|sctp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp dport 22&lt;br /&gt;
sctp dport != 33-45&lt;br /&gt;
sctp dport { 33-55 }&lt;br /&gt;
sctp dport {telnet, http, https }&lt;br /&gt;
sctp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
sctp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp sport 22&lt;br /&gt;
sctp sport != 33-45&lt;br /&gt;
sctp sport { 33, 55, 67, 88}&lt;br /&gt;
sctp sport { 33-55}&lt;br /&gt;
sctp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
sctp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;checksum&amp;gt;&#039;&#039;&lt;br /&gt;
| Checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp checksum 22&lt;br /&gt;
sctp checksum != 33-45&lt;br /&gt;
sctp checksum { 33, 55, 67, 88 }&lt;br /&gt;
sctp checksum { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;vtag &amp;lt;tag&amp;gt;&#039;&#039;&lt;br /&gt;
| Verification tag&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp vtag 22&lt;br /&gt;
sctp vtag != 33-45&lt;br /&gt;
sctp vtag { 33, 55, 67, 88 }&lt;br /&gt;
sctp vtag { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;chunk &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| Existence of a chunk with given type in packet&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp chunk init exists&lt;br /&gt;
sctp chunk error missing&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;chunk &amp;lt;type&amp;gt; &amp;lt;field&amp;gt;&#039;&#039;&lt;br /&gt;
| A chunk&#039;s field value (implies chunk existence)&lt;br /&gt;
|&amp;lt;sourcex lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sctp chunk init flags 0x1&lt;br /&gt;
sctp chunk data tsn 0x23&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Dccp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|dccp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dport &amp;lt;destination port&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dccp dport 22&lt;br /&gt;
dccp dport != 33-45&lt;br /&gt;
dccp dport { 33-55 }&lt;br /&gt;
dccp dport {telnet, http, https }&lt;br /&gt;
dccp dport vmap { 22 : accept, 23 : drop }&lt;br /&gt;
dccp dport vmap { 25:accept, 28:drop }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sport &amp;lt; source port&amp;gt;&#039;&#039;&lt;br /&gt;
| Source port&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dccp sport 22&lt;br /&gt;
dccp sport != 33-45&lt;br /&gt;
dccp sport { 33, 55, 67, 88}&lt;br /&gt;
dccp sport { 33-55}&lt;br /&gt;
dccp sport vmap { 25:accept, 28:drop }&lt;br /&gt;
dccp sport 1024 tcp dport 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| Type of packet&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dccp type {request, response, data, ack, dataack, closereq, close, reset, sync, syncack}&lt;br /&gt;
dccp type request&lt;br /&gt;
dccp type != request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ah ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ah match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| AH header length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah hdrlength 11-23&lt;br /&gt;
ah hdrlength != 11-23&lt;br /&gt;
ah hdrlength {11, 23, 44 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;reserved &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah reserved 22&lt;br /&gt;
ah reserved != 33-45&lt;br /&gt;
ah reserved {23, 100 }&lt;br /&gt;
ah reserved { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;spi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah spi 111&lt;br /&gt;
ah spi != 111-222&lt;br /&gt;
ah spi {111, 122 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;sequence&amp;gt;&#039;&#039;&lt;br /&gt;
| Sequence Number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ah sequence 123&lt;br /&gt;
ah sequence {23, 25, 33}&lt;br /&gt;
ah sequence != 23-33&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Esp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|esp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;spi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
esp spi 111&lt;br /&gt;
esp spi != 111-222&lt;br /&gt;
esp spi {111, 122 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;sequence&amp;gt;&#039;&#039;&lt;br /&gt;
| Sequence Number&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
esp sequence 123&lt;br /&gt;
esp sequence {23, 25, 33}&lt;br /&gt;
esp sequence != 23-33&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Comp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|comp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| Next header protocol (Upper layer protocol)&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
comp nexthdr != esp&lt;br /&gt;
comp nexthdr {esp, ah, comp, udp, udplite, tcp, tcp, dccp, sctp}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;flags &amp;lt;flags&amp;gt;&#039;&#039;&lt;br /&gt;
| Flags&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
comp flags 0x0&lt;br /&gt;
comp flags != 0x33-0x45&lt;br /&gt;
comp flags {0x33, 0x55, 0x67, 0x88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cpi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Compression Parameter Index&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
comp cpi 22&lt;br /&gt;
comp cpi != 33-45&lt;br /&gt;
comp cpi {33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Icmp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|icmp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp type {echo-reply, destination-unreachable, source-quench, redirect, echo-request, time-exceeded, parameter-problem, timestamp-request, timestamp-reply, info-request, info-reply, address-mask-request, address-mask-reply, router-advertisement, router-solicitation}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;code &amp;lt;code&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet code&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp code 111&lt;br /&gt;
icmp code != 33-55&lt;br /&gt;
icmp code { 2, 4, 54, 33, 56}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp checksum 12343&lt;br /&gt;
icmp checksum != 11-343&lt;br /&gt;
icmp checksum { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet id&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp id 12343&lt;br /&gt;
icmp id != 11-343&lt;br /&gt;
icmp id { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet sequence&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp sequence 12343&lt;br /&gt;
icmp sequence != 11-343&lt;br /&gt;
icmp sequence { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mtu &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet mtu&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp mtu 12343&lt;br /&gt;
icmp mtu != 11-343&lt;br /&gt;
icmp mtu { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;gateway &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMP packet gateway&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmp gateway 12343&lt;br /&gt;
icmp gateway != 11-343&lt;br /&gt;
icmp gateway { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Icmpv6 ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|icmpv6 match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 type {destination-unreachable, packet-too-big, time-exceeded, echo-request, echo-reply, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, nd-redirect, parameter-problem, router-renumbering}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;code &amp;lt;code&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet code&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 code 4&lt;br /&gt;
icmpv6 code 3-66&lt;br /&gt;
icmpv6 code {5, 6, 7}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet checksum&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 checksum 12343&lt;br /&gt;
icmpv6 checksum != 11-343&lt;br /&gt;
icmpv6 checksum { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet id&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 id 12343&lt;br /&gt;
icmpv6 id != 11-343&lt;br /&gt;
icmpv6 id { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;sequence &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet sequence&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 sequence 12343&lt;br /&gt;
icmpv6 sequence != 11-343&lt;br /&gt;
icmpv6 sequence { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mtu &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet mtu&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 mtu 12343&lt;br /&gt;
icmpv6 mtu != 11-343&lt;br /&gt;
icmpv6 mtu { 1111, 222, 343 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;max-delay &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| ICMPv6 packet max delay&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
icmpv6 max-delay 33-45&lt;br /&gt;
icmpv6 max-delay != 33-45&lt;br /&gt;
icmpv6 max-delay {33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ether ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ether match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;saddr &amp;lt;mac address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source mac address&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ether saddr 00:0f:54:0c:11:04&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ether type vlan&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Dst ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|dst match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dst nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp}&lt;br /&gt;
dst nexthdr 22&lt;br /&gt;
dst nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dst hdrlength 22&lt;br /&gt;
dst hdrlength != 33-45&lt;br /&gt;
dst hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Frag ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|frag match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag nexthdr { udplite, comp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp, icmp}&lt;br /&gt;
frag nexthdr 6&lt;br /&gt;
frag nexthdr != 50-51&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;reserved &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag reserved 22&lt;br /&gt;
frag reserved != 33-45&lt;br /&gt;
frag reserved { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;frag-off &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag frag-off 22&lt;br /&gt;
frag frag-off != 33-45&lt;br /&gt;
frag frag-off { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;more-fragments &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag more-fragments 0&lt;br /&gt;
frag more-fragments 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
frag id 1&lt;br /&gt;
frag id 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Hbh ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|hbh match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
hbh nexthdr { udplite, comp, udp, ah, sctp, esp, dccp, tcp, icmpv6}&lt;br /&gt;
hbh nexthdr 22&lt;br /&gt;
hbh nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
hbh hdrlength 22&lt;br /&gt;
hbh hdrlength != 33-45&lt;br /&gt;
hbh hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Mh ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|mh match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }&lt;br /&gt;
mh nexthdr 22&lt;br /&gt;
mh nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh hdrlength 22&lt;br /&gt;
mh hdrlength != 33-45&lt;br /&gt;
mh hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh type {binding-refresh-request, home-test-init, careof-test-init, home-test, careof-test, binding-update, binding-acknowledgement, binding-error, fast-binding-update, fast-binding-acknowledgement, fast-binding-advertisement, experimental-mobility-header, home-agent-switch-message}&lt;br /&gt;
mh type home-agent-switch-message&lt;br /&gt;
mh type != home-agent-switch-message&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;reserved &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh reserved 22&lt;br /&gt;
mh reserved != 33-45&lt;br /&gt;
mh reserved { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;checksum &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mh checksum 22&lt;br /&gt;
mh checksum != 33-45&lt;br /&gt;
mh checksum { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Rt ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|rt match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nexthdr &amp;lt;proto&amp;gt;&#039;&#039;&lt;br /&gt;
| Next protocol header&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt nexthdr { udplite, ipcomp, udp, ah, sctp, esp, dccp, tcp, ipv6-icmp }&lt;br /&gt;
rt nexthdr 22&lt;br /&gt;
rt nexthdr != 33-45&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hdrlength &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt hdrlength 22&lt;br /&gt;
rt hdrlength != 33-45&lt;br /&gt;
rt hdrlength { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt type 22&lt;br /&gt;
rt type != 33-45&lt;br /&gt;
rt type { 33, 55, 67, 88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;seg-left &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rt seg-left 22&lt;br /&gt;
rt seg-left != 33-45&lt;br /&gt;
rt seg-left { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Vlan ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|vlan match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;id &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Vlan tag ID&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vlan id 4094&lt;br /&gt;
vlan id 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cfi &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vlan cfi 0&lt;br /&gt;
vlan cfi 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;pcp &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vlan pcp 7&lt;br /&gt;
vlan pcp 3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Arp ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|arp match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;ptype &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Payload type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp ptype 0x0800&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;htype &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Header type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp htype 1&lt;br /&gt;
arp htype != 33-45&lt;br /&gt;
arp htype { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;hlen &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Header Length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp hlen 1&lt;br /&gt;
arp hlen != 33-45&lt;br /&gt;
arp hlen { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;plen &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Payload length&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp plen 1&lt;br /&gt;
arp plen != 33-45&lt;br /&gt;
arp plen { 33, 55, 67, 88}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;operation &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arp operation {nak, inreply, inrequest, rreply, rrequest, reply, request}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ct ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|ct match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;state &amp;lt;state&amp;gt;&#039;&#039;&lt;br /&gt;
| State of the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct state { new, established, related, untracked }&lt;br /&gt;
ct state != related&lt;br /&gt;
ct state established&lt;br /&gt;
ct state 8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;direction &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| Direction of the packet relative to the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct direction original&lt;br /&gt;
ct direction != original&lt;br /&gt;
ct direction {reply, original}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;status &amp;lt;status&amp;gt;&#039;&#039;&lt;br /&gt;
| Status of the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct status expected&lt;br /&gt;
(ct status &amp;amp; expected) != expected&lt;br /&gt;
ct status {expected,seen-reply,assured,confirmed,snat,dnat,dying}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mark [set] &amp;lt;mark&amp;gt;&#039;&#039;&lt;br /&gt;
| Mark of the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct mark 0&lt;br /&gt;
ct mark or 0x23 == 0x11&lt;br /&gt;
ct mark or 0x3 != 0x1&lt;br /&gt;
ct mark and 0x23 == 0x11&lt;br /&gt;
ct mark and 0x3 != 0x1&lt;br /&gt;
ct mark xor 0x23 == 0x11&lt;br /&gt;
ct mark xor 0x3 != 0x1&lt;br /&gt;
ct mark 0x00000032&lt;br /&gt;
ct mark != 0x00000032&lt;br /&gt;
ct mark 0x00000032-0x00000045&lt;br /&gt;
ct mark != 0x00000032-0x00000045&lt;br /&gt;
ct mark {0x32, 0x2222, 0x42de3}&lt;br /&gt;
ct mark {0x32-0x2222, 0x4444-0x42de3}&lt;br /&gt;
ct mark set 0x11 xor 0x1331&lt;br /&gt;
ct mark set 0x11333 and 0x11&lt;br /&gt;
ct mark set 0x12 or 0x11&lt;br /&gt;
ct mark set 0x11&lt;br /&gt;
ct mark set mark&lt;br /&gt;
ct mark set mark map { 1 : 10, 2 : 20, 3 : 30 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;expiration &amp;lt;time&amp;gt;&#039;&#039;&lt;br /&gt;
| Connection expiration time&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct expiration 30&lt;br /&gt;
ct expiration 30s&lt;br /&gt;
ct expiration != 233&lt;br /&gt;
ct expiration != 3m53s&lt;br /&gt;
ct expiration 33-45&lt;br /&gt;
ct expiration 33s-45s&lt;br /&gt;
ct expiration != 33-45&lt;br /&gt;
ct expiration != 33s-45s&lt;br /&gt;
ct expiration {33, 55, 67, 88}&lt;br /&gt;
ct expiration { 1m7s, 33s, 55s, 1m28s}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;helper &amp;quot;&amp;lt;helper&amp;gt;&amp;quot;&#039;&#039;&lt;br /&gt;
| Helper associated with the connection&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct helper &amp;quot;ftp&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] bytes &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original bytes &amp;gt; 100000&lt;br /&gt;
ct bytes &amp;gt; 100000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] packets &amp;lt;value&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct reply packets &amp;lt; 100&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] ip saddr &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original ip saddr 192.168.0.1&lt;br /&gt;
ct reply ip saddr 192.168.0.1&lt;br /&gt;
ct original ip saddr 192.168.1.0/24&lt;br /&gt;
ct reply ip saddr 192.168.1.0/24&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] ip daddr &amp;lt;ip destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original ip daddr 192.168.0.1&lt;br /&gt;
ct reply ip daddr 192.168.0.1&lt;br /&gt;
ct original ip daddr 192.168.1.0/24&lt;br /&gt;
ct reply ip daddr 192.168.1.0/24&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] l3proto &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original l3proto ipv4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] protocol &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original protocol 6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] proto-dst &amp;lt;port&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct original proto-dst 22&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;[original | reply] proto-src &amp;lt;port&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct reply proto-src 53&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| | &#039;&#039;count [over] &amp;lt;number of connections&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ct count over 2&lt;br /&gt;
&lt;br /&gt;
tcp dport 22 add @ssh_flood { ip saddr ct count over 2 } reject&lt;br /&gt;
[ which requires an existing ssh_flood set, ie. add set filter ssh_flood { type ipv4_addr; flags dynamic; } ]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Meta ====&lt;br /&gt;
&lt;br /&gt;
[[Matching packet metainformation|&#039;&#039;meta&#039;&#039;]] matches packet by metainformation.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|meta match&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iifname &amp;lt;input interface name&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface name&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iifname &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta iifname != &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta iifname {&amp;quot;eth0&amp;quot;, &amp;quot;lo&amp;quot;}&lt;br /&gt;
meta iifname &amp;quot;eth*&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oifname &amp;lt;output interface name&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface name&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oifname &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta oifname != &amp;quot;eth0&amp;quot;&lt;br /&gt;
meta oifname {&amp;quot;eth0&amp;quot;, &amp;quot;lo&amp;quot;}&lt;br /&gt;
meta oifname &amp;quot;eth*&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iif &amp;lt;input interface index&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface index&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iif eth0&lt;br /&gt;
meta iif != eth0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oif &amp;lt;output interface index&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface index&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oif lo&lt;br /&gt;
meta oif != lo&lt;br /&gt;
meta oif {eth0, lo}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iiftype &amp;lt;input interface type&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}&lt;br /&gt;
meta iiftype != ether&lt;br /&gt;
meta iiftype ether&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oiftype &amp;lt;output interface type&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface hardware type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oiftype {ether, ppp, ipip, ipip6, loopback, sit, ipgre}&lt;br /&gt;
meta oiftype != ether&lt;br /&gt;
meta oiftype ether&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;length &amp;lt;length&amp;gt;&#039;&#039;&lt;br /&gt;
| Length of the packet in bytes&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta length 1000&lt;br /&gt;
meta length != 1000&lt;br /&gt;
meta length &amp;gt; 1000&lt;br /&gt;
meta length 33-45&lt;br /&gt;
meta length != 33-45&lt;br /&gt;
meta length { 33, 55, 67, 88 }&lt;br /&gt;
meta length { 33-55, 67-88 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;protocol &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| ethertype protocol&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta protocol ip&lt;br /&gt;
meta protocol != ip&lt;br /&gt;
meta protocol { ip, arp, ip6, vlan }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;nfproto &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta nfproto ipv4&lt;br /&gt;
meta nfproto != ipv6&lt;br /&gt;
meta nfproto { ipv4, ipv6 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;l4proto &amp;lt;protocol&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta l4proto 22&lt;br /&gt;
meta l4proto != 233&lt;br /&gt;
meta l4proto 33-45&lt;br /&gt;
meta l4proto { 33, 55, 67, 88 }&lt;br /&gt;
meta l4proto { 33-55 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;mark [set] &amp;lt;mark&amp;gt;&#039;&#039;&lt;br /&gt;
| Packet mark&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta mark 0x4&lt;br /&gt;
meta mark 0x00000032&lt;br /&gt;
meta mark and 0x03 == 0x01&lt;br /&gt;
meta mark and 0x03 != 0x01&lt;br /&gt;
meta mark != 0x10&lt;br /&gt;
meta mark or 0x03 == 0x01&lt;br /&gt;
meta mark or 0x03 != 0x01&lt;br /&gt;
meta mark xor 0x03 == 0x01&lt;br /&gt;
meta mark xor 0x03 != 0x01&lt;br /&gt;
meta mark set 0xffffffc8 xor 0x16&lt;br /&gt;
meta mark set 0x16 and 0x16&lt;br /&gt;
meta mark set 0xffffffe9 or 0x16&lt;br /&gt;
meta mark set 0xffffffde and 0x16&lt;br /&gt;
meta mark set 0x32 or 0xfffff&lt;br /&gt;
meta mark set 0xfffe xor 0x16&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;priority [set] &amp;lt;priority&amp;gt;&#039;&#039;&lt;br /&gt;
| tc class id&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta priority none&lt;br /&gt;
meta priority 0x1:0x1&lt;br /&gt;
meta priority 0x1:0xffff&lt;br /&gt;
meta priority 0xffff:0xffff&lt;br /&gt;
meta priority set 0x1:0x1&lt;br /&gt;
meta priority set 0x1:0xffff&lt;br /&gt;
meta priority set 0xffff:0xffff&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;skuid &amp;lt;user id&amp;gt;&#039;&#039;&lt;br /&gt;
| UID associated with originating socket&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta skuid {bin, root, daemon}&lt;br /&gt;
meta skuid root&lt;br /&gt;
meta skuid != root&lt;br /&gt;
meta skuid lt 3000&lt;br /&gt;
meta skuid gt 3000&lt;br /&gt;
meta skuid eq 3000&lt;br /&gt;
meta skuid 3001-3005&lt;br /&gt;
meta skuid != 2001-2005&lt;br /&gt;
meta skuid { 2001-2005 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;skgid &amp;lt;group id&amp;gt;&#039;&#039;&lt;br /&gt;
| GID associated with originating socket&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta skgid {bin, root, daemon}&lt;br /&gt;
meta skgid root&lt;br /&gt;
meta skgid != root&lt;br /&gt;
meta skgid lt 3000&lt;br /&gt;
meta skgid gt 3000&lt;br /&gt;
meta skgid eq 3000&lt;br /&gt;
meta skgid 3001-3005&lt;br /&gt;
meta skgid != 2001-2005&lt;br /&gt;
meta skgid { 2001-2005 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;rtclassid &amp;lt;class&amp;gt;&#039;&#039;&lt;br /&gt;
| Routing realm&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta rtclassid cosmos&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;pkttype &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| Packet type&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta pkttype broadcast&lt;br /&gt;
meta pkttype != broadcast&lt;br /&gt;
meta pkttype { broadcast, unicast, multicast}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cpu &amp;lt;cpu index&amp;gt;&#039;&#039;&lt;br /&gt;
| CPU ID&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta cpu 1&lt;br /&gt;
meta cpu != 1&lt;br /&gt;
meta cpu 1-3&lt;br /&gt;
meta cpu != 1-2&lt;br /&gt;
meta cpu { 2,3 }&lt;br /&gt;
meta cpu { 2-3, 5-7 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;iifgroup &amp;lt;input group&amp;gt;&#039;&#039;&lt;br /&gt;
| Input interface group&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta iifgroup 0&lt;br /&gt;
meta iifgroup != 0&lt;br /&gt;
meta iifgroup default&lt;br /&gt;
meta iifgroup != default&lt;br /&gt;
meta iifgroup {default}&lt;br /&gt;
meta iifgroup { 11,33 }&lt;br /&gt;
meta iifgroup {11-33}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;oifgroup &amp;lt;group&amp;gt;&#039;&#039;&lt;br /&gt;
| Output interface group&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta oifgroup 0&lt;br /&gt;
meta oifgroup != 0&lt;br /&gt;
meta oifgroup default&lt;br /&gt;
meta oifgroup != default&lt;br /&gt;
meta oifgroup {default}&lt;br /&gt;
meta oifgroup { 11,33 }&lt;br /&gt;
meta oifgroup {11-33}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;cgroup &amp;lt;group&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
meta cgroup 1048577&lt;br /&gt;
meta cgroup != 1048577&lt;br /&gt;
meta cgroup { 1048577, 1048578 }&lt;br /&gt;
meta cgroup 1048577-1048578&lt;br /&gt;
meta cgroup != 1048577-1048578&lt;br /&gt;
meta cgroup {1048577-1048578}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Statements ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;statement&#039;&#039;&#039; is the action performed when the packet match the rule. It could be &#039;&#039;terminal&#039;&#039; and &#039;&#039;non-terminal&#039;&#039;. In a certain rule we can consider several non-terminal statements but only a single terminal statement.&lt;br /&gt;
&lt;br /&gt;
==== Verdict statements ====&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;verdict statement&#039;&#039;&#039; alters control flow in the ruleset and issues policy decisions for packets. The valid verdict statements are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;accept&#039;&#039;: Accept the packet and stop the remain rules evaluation.&lt;br /&gt;
* &#039;&#039;drop&#039;&#039;: Drop the packet and stop the remain rules evaluation.&lt;br /&gt;
* &#039;&#039;queue&#039;&#039;: Queue the packet to userspace and stop the remain rules evaluation.&lt;br /&gt;
* &#039;&#039;continue&#039;&#039;: Continue the ruleset evaluation with the next rule.&lt;br /&gt;
* &#039;&#039;return&#039;&#039;: Return from the current chain and continue at the next rule of the last chain. In a base chain it is equivalent to accept&lt;br /&gt;
* &#039;&#039;jump &amp;lt;chain&amp;gt;&#039;&#039;: Continue at the first rule of &amp;lt;chain&amp;gt;. It will continue at the next rule after a return statement is issued&lt;br /&gt;
* &#039;&#039;goto &amp;lt;chain&amp;gt;&#039;&#039;: Similar to jump, but after the new chain the evaluation will continue at the last chain instead of the one containing the goto statement&lt;br /&gt;
&lt;br /&gt;
==== Log ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|log statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;level [over] &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt; [burst &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt;]&#039;&#039;&lt;br /&gt;
| Log level&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
log&lt;br /&gt;
log level emerg&lt;br /&gt;
log level alert&lt;br /&gt;
log level crit&lt;br /&gt;
log level err&lt;br /&gt;
log level warn&lt;br /&gt;
log level notice&lt;br /&gt;
log level info&lt;br /&gt;
log level debug&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;group &amp;lt;value&amp;gt; [queue-threshold &amp;lt;value&amp;gt;] [snaplen &amp;lt;value&amp;gt;] [prefix &amp;quot;&amp;lt;prefix&amp;gt;&amp;quot;]&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
log prefix aaaaa-aaaaaa group 2 snaplen 33&lt;br /&gt;
log group 2 queue-threshold 2&lt;br /&gt;
log group 2 snaplen 33&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Reject ====&lt;br /&gt;
&lt;br /&gt;
The default &#039;&#039;&#039;reject&#039;&#039;&#039; will be the ICMP type &#039;&#039;&#039;port-unreachable&#039;&#039;&#039;. The &#039;&#039;&#039;icmpx&#039;&#039;&#039; is only used for inet family support.&lt;br /&gt;
&lt;br /&gt;
More information on the [[Rejecting_traffic]] page.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|reject statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;with &amp;lt;protocol&amp;gt; type &amp;lt;type&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
reject&lt;br /&gt;
reject with icmp type host-unreachable&lt;br /&gt;
reject with icmp type net-unreachable&lt;br /&gt;
reject with icmp type prot-unreachable&lt;br /&gt;
reject with icmp type port-unreachable&lt;br /&gt;
reject with icmp type net-prohibited&lt;br /&gt;
reject with icmp type host-prohibited&lt;br /&gt;
reject with icmp type admin-prohibited&lt;br /&gt;
reject with icmpv6 type no-route&lt;br /&gt;
reject with icmpv6 type admin-prohibited&lt;br /&gt;
reject with icmpv6 type addr-unreachable&lt;br /&gt;
reject with icmpv6 type port-unreachable&lt;br /&gt;
reject with icmpx type host-unreachable&lt;br /&gt;
reject with icmpx type no-route&lt;br /&gt;
reject with icmpx type admin-prohibited&lt;br /&gt;
reject with icmpx type port-unreachable&lt;br /&gt;
ip protocol tcp reject with tcp reset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Counter ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|counter statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;packets &amp;lt;packets&amp;gt; bytes &amp;lt;bytes&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
counter&lt;br /&gt;
counter packets 0 bytes 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Limit ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|limit statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;rate [over] &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt; [burst &amp;lt;value&amp;gt; &amp;lt;unit&amp;gt;]&#039;&#039;&lt;br /&gt;
| Rate limit&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
limit rate 400/minute&lt;br /&gt;
limit rate 400/hour&lt;br /&gt;
limit rate over 40/day&lt;br /&gt;
limit rate over 400/week&lt;br /&gt;
limit rate over 1023/second burst 10 packets&lt;br /&gt;
limit rate 1025 kbytes/second&lt;br /&gt;
limit rate 1023000 mbytes/second&lt;br /&gt;
limit rate 1025 bytes/second burst 512 bytes&lt;br /&gt;
limit rate 1025 kbytes/second burst 1023 kbytes&lt;br /&gt;
limit rate 1025 mbytes/second burst 1025 kbytes&lt;br /&gt;
limit rate 1025000 mbytes/second burst 1023 mbytes&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Nat ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|nat statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;dnat to &amp;lt;destination address&amp;gt;&#039;&#039;&lt;br /&gt;
| Destination address translation&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dnat to 192.168.3.2&lt;br /&gt;
dnat to ct mark map { 0x00000014 : 1.2.3.4}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;snat to &amp;lt;ip source address&amp;gt;&#039;&#039;&lt;br /&gt;
| Source address translation&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
snat to 192.168.3.2&lt;br /&gt;
snat to 2001:838:35f:1::-2001:838:35f:2:::100&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;masquerade [&amp;lt;type&amp;gt;] [to :&amp;lt;port&amp;gt;]&#039;&#039;&lt;br /&gt;
| Masquerade&lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
masquerade&lt;br /&gt;
masquerade persistent,fully-random,random&lt;br /&gt;
masquerade to :1024&lt;br /&gt;
masquerade to :1024-2048&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Queue ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;6&amp;quot;|queue statement&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;num &amp;lt;value&amp;gt; &amp;lt;scheduler&amp;gt;&#039;&#039;&lt;br /&gt;
| &lt;br /&gt;
|&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
queue&lt;br /&gt;
queue num 2&lt;br /&gt;
queue num 2-3&lt;br /&gt;
queue num 4-5 fanout bypass&lt;br /&gt;
queue num 4-5 fanout&lt;br /&gt;
queue num 4-5 bypass&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Extras ==&lt;br /&gt;
&lt;br /&gt;
=== Export Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft export (xml | json)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Monitor Events ===&lt;br /&gt;
&lt;br /&gt;
Monitor events from Netlink creating filters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft monitor [new | destroy] [tables | chains | sets | rules | elements] [xml | json]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Nft scripting =&lt;br /&gt;
&lt;br /&gt;
== List ruleset ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list ruleset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Flush ruleset ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft flush ruleset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Load ruleset ==&lt;br /&gt;
&lt;br /&gt;
Create a command batch file and load it with the nft interpreter,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% echo &amp;quot;flush ruleset&amp;quot; &amp;gt; /etc/nftables.rules&lt;br /&gt;
% echo &amp;quot;add table filter&amp;quot; &amp;gt;&amp;gt; /etc/nftables.rules&lt;br /&gt;
% echo &amp;quot;add chain filter input&amp;quot; &amp;gt;&amp;gt; /etc/nftables.rules&lt;br /&gt;
% echo &amp;quot;add rule filter input meta iifname lo accept&amp;quot; &amp;gt;&amp;gt; /etc/nftables.rules&lt;br /&gt;
% nft -f /etc/nftables.rules&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or create an executable nft script file,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% cat &amp;lt;&amp;lt; EOF &amp;gt; /etc/nftables.rules&lt;br /&gt;
&amp;gt; #!/usr/local/sbin/nft -f&lt;br /&gt;
&amp;gt; flush ruleset&lt;br /&gt;
&amp;gt; add table filter&lt;br /&gt;
&amp;gt; add chain filter input&lt;br /&gt;
&amp;gt; add rule filter input meta iifname lo accept&lt;br /&gt;
&amp;gt; EOF&lt;br /&gt;
% chmod u+x /etc/nftables.rules&lt;br /&gt;
% /etc/nftables.rules&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or create an executable nft script file from an already created ruleset,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft list ruleset &amp;gt; /etc/nftables.rules&lt;br /&gt;
% nft flush ruleset&lt;br /&gt;
% nft -f /etc/nftables.rules&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
== Simple IP/IPv6 Firewall ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
flush ruleset&lt;br /&gt;
&lt;br /&gt;
table firewall {&lt;br /&gt;
  chain incoming {&lt;br /&gt;
    type filter hook input priority 0; policy drop;&lt;br /&gt;
&lt;br /&gt;
    # established/related connections&lt;br /&gt;
    ct state established,related accept&lt;br /&gt;
&lt;br /&gt;
    # loopback interface&lt;br /&gt;
    iifname lo accept&lt;br /&gt;
&lt;br /&gt;
    # icmp&lt;br /&gt;
    icmp type echo-request accept&lt;br /&gt;
&lt;br /&gt;
    # open tcp ports: sshd (22), httpd (80)&lt;br /&gt;
    tcp dport {ssh, http} accept&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
table ip6 firewall {&lt;br /&gt;
  chain incoming {&lt;br /&gt;
    type filter hook input priority 0; policy drop;&lt;br /&gt;
&lt;br /&gt;
    # established/related connections&lt;br /&gt;
    ct state established,related accept&lt;br /&gt;
&lt;br /&gt;
    # invalid connections&lt;br /&gt;
    ct state invalid drop&lt;br /&gt;
&lt;br /&gt;
    # loopback interface&lt;br /&gt;
    iifname lo accept&lt;br /&gt;
&lt;br /&gt;
    # icmp&lt;br /&gt;
    # routers may also want: mld-listener-query, nd-router-solicit&lt;br /&gt;
    icmpv6 type {echo-request,nd-neighbor-solicit} accept&lt;br /&gt;
&lt;br /&gt;
    # open tcp ports: sshd (22), httpd (80)&lt;br /&gt;
    tcp dport {ssh, http} accept&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Flowtables&amp;diff=1069</id>
		<title>Flowtables</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Flowtables&amp;diff=1069"/>
		<updated>2022-06-24T06:35:20Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Add missing semi-colon in hook.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;NOTE&#039;&#039;&#039;: [[Meters]] were formerly known as flowtables before nftables 0.8.1 release. Now they are 2 separated, unrelated things.&lt;br /&gt;
&lt;br /&gt;
Flowtables allow you to accelerate packet forwarding in software (and in hardware if your NIC supports it) by using a conntrack-based network stack bypass.&lt;br /&gt;
&lt;br /&gt;
Entries are represented through a tuple that is composed of the input interface, source and destination address, source and destination port; and layer 3/4&lt;br /&gt;
protocols. Each entry also caches the destination interface and the gateway address (to update the destination link-layer address) to forward packets.&lt;br /&gt;
&lt;br /&gt;
The TTL and hoplimit fields are also decremented. Hence, flowtables provides an alternative path that allow packets to bypass the classic forwarding path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                                         userspace process&lt;br /&gt;
                                          ^              |&lt;br /&gt;
                                          |              |&lt;br /&gt;
                                     _____|____     ____\/___&lt;br /&gt;
                                    /          \   /         \&lt;br /&gt;
                                    |   input  |   |  output |&lt;br /&gt;
                                    \__________/   \_________/&lt;br /&gt;
                                         ^               |&lt;br /&gt;
                                         |               |&lt;br /&gt;
      _________      __________      ---------     _____\/_____&lt;br /&gt;
     /         \    /          \     |Routing |   /            \&lt;br /&gt;
  --&amp;gt;  ingress  ---&amp;gt; prerouting ---&amp;gt; |decision|   | postrouting|--&amp;gt; neigh_xmit&lt;br /&gt;
     \_________/    \__________/     ----------   \____________/          ^&lt;br /&gt;
       |      ^                          |               ^                |&lt;br /&gt;
   flowtable  |                     ____\/___            |                |&lt;br /&gt;
       |      |                    /         \           |                |&lt;br /&gt;
    __\/___   |                    | forward |------------                |&lt;br /&gt;
    |-----|   |                    \_________/                            |&lt;br /&gt;
    |-----|   |                 &#039;flow offload&#039; rule                       |&lt;br /&gt;
    |-----|   |                   adds entry to                           |&lt;br /&gt;
    |_____|   |                     flowtable                             |&lt;br /&gt;
       |      |                                                           |&lt;br /&gt;
      / \     |                                                           |&lt;br /&gt;
     /hit\_no_|                                                           |&lt;br /&gt;
     \ ? /                                                                |&lt;br /&gt;
      \ /                                                                 |&lt;br /&gt;
       |__yes_________________fastpath bypass ____________________________|&lt;br /&gt;
&lt;br /&gt;
               Fig.1 Netfilter hooks and flowtable interactions&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Flowtables reside in the ingress hook that is located before the prerouting hook. You can select which flows you want to offload through the flow expression from the forward chain. Flowtables are identified by their address [[Nftables_families|family]] and their name. The address family must be one of ip, ip6, or inet. When no address family is specified, ip is used by default.&lt;br /&gt;
&lt;br /&gt;
Flows are offloaded after the state is created. That means that usually the first reply packet will create the flowtable entry.&lt;br /&gt;
A firewall rule to accept the initial traffic is required.&lt;br /&gt;
The flow expression on the forward chain must match the return traffic of the initial connection.&lt;br /&gt;
Be aware that the return route is deducted from the packet, that creates the flowtable entry.&lt;br /&gt;
This also means if you are using special ip rules, you need to make sure that they match the reply packet traffic as well as the original traffic.&lt;br /&gt;
&lt;br /&gt;
The *priority* can be a signed integer or *filter* which stands for 0. Addition and subtraction can be used to set relative priority, e.g. filter + 5 equals to 5.&lt;br /&gt;
&lt;br /&gt;
The *devices* are specified as [[Data_types|iifname]](s) of the input interface(s) of the traffic that should be offloaded. Devices are required for both traffic directions.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet x {&lt;br /&gt;
&lt;br /&gt;
    flowtable f {&lt;br /&gt;
        hook ingress priority 0; devices = { eth0, eth1 };&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    chain forward {&lt;br /&gt;
        type filter hook forward priority 0; policy drop;&lt;br /&gt;
&lt;br /&gt;
        # offload established connections&lt;br /&gt;
        ip protocol { tcp, udp } flow offload @f&lt;br /&gt;
        ip6 nexthdr { tcp, udp } flow offload @f&lt;br /&gt;
        counter packets 0 bytes 0&lt;br /&gt;
&lt;br /&gt;
        # established/related connections&lt;br /&gt;
        ct state established,related counter accept&lt;br /&gt;
&lt;br /&gt;
        # allow initial connection&lt;br /&gt;
        ip protocol { tcp, udp } accept&lt;br /&gt;
        ip6 nexthdr { tcp, udp } accept&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.kernel.org/doc/html/latest/networking/nf_flowtable.html Linux kernel documentation on Netfilter flowtable]&lt;br /&gt;
* [https://netdevconf.info/0x13/session.html?workshop-netfilter-mini Netfilter Mini-Workshop, Netdev 0x13, 2019-03]&lt;br /&gt;
* [https://lwn.net/Articles/804384/ Mellanox flowtable hardware offload]&lt;br /&gt;
* [https://www.programmersought.com/article/11833283913/ Some Mellanox flowtable hardware offload performance measurements by Wen Xu of UCloud]&lt;br /&gt;
* [https://linuxplumbersconf.org/event/4/contributions/463/ Netfilter hardware offloads, Pablo Neira Ayuso, Linux Plumbers Conference, 2019-09]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=611</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=611"/>
		<updated>2020-12-30T22:45:04Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Correct wording concerning the default chain policy&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, you attach your [[Simple rule management|rules]] to chains. However, contrary to the &#039;&#039;iptables&#039;&#039; modus operandi, the &#039;&#039;nftables&#039;&#039; infrastructure comes with no predefined chains, so you need to register your base chains in first place before you can add any rule. This allows very flexible configurations.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
The syntax to add base chains is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain [&amp;lt;family&amp;gt;] &amp;lt;table-name&amp;gt; &amp;lt;chain-name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; priority &amp;lt;value&amp;gt; \; [policy &amp;lt;policy&amp;gt;] } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], ie. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The following example show how you can add new base chains to the &#039;&#039;foo&#039;&#039; table (that need to be created prior) through the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: nft re-uses special characters, such as curly braces and the semicolon.I&lt;br /&gt;
f you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need&lt;br /&gt;
to be escaped.  The most simple way to prevent the shell from attempting to parse the nft syntax&lt;br /&gt;
is to quote everything withing single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another.&lt;br /&gt;
For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order.  Its possible to give two base chains the same priority, but there&lt;br /&gt;
is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, ie. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a non-base chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is obviously used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). The first packet that belongs to a flow always hits this chain, follow up packets not. Therefore, never use this chain for filtering. This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible hooks that you can use when you configure your chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: the routing decision for those packets didn&#039;t happen yet, so you don&#039;t know if they are addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: It happens after the routing decision, you can see packets that are directed to the local system and processes running in system.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: It also happens after the routing decision, you can see packet that are not directed to the local machine.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: to catch packets that are originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: After the routing decision for packets leaving the local system.&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only available at the &#039;&#039;netdev&#039;&#039; family): Since Linux kernel 4.2, you can filter traffic way before prerouting, after the packet is passed up from the NIC driver. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
The priority can be used to order the chains or to put them before or after some Netfilter internal operations. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with the priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: starting with nftables 0.9.6 you may use keywords instead of numbers to configure the chain priority. Check the nft manpage for reference.&lt;br /&gt;
&lt;br /&gt;
For reference, here&#039;s the list of different priority used in iptables:&lt;br /&gt;
&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_DEFRAG (-400): priority of defragmentation&lt;br /&gt;
* NF_IP_PRI_RAW (-300): traditional priority of the raw table placed before connection tracking operation&lt;br /&gt;
* NF_IP_PRI_SELINUX_FIRST (-225): SELinux operations&lt;br /&gt;
* NF_IP_PRI_CONNTRACK (-200): Connection tracking operations&lt;br /&gt;
* NF_IP_PRI_MANGLE (-150): mangle operation&lt;br /&gt;
* NF_IP_PRI_NAT_DST (-100): destination NAT&lt;br /&gt;
* NF_IP_PRI_FILTER (0): filtering operation, the filter table&lt;br /&gt;
* NF_IP_PRI_SECURITY (50): Place of security table where secmark can be set for example&lt;br /&gt;
* NF_IP_PRI_NAT_SRC (100): source NAT&lt;br /&gt;
* NF_IP_PRI_SELINUX_LAST (225): SELinux at packet exit&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_HELPER (300): connection tracking at exit&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the default chain policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding non-base chains =&lt;br /&gt;
&lt;br /&gt;
You can also create non-base chains as in &#039;&#039;iptables&#039;&#039; via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this chain does &#039;&#039;&#039;not&#039;&#039;&#039; see any traffic as it is not attached to any hook, but it can be very useful to arrange your rule-set in a tree of chains by using the [[jumping to chain|jump to chain]] action.&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete the chains that you don&#039;t need, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will tell you that such chain is in used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chain =&lt;br /&gt;
&lt;br /&gt;
You can also flush the content of a chain. If you want to flush all the rule in the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft flush chain foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft &#039;add chain ip filter input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
% nft &#039;add chain ip filter output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=610</id>
		<title>Configuring chains</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Configuring_chains&amp;diff=610"/>
		<updated>2020-12-30T22:28:53Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: Explain base chain traversal in the case of multiple equivalent hooks in slightly more detail&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;As in &#039;&#039;iptables&#039;&#039;, you attach your [[Simple rule management|rules]] to chains. However, contrary to the &#039;&#039;iptables&#039;&#039; modus operandi, the &#039;&#039;nftables&#039;&#039; infrastructure comes with no predefined chains, so you need to register your base chains in first place before you can add any rule. This allows very flexible configurations.&lt;br /&gt;
&lt;br /&gt;
= Adding base chains =&lt;br /&gt;
&lt;br /&gt;
The syntax to add base chains is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain [&amp;lt;family&amp;gt;] &amp;lt;table-name&amp;gt; &amp;lt;chain-name&amp;gt; { type &amp;lt;type&amp;gt; hook &amp;lt;hook&amp;gt; priority &amp;lt;value&amp;gt; \; [policy &amp;lt;policy&amp;gt;] } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Base chains are those that are registered into the [[Netfilter hooks]], ie. these chains see packets flowing through your Linux TCP/IP stack.&lt;br /&gt;
&lt;br /&gt;
The following example show how you can add new base chains to the &#039;&#039;foo&#039;&#039; table (that need to be created prior) through the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important&#039;&#039;&#039;: nft re-uses special characters, such as curly braces and the semicolon.I&lt;br /&gt;
f you are running these commands from a shell such as &#039;&#039;bash&#039;&#039;, all the special characters need&lt;br /&gt;
to be escaped.  The most simple way to prevent the shell from attempting to parse the nft syntax&lt;br /&gt;
is to quote everything withing single quotes.  Alternatively, you can run the command&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and run nft in interactive mode.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;add chain&#039;&#039; command registers the &#039;&#039;input&#039;&#039; chain, that it attached to the &#039;&#039;input&#039;&#039; hook so it will see packets that are addressed to the local processes.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;priority&#039;&#039; is important since it determines the ordering of the chains, thus, if you have several chains in the &#039;&#039;input&#039;&#039; hook, you can decide which one sees packets before another.&lt;br /&gt;
For example, input chains with priorities -12, -1, 0, 10 would be consulted exactly in that order.  Its possible to give two base chains the same priority, but there&lt;br /&gt;
is no guaranteed evaluation order of base chains with identical priority that are attached to the same hook location.&lt;br /&gt;
&lt;br /&gt;
If you want to use &#039;&#039;nftables&#039;&#039; to filter traffic for desktop Linux computers, ie. a computer which does not forward traffic, you can also register the output chain:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now you are ready to filter incoming (directed to local processes) and outgoing (generated by local processes) traffic.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important note&#039;&#039;&#039;: If you don&#039;t include the chain configuration that is specified enclosed in the curly braces, you are creating a non-base chain that will not see any packets (similar to &#039;&#039;iptables -N chain-name&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Since nftables 0.5, you can also specify the default policy for base chains as in &#039;&#039;iptables&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain ip foo output { type filter hook output priority 0 ; policy accept; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As in &#039;&#039;iptables&#039;&#039;, the two possible default policies are &#039;&#039;accept&#039;&#039; and &#039;&#039;drop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
When adding a chain on &#039;&#039;&#039;ingress&#039;&#039;&#039; hook, it is mandatory to specify the device where the chain will be attached: &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft &#039;add chain netdev foo dev0filter { type filter hook ingress device eth0 priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Base chain types ==&lt;br /&gt;
&lt;br /&gt;
The possible chain types are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039;, which is obviously used to filter packets. This is supported by the arp, bridge, ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;route&#039;&#039;&#039;, which is used to reroute packets if any relevant IP header field or the packet mark is modified. If you are familiar with &#039;&#039;iptables&#039;&#039;, this chain type provides equivalent semantics to the &#039;&#039;mangle&#039;&#039; table but only for the &#039;&#039;output&#039;&#039; hook (for other hooks use type &#039;&#039;filter&#039;&#039; instead). This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
* &#039;&#039;&#039;nat&#039;&#039;&#039;, which is used to perform Networking Address Translation (NAT). The first packet that belongs to a flow always hits this chain, follow up packets not. Therefore, never use this chain for filtering. This is supported by the ip, ip6 and inet table families.&lt;br /&gt;
&lt;br /&gt;
== Base chain hooks ==&lt;br /&gt;
&lt;br /&gt;
The possible hooks that you can use when you configure your chain are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;prerouting&#039;&#039;&#039;: the routing decision for those packets didn&#039;t happen yet, so you don&#039;t know if they are addressed to the local or remote systems.&lt;br /&gt;
* &#039;&#039;&#039;input&#039;&#039;&#039;: It happens after the routing decision, you can see packets that are directed to the local system and processes running in system.&lt;br /&gt;
* &#039;&#039;&#039;forward&#039;&#039;&#039;: It also happens after the routing decision, you can see packet that are not directed to the local machine.&lt;br /&gt;
* &#039;&#039;&#039;output&#039;&#039;&#039;: to catch packets that are originated from processes in the local machine.&lt;br /&gt;
* &#039;&#039;&#039;postrouting&#039;&#039;&#039;: After the routing decision for packets leaving the local system.&lt;br /&gt;
* &#039;&#039;&#039;ingress&#039;&#039;&#039; (only available at the &#039;&#039;netdev&#039;&#039; family): Since Linux kernel 4.2, you can filter traffic way before prerouting, after the packet is passed up from the NIC driver. So you have an alternative to &#039;&#039;tc&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Base chain priority ==&lt;br /&gt;
&lt;br /&gt;
The priority can be used to order the chains or to put them before or after some Netfilter internal operations. For example, a chain on the &#039;&#039;prerouting&#039;&#039; hook with the priority &#039;&#039;-300&#039;&#039; will be placed before connection tracking operations. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: starting with nftables 0.9.6 you may use keywords instead of numbers to configure the chain priority. Check the nft manpage for reference.&lt;br /&gt;
&lt;br /&gt;
For reference, here&#039;s the list of different priority used in iptables:&lt;br /&gt;
&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_DEFRAG (-400): priority of defragmentation&lt;br /&gt;
* NF_IP_PRI_RAW (-300): traditional priority of the raw table placed before connection tracking operation&lt;br /&gt;
* NF_IP_PRI_SELINUX_FIRST (-225): SELinux operations&lt;br /&gt;
* NF_IP_PRI_CONNTRACK (-200): Connection tracking operations&lt;br /&gt;
* NF_IP_PRI_MANGLE (-150): mangle operation&lt;br /&gt;
* NF_IP_PRI_NAT_DST (-100): destination NAT&lt;br /&gt;
* NF_IP_PRI_FILTER (0): filtering operation, the filter table&lt;br /&gt;
* NF_IP_PRI_SECURITY (50): Place of security table where secmark can be set for example&lt;br /&gt;
* NF_IP_PRI_NAT_SRC (100): source NAT&lt;br /&gt;
* NF_IP_PRI_SELINUX_LAST (225): SELinux at packet exit&lt;br /&gt;
* NF_IP_PRI_CONNTRACK_HELPER (300): connection tracking at exit&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If a packet is accepted and there is another chain, bearing the same hook type and with a later priority, then the packet will subsequently traverse this other chain. Hence, an accept verdict - be it by way of a rule or the hook policy - isn&#039;t necessarily final. However, the same is &#039;&#039;not&#039;&#039; true of packets that are subjected to a drop verdict. Instead, drops take immediate effect, with no further rules or chains being evaluated. &lt;br /&gt;
&lt;br /&gt;
The following ruleset demonstrates this potentially surprising distinction in behaviour:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
table inet filter {&lt;br /&gt;
        # This chain is evaluated first due to priority&lt;br /&gt;
        chain services {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
&lt;br /&gt;
                # If matched, this rule will prevent any further evaluation&lt;br /&gt;
                tcp dport http drop&lt;br /&gt;
&lt;br /&gt;
                # If matched, and despite the accept verdict, the packet proceeds to enter the chain below&lt;br /&gt;
                tcp dport ssh accept&lt;br /&gt;
&lt;br /&gt;
                # Likewise for any packets that get this far and hit the default policy&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        # This chain is evaluated last due to priority&lt;br /&gt;
        chain input {&lt;br /&gt;
                type filter hook input priority 1; policy drop;&lt;br /&gt;
                # All ingress packets end up being dropped here!&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the priority of the &#039;input&#039; chain above were to be changed to -1, the only difference would be that no packets have the opportunity to enter the &#039;services&#039; chain. Either way, this ruleset will result in all ingress packets being dropped.&lt;br /&gt;
&lt;br /&gt;
In summary, packets will traverse all of the chains within the scope of a given hook until they are either dropped or no more base chains exist. An accept verdict is only guaranteed to be final in the case that there is no later chain bearing the same type of hook as the chain that the packet originally entered.&lt;br /&gt;
&lt;br /&gt;
== Base chain policy ==&lt;br /&gt;
&lt;br /&gt;
This is the default verdict that will be applied to packets reaching the end of the chain (i.e, no more rules to be evaluated against).&lt;br /&gt;
&lt;br /&gt;
Currently there are 2 policies: &#039;&#039;&#039;accept&#039;&#039;&#039; (default) or &#039;&#039;&#039;drop&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;accept&#039;&#039; verdict means that the packet will keep traversing the network stack (default).&lt;br /&gt;
* The &#039;&#039;drop&#039;&#039; verdict means that the packet is discarded if the packet reaches the end of the base chain.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE&#039;&#039;&#039;: If no policy is explicitly selected, the default policy &#039;&#039;&#039;accept&#039;&#039;&#039; will be used.&lt;br /&gt;
&lt;br /&gt;
= Adding non-base chains =&lt;br /&gt;
&lt;br /&gt;
You can also create non-base chains as in &#039;&#039;iptables&#039;&#039; via:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add chain ip &amp;lt;table_name&amp;gt; &amp;lt;chain_name&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that this chain does &#039;&#039;&#039;not&#039;&#039;&#039; see any traffic as it is not attached to any hook, but it can be very useful to arrange your rule-set in a tree of chains by using the [[jumping to chain|jump to chain]] action.&lt;br /&gt;
&lt;br /&gt;
The chain name is an arbitrary string, with arbitrary case.&lt;br /&gt;
&lt;br /&gt;
= Deleting chains =&lt;br /&gt;
&lt;br /&gt;
You can delete the chains that you don&#039;t need, eg.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only condition is that the chain you want to delete needs to be empty, otherwise the kernel will tell you that such chain is in used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft delete chain ip foo input&lt;br /&gt;
&amp;lt;cmdline&amp;gt;:1:1-28: Error: Could not delete chain: Device or resource busy&lt;br /&gt;
delete chain ip foo input&lt;br /&gt;
^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to [[Simple rule management|flush the ruleset]] in that chain before you can remove the chain.&lt;br /&gt;
&lt;br /&gt;
= Flushing chain =&lt;br /&gt;
&lt;br /&gt;
You can also flush the content of a chain. If you want to flush all the rule in the chain &#039;&#039;input&#039;&#039; of the &#039;&#039;foo&#039;&#039; table, you have to type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
nft flush chain foo input&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example configuration: Filtering traffic for your standalone computer =&lt;br /&gt;
&lt;br /&gt;
You can create a table with two base chains to define rule to filter traffic coming to and leaving from your computer, asumming IPv4 connectivity:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
% nft add table ip filter&lt;br /&gt;
% nft &#039;add chain ip filter input { type filter hook input priority 0 ; }&#039;&lt;br /&gt;
% nft &#039;add chain ip filter output { type filter hook output priority 0 ; }&#039;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, you can start attaching [[Simple rule management|rules]] to these two base chains. Note that you don&#039;t need the &#039;&#039;forward&#039;&#039; chain in this case since this example assumes that you&#039;re configuring nftables to filter traffic for a standalone computer that doesn&#039;t behave as router.&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
	<entry>
		<id>http://wiki.nftables.org/wiki-nftables/index.php?title=Adoption&amp;diff=583</id>
		<title>Adoption</title>
		<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php?title=Adoption&amp;diff=583"/>
		<updated>2020-12-02T21:55:03Z</updated>

		<summary type="html">&lt;p&gt;Plushkava: /* system / firewalling / management */ Mention projects with no plans to support nftables, at the suggestion of anarcat&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page offers some light and data about current &#039;&#039;&#039;nftables adoption&#039;&#039;&#039; in the wider community.&lt;br /&gt;
As you probably know, the focus of the Netfilter project and community is in replacing the iptables framework with nftables, adding brand new features and refreshing some workflows along the way.&lt;br /&gt;
&lt;br /&gt;
Lots of upstream projects use iptables to handle NAT, filtering, mangling or other networking stuff.&lt;br /&gt;
Here, the info we know about them, their relationship with nftables and the possibilities for them to migrate to nftables.&lt;br /&gt;
&lt;br /&gt;
= Cases =&lt;br /&gt;
&lt;br /&gt;
Known cases and examples we could heard of. &#039;&#039;&#039;TODO: extend with more current data&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
All major Linux distributions contains the nftables framework ready to use. Check [[Nftables from distributions]].&lt;br /&gt;
&lt;br /&gt;
== system / firewalling / management ==&lt;br /&gt;
&lt;br /&gt;
=== Supporting nftables ===&lt;br /&gt;
&lt;br /&gt;
The following projects are known to either directly support nftables or have authors actively working on nftables integration.&lt;br /&gt;
&lt;br /&gt;
* https://www.fail2ban.org/ -- the fail2ban tool already includes native support for nftables.&lt;br /&gt;
* https://firewalld.org/ -- firewalld by RedHat is currently developing a native integration with nftables.&lt;br /&gt;
* https://suricata-ids.org/ -- suricata can work natively with nftables ([https://home.regit.org/2014/02/suricata-and-nftables/ link])&lt;br /&gt;
&lt;br /&gt;
=== Supporting iptables only ===&lt;br /&gt;
&lt;br /&gt;
The following projects are known to only support iptables/iptables-nft, with no plans to support nftables in the future.&lt;br /&gt;
&lt;br /&gt;
* http://ferm.foo-projects.org/ -- [https://github.com/MaxKellermann/ferm/issues/35#issuecomment-386091563 citation]&lt;br /&gt;
* https://shorewall.org/ -- [https://sourceforge.net/p/shorewall/mailman/message/35458915/ citation]&lt;br /&gt;
&lt;br /&gt;
== virtualization / cloud / infrastructure ==&lt;br /&gt;
&lt;br /&gt;
* https://github.com/zevenet/nftlb -- nftlb by Zevenet is a nftables-based loadbalancer which can outperform LVS by 10x&lt;br /&gt;
* https://www.docker.com/ -- Some discussion happened in the Docker community regarding a native integration with nftables, which could ease some of their use cases ([https://github.com/moby/moby/issues/26824 link]) ([https://github.com/robbertkl/docker-ipv6nat/issues/17 link]) ([https://stephank.nl/p/2017-06-05-ipv6-on-production-docker.html running docker with IPv6 using nftables])&lt;br /&gt;
* https://kubernetes.io/ -- Kubernetes does not support nftables yes, but some discussion happened already ([https://github.com/kubernetes/kubernetes/issues/45385 link]). Compat tools may be used to trick kubernetes into using nftables transparently.&lt;br /&gt;
* http://openstack.org/ -- Openstack does not support nftables yet. Compat tools may be used to trick neutron and other components into using nftables transparently.&lt;br /&gt;
* https://libvirt.org/ -- there are reports of people running libvirt with nftables for bridge filtering for virtual machines&lt;br /&gt;
* https://saltstack.com/ -- SaltStack includes native support for nftables ([https://docs.saltstack.com/en/latest/ref/states/all/salt.states.nftables.html link]).&lt;br /&gt;
* https://coreos.com/ -- the CoreOS ecosystem includes native support for nftables ([https://github.com/coreos/coreos-overlay/pull/2662 link])&lt;br /&gt;
&lt;br /&gt;
== others ==&lt;br /&gt;
&lt;br /&gt;
* https://openwrt.org/ -- there are reports of people running nftables rather than iptables in openwrt systems&lt;br /&gt;
* https://www.cica.es/ -- this regional [https://en.wikipedia.org/wiki/National_research_and_education_network NREN] uses nftables in the datacenter for their perimetral firewalls ([http://workshop.netfilter.org/2017/wiki/index.php/Developer_days.html#nftables_at_CICA.2C_our_experience slides])&lt;br /&gt;
* [[Nftables from distributions]] -- all major Linux distribution already include nftables ready to use&lt;br /&gt;
* https://www.nano-editor.org/ -- The nano editor includes syntax highlighting for nftables in files with .nft name extension or nft shebang&lt;br /&gt;
* https://github.com/nfnty/vim-nftables -- the VIM editor includes syntax highlighting for nftables&lt;br /&gt;
* [https://github.com/ipr-cnrs Institut de Physique de Rennes] -- this french research entity seems to be using nftables with ansible ([https://github.com/ipr-cnrs/nftables link])&lt;br /&gt;
* VPN -- nftables can be combined with other software packages like OpenVPN to build great VPN solutions ([http://ral-arturo.org/2017/04/07/openvpn-debian-stretch.html link])&lt;br /&gt;
* [https://github.com/mdlayher/netlink netlink golang package] -- the Golang Netlink package got batching support to be able to work with nftables ([https://github.com/mdlayher/netlink/issues/81 link])&lt;br /&gt;
* [https://github.com/google/nftables nftables golang library] -- This nftables golang integration library was made by Google&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Moving from iptables to nftables]]&lt;br /&gt;
* [[Moving from ipset to nftables]]&lt;br /&gt;
* [[List of updates since Linux kernel 3.13]]&lt;br /&gt;
* [[Supported features compared to xtables]]&lt;br /&gt;
* [[List of available translations via iptables-translate tool]]&lt;/div&gt;</summary>
		<author><name>Plushkava</name></author>
	</entry>
</feed>