<?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=Jesper</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=Jesper"/>
	<link rel="alternate" type="text/html" href="http://wiki.nftables.org/wiki-nftables/index.php/Special:Contributions/Jesper"/>
	<updated>2026-06-13T05:09:08Z</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=520</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=520"/>
		<updated>2020-07-03T16:53:28Z</updated>

		<summary type="html">&lt;p&gt;Jesper: Mention &amp;#039;foo&amp;#039; table must be created prior to this command&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;
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 gets accepted and there is another base chain in the same hook which is ordered with a later priority, the packet will be evaluated &#039;&#039;&#039;again&#039;&#039;&#039;.&lt;br /&gt;
That is, packets will traverse chains in a given hook, until it is dropped or no more base chains exist. Drops take instant effect, no further rules or chains are evaluated.&lt;br /&gt;
&lt;br /&gt;
Example ruleset of this behavior:&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 ssh {&lt;br /&gt;
                type filter hook input priority 0; policy accept;&lt;br /&gt;
                # ssh packet accepted&lt;br /&gt;
                tcp dport ssh accept&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;
                # the same ssh packet is dropped here by means of default policy&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If priority of the &#039;input chain&#039; above would be changed to -1, all packets would&lt;br /&gt;
be dropped.&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>Jesper</name></author>
	</entry>
</feed>