netfilter: nf_nat: add nat type hooks to nat core
authorFlorian Westphal <fw@strlen.de>
Mon, 14 May 2018 21:46:58 +0000 (23:46 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Wed, 23 May 2018 07:14:06 +0000 (09:14 +0200)
commit9971a514ed2697e542f3984a6162eac54bb1da98
treec7ea7481b1c10cdfc7634b3277013079e7d1c815
parent1cd472bf036ca038e783ef5f058f54e45b7e8180
netfilter: nf_nat: add nat type hooks to nat core

Currently the packet rewrite and instantiation of nat NULL bindings
happens from the protocol specific nat backend.

Invocation occurs either via ip(6)table_nat or the nf_tables nat chain type.

Invocation looks like this (simplified):
NF_HOOK()
   |
   `---iptable_nat
 |
 `---> nf_nat_l3proto_ipv4 -> nf_nat_packet
               |
          new packet? pass skb though iptables nat chain
                       |
       `---> iptable_nat: ipt_do_table

In nft case, this looks the same (nft_chain_nat_ipv4 instead of
iptable_nat).

This is a problem for two reasons:
1. Can't use iptables nat and nf_tables nat at the same time,
   as the first user adds a nat binding (nf_nat_l3proto_ipv4 adds a
   NULL binding if do_table() did not find a matching nat rule so we
   can detect post-nat tuple collisions).
2. If you use e.g. nft_masq, snat, redir, etc. uses must also register
   an empty base chain so that the nat core gets called fro NF_HOOK()
   to do the reverse translation, which is neither obvious nor user
   friendly.

After this change, the base hook gets registered not from iptable_nat or
nftables nat hooks, but from the l3 nat core.

iptables/nft nat base hooks get registered with the nat core instead:

NF_HOOK()
   |
   `---> nf_nat_l3proto_ipv4 -> nf_nat_packet
|
         new packet? pass skb through iptables/nftables nat chains
                |
+-> iptables_nat: ipt_do_table
        +-> nft nat chain x
        `-> nft nat chain y

The nat core deals with null bindings and reverse translation.
When no mapping exists, it calls the registered nat lookup hooks until
one creates a new mapping.
If both iptables and nftables nat hooks exist, the first matching
one is used (i.e., higher priority wins).

Also, nft users do not need to create empty nat hooks anymore,
nat core always registers the base hooks that take care of reverse/reply
translation.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/net/netfilter/nf_nat_core.h
include/net/netfilter/nf_nat_l3proto.h
net/ipv4/netfilter/iptable_nat.c
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
net/ipv4/netfilter/nft_chain_nat_ipv4.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
net/ipv6/netfilter/nft_chain_nat_ipv6.c
net/netfilter/nf_nat_core.c