netfilter: conntrack: do not enable connection tracking unless needed
authorFlorian Westphal <fw@strlen.de>
Fri, 28 Jul 2017 09:22:04 +0000 (11:22 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Mon, 31 Jul 2017 18:42:00 +0000 (20:42 +0200)
Discussion during NFWS 2017 in Faro has shown that the current
conntrack behaviour is unreasonable.

Even if conntrack module is loaded on behalf of a single net namespace,
its turned on for all namespaces, which is expensive.  Commit
481fa373476 ("netfilter: conntrack: add nf_conntrack_default_on sysctl")
attempted to provide an alternative to the 'default on' behaviour by
adding a sysctl to change it.

However, as Eric points out, the sysctl only becomes available
once the module is loaded, and then its too late.

So we either have to move the sysctl to the core, or, alternatively,
change conntrack to become active only once the rule set requires this.

This does the latter, conntrack is only enabled when a rule needs it.

Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Documentation/networking/nf_conntrack-sysctl.txt
include/net/netfilter/nf_conntrack_l3proto.h
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/netfilter/nf_conntrack_proto.c
net/netfilter/nf_conntrack_standalone.c

index 497d668288f95f98d15c3f0057656fb5a5726c30..433b6724797ad7e9476f041c7f0e2dcd77ca8579 100644 (file)
@@ -96,17 +96,6 @@ nf_conntrack_max - INTEGER
        Size of connection tracking table.  Default value is
        nf_conntrack_buckets value * 4.
 
-nf_conntrack_default_on - BOOLEAN
-       0 - don't register conntrack in new net namespaces
-       1 - register conntrack in new net namespaces (default)
-
-       This controls wheter newly created network namespaces have connection
-       tracking enabled by default.  It will be enabled automatically
-       regardless of this setting if the new net namespace requires
-       connection tracking, e.g. when NAT rules are created.
-       This setting is only visible in initial user namespace, it has no
-       effect on existing namespaces.
-
 nf_conntrack_tcp_be_liberal - BOOLEAN
        0 - disabled (default)
        not 0 - enabled
index 6d14b36e3a49084a58333ceff5db0b1957aff387..1b8de164d7446108d0a1748a074629cbc40549cc 100644 (file)
@@ -73,21 +73,6 @@ struct nf_conntrack_l3proto {
 
 extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO];
 
-#ifdef CONFIG_SYSCTL
-/* Protocol pernet registration. */
-int nf_ct_l3proto_pernet_register(struct net *net,
-                                 struct nf_conntrack_l3proto *proto);
-#else
-static inline int nf_ct_l3proto_pernet_register(struct net *n,
-                                               struct nf_conntrack_l3proto *p)
-{
-       return 0;
-}
-#endif
-
-void nf_ct_l3proto_pernet_unregister(struct net *net,
-                                    struct nf_conntrack_l3proto *proto);
-
 /* Protocol global registration. */
 int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto);
 void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto);
index 63e4ea0e01f8780586722ca3371506fa6e2fd019..de5f0e6ddd1b1a95b68a302e18640a32e26c2a30 100644 (file)
@@ -398,24 +398,12 @@ static struct nf_conntrack_l4proto *builtin_l4proto4[] = {
 
 static int ipv4_net_init(struct net *net)
 {
-       int ret = 0;
-
-       ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto4,
-                                           ARRAY_SIZE(builtin_l4proto4));
-       if (ret < 0)
-               return ret;
-       ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv4);
-       if (ret < 0) {
-               pr_err("nf_conntrack_ipv4: pernet registration failed\n");
-               nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
-                                               ARRAY_SIZE(builtin_l4proto4));
-       }
-       return ret;
+       return nf_ct_l4proto_pernet_register(net, builtin_l4proto4,
+                                            ARRAY_SIZE(builtin_l4proto4));
 }
 
 static void ipv4_net_exit(struct net *net)
 {
-       nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv4);
        nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
                                        ARRAY_SIZE(builtin_l4proto4));
 }
index f2d2f4a9294b74413fc92c58ca52ab15af3dbd58..ddef5ee9e0a863f407410645020d7a0655175d7c 100644 (file)
@@ -398,25 +398,12 @@ static struct nf_conntrack_l4proto *builtin_l4proto6[] = {
 
 static int ipv6_net_init(struct net *net)
 {
-       int ret = 0;
-
-       ret = nf_ct_l4proto_pernet_register(net, builtin_l4proto6,
-                                           ARRAY_SIZE(builtin_l4proto6));
-       if (ret < 0)
-               return ret;
-
-       ret = nf_ct_l3proto_pernet_register(net, &nf_conntrack_l3proto_ipv6);
-       if (ret < 0) {
-               pr_err("nf_conntrack_ipv6: pernet registration failed.\n");
-               nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
-                                               ARRAY_SIZE(builtin_l4proto6));
-       }
-       return ret;
+       return nf_ct_l4proto_pernet_register(net, builtin_l4proto6,
+                                            ARRAY_SIZE(builtin_l4proto6));
 }
 
 static void ipv6_net_exit(struct net *net)
 {
-       nf_ct_l3proto_pernet_unregister(net, &nf_conntrack_l3proto_ipv6);
        nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
                                        ARRAY_SIZE(builtin_l4proto6));
 }
index 1dcad229c3cc7290c9e89bea109ebf6098e79b21..7c89dade6fd3bc7e41e2318367e1abe3213f7c83 100644 (file)
@@ -238,20 +238,6 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(nf_ct_l3proto_register);
 
-#ifdef CONFIG_SYSCTL
-extern unsigned int nf_conntrack_default_on;
-
-int nf_ct_l3proto_pernet_register(struct net *net,
-                                 struct nf_conntrack_l3proto *proto)
-{
-       if (nf_conntrack_default_on == 0)
-               return 0;
-
-       return proto->net_ns_get ? proto->net_ns_get(net) : 0;
-}
-EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_register);
-#endif
-
 void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)
 {
        BUG_ON(proto->l3proto >= NFPROTO_NUMPROTO);
@@ -270,21 +256,6 @@ void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)
 }
 EXPORT_SYMBOL_GPL(nf_ct_l3proto_unregister);
 
-void nf_ct_l3proto_pernet_unregister(struct net *net,
-                                    struct nf_conntrack_l3proto *proto)
-{
-       /*
-        * nf_conntrack_default_on *might* have registered hooks.
-        * ->net_ns_put must cope with more puts() than get(), i.e.
-        * if nf_conntrack_default_on was 0 at time of
-        * nf_ct_l3proto_pernet_register invocation this net_ns_put()
-        * should be a noop.
-        */
-       if (proto->net_ns_put)
-               proto->net_ns_put(net);
-}
-EXPORT_SYMBOL_GPL(nf_ct_l3proto_pernet_unregister);
-
 static struct nf_proto_net *nf_ct_l4proto_net(struct net *net,
                                              struct nf_conntrack_l4proto *l4proto)
 {
index ccb5cb9043e0e769ba463759a69f4d9f36e122e0..5b6c675d55b14b2392a75285a2d8f87b569c9b22 100644 (file)
@@ -452,9 +452,6 @@ static int log_invalid_proto_max __read_mostly = 255;
 /* size the user *wants to set */
 static unsigned int nf_conntrack_htable_size_user __read_mostly;
 
-extern unsigned int nf_conntrack_default_on;
-unsigned int nf_conntrack_default_on __read_mostly = 1;
-
 static int
 nf_conntrack_hash_sysctl(struct ctl_table *table, int write,
                         void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -520,13 +517,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
-       {
-               .procname       = "nf_conntrack_default_on",
-               .data           = &nf_conntrack_default_on,
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
        { }
 };