Re: [PATCH net] netfilter: nf_dup_netdev: scrub duplicates to preserve the direct path

Pablo Neira Ayuso <[email protected]> Wed, 5 Aug 2026 10:24:33 +0200
Newsgroups gmane.linux.network,gmane.comp.security.firewalls.netfilter.devel
Message-ID <anLzQeYulW2CQItC@chamomile>
Hi,

On Tue, Aug 04, 2026 at 10:11:50PM +0200, Alexandre Ferrieux wrote:
> The nftables 'dup' action clones the skb with its full glory of
> metadata, including references to its destination and conntrack
> information. As a consequence, a link failure on the duplicate's
> egress path ends up doing the same as it would for the direct path,
> for example invalidating the original packet's destination, which
> typically breaks all TCP connections to that address.
>
> In other words, the "dup" path has the potential to wreak havoc
> in the direct path as a consequence of secondary link failures. This
> is very bad behavior for a monitoring tool, which is the most
> obvious application of 'dup'.

Can you describe your use-case a bit and how it breaks?

> This patch fixes all similar scenarii by calling skb_scrub_pkt()
> on the clone, severing its link to precious direct-path state.

This patch is targetted at the net tree, but nf.git is preferred.

> Note: the second argument of skb_scrub_pkt(), the boolean "packet
> is crossing netns", is intentionally set to 'false', as a 'true'
> involves exaggerate scrubbing, e.g. of the timestamp, which a
> monitoring 'dup' typically wants to preserve.

Yes, the skb->mark should really remain in place for the duplication.
As for the conntrack and dst, you have to explain what it breaks on
your end.

> Signed-off-by: Alexandre Ferrieux <[email protected]>
> ---
>  net/netfilter/nf_dup_netdev.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/net/netfilter/nf_dup_netdev.c b/net/netfilter/nf_dup_netdev.c
> index c6bd5c29bed6..0f47a2135955 100644
> --- a/net/netfilter/nf_dup_netdev.c
> +++ b/net/netfilter/nf_dup_netdev.c
> @@ -63,8 +63,10 @@ void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif)
>  		return;
>  
>  	skb = skb_clone(pkt->skb, GFP_ATOMIC);
> -	if (skb)
> +	if (skb) {
> +		skb_scrub_packet(skb, false);
>  		nf_do_netdev_egress(skb, dev, nft_hook(pkt));
> +	}
>  }
>  EXPORT_SYMBOL_GPL(nf_dup_netdev_egress);
>  
> -- 
> 2.47.3
> 
>