Commit 4d3a57f2 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: conntrack: do not enable connection tracking unless needed

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
481fa373 ("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: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 9b7e26ae
...@@ -96,17 +96,6 @@ nf_conntrack_max - INTEGER ...@@ -96,17 +96,6 @@ nf_conntrack_max - INTEGER
Size of connection tracking table. Default value is Size of connection tracking table. Default value is
nf_conntrack_buckets value * 4. 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 nf_conntrack_tcp_be_liberal - BOOLEAN
0 - disabled (default) 0 - disabled (default)
not 0 - enabled not 0 - enabled
......
...@@ -73,21 +73,6 @@ struct nf_conntrack_l3proto { ...@@ -73,21 +73,6 @@ struct nf_conntrack_l3proto {
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO]; 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. */ /* Protocol global registration. */
int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto); int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto);
void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto); void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto);
......
...@@ -398,24 +398,12 @@ static struct nf_conntrack_l4proto *builtin_l4proto4[] = { ...@@ -398,24 +398,12 @@ static struct nf_conntrack_l4proto *builtin_l4proto4[] = {
static int ipv4_net_init(struct net *net) static int ipv4_net_init(struct net *net)
{ {
int ret = 0; return nf_ct_l4proto_pernet_register(net, builtin_l4proto4,
ARRAY_SIZE(builtin_l4proto4));
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;
} }
static void ipv4_net_exit(struct net *net) 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, nf_ct_l4proto_pernet_unregister(net, builtin_l4proto4,
ARRAY_SIZE(builtin_l4proto4)); ARRAY_SIZE(builtin_l4proto4));
} }
......
...@@ -398,25 +398,12 @@ static struct nf_conntrack_l4proto *builtin_l4proto6[] = { ...@@ -398,25 +398,12 @@ static struct nf_conntrack_l4proto *builtin_l4proto6[] = {
static int ipv6_net_init(struct net *net) static int ipv6_net_init(struct net *net)
{ {
int ret = 0; return nf_ct_l4proto_pernet_register(net, builtin_l4proto6,
ARRAY_SIZE(builtin_l4proto6));
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;
} }
static void ipv6_net_exit(struct net *net) 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, nf_ct_l4proto_pernet_unregister(net, builtin_l4proto6,
ARRAY_SIZE(builtin_l4proto6)); ARRAY_SIZE(builtin_l4proto6));
} }
......
...@@ -238,20 +238,6 @@ int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto) ...@@ -238,20 +238,6 @@ int nf_ct_l3proto_register(struct nf_conntrack_l3proto *proto)
} }
EXPORT_SYMBOL_GPL(nf_ct_l3proto_register); 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) void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)
{ {
BUG_ON(proto->l3proto >= NFPROTO_NUMPROTO); BUG_ON(proto->l3proto >= NFPROTO_NUMPROTO);
...@@ -270,21 +256,6 @@ void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto) ...@@ -270,21 +256,6 @@ void nf_ct_l3proto_unregister(struct nf_conntrack_l3proto *proto)
} }
EXPORT_SYMBOL_GPL(nf_ct_l3proto_unregister); 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, static struct nf_proto_net *nf_ct_l4proto_net(struct net *net,
struct nf_conntrack_l4proto *l4proto) struct nf_conntrack_l4proto *l4proto)
{ {
......
...@@ -452,9 +452,6 @@ static int log_invalid_proto_max __read_mostly = 255; ...@@ -452,9 +452,6 @@ static int log_invalid_proto_max __read_mostly = 255;
/* size the user *wants to set */ /* size the user *wants to set */
static unsigned int nf_conntrack_htable_size_user __read_mostly; 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 static int
nf_conntrack_hash_sysctl(struct ctl_table *table, int write, nf_conntrack_hash_sysctl(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos) void __user *buffer, size_t *lenp, loff_t *ppos)
...@@ -520,13 +517,6 @@ static struct ctl_table nf_ct_sysctl_table[] = { ...@@ -520,13 +517,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
}, },
{
.procname = "nf_conntrack_default_on",
.data = &nf_conntrack_default_on,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{ } { }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment