Re: order of netfilter hooks and check for martian source

Michael Tokarev <[email protected]> Sat, 21 Jun 2025 20:50:35 +0300
Newsgroups gmane.comp.security.firewalls.netfilter.general
Message-ID <[email protected]>
On 21.06.2025 19:08, Michael Tokarev wrote:
> On 21.06.2025 19:05, Jozsef Kadlecsik wrote:
>> On Sat, 21 Jun 2025, Michael Tokarev wrote:
>>
>>> On 21.06.2025 17:42, Jozsef Kadlecsik wrote:
>>> ..
>>>> However, routing decisions can be affected by marking packets. So 
>>>> I'd mark
>>>> packets before routing and use routing tables according to the mark 
>>>> value.
>>>
>>> The prob with replies to DNAted packets is that these packets traverse
>>> routing rules first, BEFORE they're seen by netfilter code.  Who can
>>> mark them for routing if routing is done before it's in netfilter?
>>
>> No, not at all. You can mark the incoming first packet, store the 
>> packet's
>> mark value in conntrack and restore from conntrack for the reply packets
>> in mangle/prerouting. Which is exactly that, before routing.

I tried to follow this route.  In the dnat rule, I applied a mark to
this conntrack entry, and checked this fwmark in ip rule to perform
routing through ip2/gw2 instead of default ip1/gw1.

As expected, netfilter code does not mark the reply packet with this
fwmark before it goes through the routing tables, - exactly like this
same netfilter code does not de-DNAT"if the source address of the
reply packet..

> Why netfilter can't de-DNAT'ify this (reply) packet at this same place
> where you suggest to apply the mark, so the routing see it in its final
> form, and no jumping through hoops is needed for the user?

So it's not just jumping through hoops, - it looks like netfilter just
can't do this correctly currently.

The order of applying routing and mangling/demangling is wrong.
And it looks like a rather interesting and serious bug, though not
for a widely used situation.

It should be:

   1 check for martians (network code)
   2 prerouting netfilter hook,
     AND de-mangling NAT'ed replies
   3 routing
   4 filter table
   5 postrouting hook

Currently, 2 and 3 is swapped out.

Thanks,

/mjt