From: Binarus <lists@binarus.de>
To: netfilter@vger.kernel.org
Subject: "nft list hooks" not showing the custom nat chains, and unexpected priority for nf_nat_ipv4_local_fn
Date: Sat, 13 Jun 2026 18:16:33 +0200 [thread overview]
Message-ID: <2b4db6cd-bc9b-47ff-99ee-7c15da7a343f@binarus.de> (raw)
Dear all,
I am still struggling with understanding the packet flow through the netfilter hooks and chains. Therefore, I have set up a very simple test scenario. Before listing the ruleset, a few remarks:
The following relates to netfilter 1.1.3 with kernel 6.12.90 on Debian trixie. I had to modify the kernel to enable the hook listing, but that's the only change compared to a Debian trixie vanilla system.
The test system has a ppp0 interface (default route / internet access) and a physical NIC interface (network 192.168.20.0/24, IP 192.168.20.249). The following ruleset is totally useless for any practical application, but I hope it's appropriate for investigations:
root@charon /etc/network # nft list ruleset
table ip t_IP {
chain output-route {
type route hook output priority mangle; policy drop;
ip saddr 192.168.20.249 ip protocol icmp meta nftrace set 1
accept
}
chain output-filter {
type filter hook output priority filter; policy drop;
ip saddr 192.168.20.249 ip protocol icmp meta nftrace set 1
accept
}
chain output-nat {
type nat hook output priority 100; policy drop;
ip saddr 192.168.20.249 ip protocol icmp meta nftrace set 1
accept
}
chain postrouting-filter {
type filter hook postrouting priority filter; policy drop;
ip saddr 192.168.20.249 ip protocol icmp meta nftrace set 1
accept
}
chain postrouting-nat {
type nat hook postrouting priority srcnat; policy drop;
ip saddr 192.168.20.249 ip protocol icmp meta nftrace set 1
oifname "ppp0" ip protocol { tcp, udp } masquerade to :61000-64999
oifname "ppp0" ip protocol icmp masquerade
accept
}
}
The goal is to investigate the flow of an outbound icmp packet that is locally generated. I believe that the above ruleset includes all pairs of hooks and chain types that exist for outbound local packets. I have included the "nftrace" line in every chain because I wanted to see all chains the packet goes through even in case I had totally misunderstood the order.
But before the actual test, I looked at the output of "nft list hooks". This is the result:
root@charon /etc/network # nft list hooks
family ip {
hook prerouting {
-0000000400 ipv4_conntrack_defrag [nf_defrag_ipv4]
-0000000200 ipv4_conntrack_in [nf_conntrack]
-0000000100 nf_nat_ipv4_pre_routing [nf_nat]
}
hook input {
+0000000100 nf_nat_ipv4_local_in [nf_nat]
+2147483647 nf_confirm [nf_conntrack]
}
hook output {
-0000000400 ipv4_conntrack_defrag [nf_defrag_ipv4]
-0000000200 ipv4_conntrack_local [nf_conntrack]
-0000000150 chain ip t_IP output-route [nf_tables]
-0000000100 nf_nat_ipv4_local_fn [nf_nat]
0000000000 chain ip t_IP output-filter [nf_tables]
}
hook postrouting {
0000000000 chain ip t_IP postrouting-filter [nf_tables]
+0000000100 nf_nat_ipv4_out [nf_nat]
+2147483647 nf_confirm [nf_conntrack]
}
}
Now this leaves me totally clueless. Focusing on the output and the postrouting hook only (because I'd like to learn about these two first):
1.
My own custom output-route, output-filter and postrouting-filter are listed. But neither the output-nat nor the postrouting-nat chain are listed; at their place, the respective internal netfilter functions are listed.
I then have changed the priorities for these two chains (setting them to the shown value from the ruleset ±1 each) in case the default priorities must not be used. But that did not change anything: The custom nat chains still were not listed in the output of "nft list hooks".
Could somebody please explain where my misunderstanding is? In further tests, I have verified that these custom chains were indeed active, so why aren't they listed?
2.
According to my research, the nat chain in the output hook is for source nat, not for destination nat, and therefore its priority should be 100, as given in the ruleset. The famous "netfilter hooks" graphics in the nftables wiki says the same, at least in my understanding.
But "nft list hooks" says that the priority of nf_nat_ipv4_local_fn is -100, as if the nat chain at this hook would be for destination nat instead of source nat.
Could somebody please explain which type of nat the nat chain at the output hook is meant for (snat or dnat), and if it is snat, why the priority is -100 instead of 100 as expected?
Thank you very much in advance, and have a nice weekend,
Binarus
next reply other threads:[~2026-06-13 16:16 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-13 16:16 Binarus [this message]
2026-06-13 16:52 ` "nft list hooks" not showing the custom nat chains, and unexpected priority for nf_nat_ipv4_local_fn Kerin Millar
2026-06-15 13:44 ` Binarus
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2b4db6cd-bc9b-47ff-99ee-7c15da7a343f@binarus.de \
--to=lists@binarus.de \
--cc=netfilter@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox