From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Patrick McHardy <kaber@trash.net>
Cc: Phil Oester <kernel@linuxace.com>,
Netfilter Development Mailinglist
<netfilter-devel@vger.kernel.org>
Subject: Re: [RFC] generic CONNTRACK target
Date: Mon, 14 Jan 2008 17:29:37 +0100 [thread overview]
Message-ID: <478B8DF1.3060503@netfilter.org> (raw)
In-Reply-To: <478B8B74.3070903@netfilter.org>
[-- Attachment #1: Type: text/plain, Size: 158 bytes --]
Pablo Neira Ayuso wrote:
> Attached an untested RFC patch [...]
I forgot to attach the patch...
--
"Los honestos son inadaptados sociales" -- Les Luthiers
[-- Attachment #2: rfc.patch --]
[-- Type: text/x-patch, Size: 16504 bytes --]
[RFC] Introduce the generic conntrack target
This patch implements the generic CONNTRACK target which merges
CONNMARK, CONNSECMARK, NOTRACK and TIMEOUT into a single target. Also,
This patch introduces the volatile events marking to make ctnetlink ignore
certain events.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Index: net-2.6.git/include/linux/netfilter/nf_conntrack_common.h
===================================================================
--- net-2.6.git.orig/include/linux/netfilter/nf_conntrack_common.h 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/include/linux/netfilter/nf_conntrack_common.h 2008-01-02 04:54:29.000000000 +0100
@@ -73,6 +73,10 @@ enum ip_conntrack_status {
/* Connection has fixed timeout. */
IPS_FIXED_TIMEOUT_BIT = 10,
IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+
+ /* Connection has a manually configured timeout. */
+ IPS_MANUAL_TIMEOUT_BIT = 11,
+ IPS_MANUAL_TIMEOUT = (1 << IPS_MANUAL_TIMEOUT_BIT),
};
/* Connection tracking event bits */
@@ -137,6 +141,10 @@ enum ip_conntrack_events
/* Secmark is set */
IPCT_SECMARK_BIT = 14,
IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
+
+ /* These events has been set as volatile (via iptables) */
+ IPCT_VOLATILE_BIT = 15,
+ IPCT_VOLATILE = (1 << IPCT_VOLATILE_BIT),
};
enum ip_conntrack_expect_events {
Index: net-2.6.git/include/net/netfilter/nf_conntrack.h
===================================================================
--- net-2.6.git.orig/include/net/netfilter/nf_conntrack.h 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/include/net/netfilter/nf_conntrack.h 2008-01-02 03:47:52.000000000 +0100
@@ -88,6 +88,10 @@ struct nf_conn_help {
unsigned int expecting;
};
+/* nf_conn feature for manual timeouts via iptables */
+struct nf_conn_timeout {
+ u_int32_t timeout;
+};
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
Index: net-2.6.git/include/net/netfilter/nf_conntrack_extend.h
===================================================================
--- net-2.6.git.orig/include/net/netfilter/nf_conntrack_extend.h 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/include/net/netfilter/nf_conntrack_extend.h 2008-01-02 03:48:45.000000000 +0100
@@ -7,11 +7,13 @@ enum nf_ct_ext_id
{
NF_CT_EXT_HELPER,
NF_CT_EXT_NAT,
+ NF_CT_EXT_TIMEOUT,
NF_CT_EXT_NUM,
};
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
+#define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout
/* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext {
@@ -82,4 +84,10 @@ struct nf_ct_ext_type
int nf_ct_extend_register(struct nf_ct_ext_type *type);
void nf_ct_extend_unregister(struct nf_ct_ext_type *type);
+
+static inline struct nf_conn_timeout *nfct_timeout(const struct nf_conn *ct)
+{
+ return nf_ct_ext_find(ct, NF_CT_EXT_TIMEOUT);
+}
+
#endif /* _NF_CONNTRACK_EXTEND_H */
Index: net-2.6.git/net/netfilter/Kconfig
===================================================================
--- net-2.6.git.orig/net/netfilter/Kconfig 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/net/netfilter/Kconfig 2008-01-02 05:00:44.000000000 +0100
@@ -420,6 +420,30 @@ config NETFILTER_XT_TARGET_CONNSECMARK
To compile it as a module, choose M here. If unsure, say N.
+config NETFILTER_XT_TARGET_CONNTRACK
+ tristate '"CONNTRACK" target support'
+ depends on NETFILTER_XTABLES
+ depends on NF_CONNTRACK
+ default m if NETFILTER_ADVANCED=n
+ help
+ The generic CONNTRACK target:
+ a) allows you to manipulate the connection mark value. Similar
+ to the MARK target, but affects the connection mark value rather
+ than the packet mark value.
+ b) allows you to copy security markings from packets to connections,
+ and restores security markings from connections to packets (if the
+ packets are not already marked). This would normally be used in
+ conjunction with the SECMARK target.
+ c) allows you to alter the timeout of specific sessions in the
+ conntrack/NAT subsystem. Specific conntracks can be given longer
+ or shorter timeouts than the global defaults.
+ d) allows a select rule to specify which packets *not* to enter
+ the conntrack/NAT subsystem with all the consequences (no ICMP error
+ tracking, no protocol helpers for the selected packets).
+ e) allows you to skip ctnetlink events delivery
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_TARGET_TCPMSS
tristate '"TCPMSS" target support'
depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
Index: net-2.6.git/net/netfilter/Makefile
===================================================================
--- net-2.6.git.orig/net/netfilter/Makefile 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/net/netfilter/Makefile 2008-01-02 03:44:04.000000000 +0100
@@ -41,6 +41,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tab
obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CONNTRACK) += xt_CONNTRACK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
Index: net-2.6.git/net/netfilter/nf_conntrack_core.c
===================================================================
--- net-2.6.git.orig/net/netfilter/nf_conntrack_core.c 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/net/netfilter/nf_conntrack_core.c 2008-01-02 03:44:04.000000000 +0100
@@ -781,6 +781,10 @@ void __nf_ct_refresh_acct(struct nf_conn
return;
}
+ /* This conntrack has a manual timeout set via iptables */
+ if (test_bit(IPS_MANUAL_TIMEOUT_BIT, &ct->status) && nfct_timeout(ct))
+ extra_jiffies = nfct_timeout(ct)->timeout;
+
/* If not in hash table, timer will not be active yet */
if (!nf_ct_is_confirmed(ct)) {
ct->timeout.expires = extra_jiffies;
Index: net-2.6.git/net/netfilter/nf_conntrack_netlink.c
===================================================================
--- net-2.6.git.orig/net/netfilter/nf_conntrack_netlink.c 2008-01-02 03:43:36.000000000 +0100
+++ net-2.6.git/net/netfilter/nf_conntrack_netlink.c 2008-01-02 04:55:38.000000000 +0100
@@ -4,7 +4,7 @@
* (C) 2001 by Jay Schulist <jschlst@samba.org>
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005-2007 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2005-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* Initial connection tracking via netlink development funded and
* generally made possible by Network Robots, Inc. (www.networkrobots.com)
@@ -427,6 +427,9 @@ static int ctnetlink_conntrack_event(str
if (ct == &nf_conntrack_untracked)
return NOTIFY_DONE;
+ if (events & IPCT_VOLATILE)
+ return NOTIFY_DONE;
+
if (events & IPCT_DESTROY) {
type = IPCTNL_MSG_CT_DELETE;
group = NFNLGRP_CONNTRACK_DESTROY;
Index: net-2.6.git/net/netfilter/xt_CONNTRACK.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ net-2.6.git/net/netfilter/xt_CONNTRACK.c 2008-01-02 05:03:23.000000000 +0100
@@ -0,0 +1,304 @@
+/*
+ * (C) 2008 Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on the following previous works:
+ * CONNMARK target: Henrik Nordstrom <hno@marasystems.com>
+ * NOTRACK target: Jeremy Kerr <jk@ozlabs.org>
+ * CONNSECMARK target: James Morris <jmorris@redhat.com>
+ * TIMEOUT target: Phil Oester <kernel@linuxace.com>
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNTRACK.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_ecache.h>
+
+#define PFX "xt_CONNTRACK: "
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
+MODULE_DESCRIPTION("ip[6]tables CONNTRACK module");
+MODULE_ALIAS("ipt_CONNTRACK");
+MODULE_ALIAS("ip6t_CONNTRACK");
+
+#define CT_TG_MASK(x) (x->data_0)
+#define CT_TG_MARK(x) (x->data_1)
+
+static void mark_set(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ u_int32_t newmark;
+
+ newmark = (ct->mark & ~CT_TG_MASK(info)) | CT_TG_MARK(info);
+ if (newmark != ct->mark) {
+ ct->mark = newmark;
+ nf_conntrack_event_cache(IPCT_MARK, skb);
+ }
+}
+
+static void mark_save(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ u_int32_t newmark;
+
+ newmark = (ct->mark & ~CT_TG_MASK(info)) |
+ (skb->mark & CT_TG_MASK(info));
+ if (ct->mark != newmark) {
+ ct->mark = newmark;
+ nf_conntrack_event_cache(IPCT_MARK, skb);
+ }
+}
+
+static void mark_restore(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ u_int32_t mark, diff;
+
+ mark = skb->mark;
+ diff = (ct->mark ^ mark) & CT_TG_MASK(info);
+ skb->mark = mark ^ diff;
+}
+
+static void secmark_save(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ if (skb->secmark && !ct->secmark) {
+ ct->secmark = skb->secmark;
+ nf_conntrack_event_cache(IPCT_SECMARK, skb);
+ }
+}
+
+static void secmark_restore(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ if (!skb->secmark && ct->secmark)
+ skb->secmark = ct->secmark;
+}
+
+static void notrack(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ /* Previously seen (loopback)? Ignore. */
+ if (skb->nfct != NULL)
+ return;
+
+ /* Attach fake conntrack entry.
+ * If there is a real ct entry correspondig to this packet,
+ * it'll hang aroun till timing out. We don't deal with it
+ * for performance reasons. JK */
+ skb->nfct = &nf_conntrack_untracked.ct_general;
+ skb->nfctinfo = IP_CT_NEW;
+ nf_conntrack_get(skb->nfct);
+}
+
+#define CT_TG_TIMEOUT(x) (x->data_0)
+
+static void manual_timeout(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ struct nf_conn_timeout *timeout_ext;
+
+ timeout_ext = nfct_timeout(ct);
+ if (!timeout_ext) {
+ timeout_ext = nf_ct_ext_add(ct, NF_CT_EXT_TIMEOUT, GFP_ATOMIC);
+ if (timeout_ext == NULL) {
+ pr_debug("failed to add TIMEOUT extension\n");
+ return;
+ }
+ }
+ timeout_ext->timeout = CT_TG_TIMEOUT(info) * HZ;
+ set_bit(IPS_MANUAL_TIMEOUT_BIT, &ct->status);
+}
+
+static void volatile_events(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info)
+{
+ nf_conntrack_event_cache(IPCT_VOLATILE, skb);
+}
+
+typedef void (*ct_tg_array)(struct sk_buff *skb,
+ struct nf_conn *ct,
+ const struct xt_conntrack_tg_info *info);
+
+ct_tg_array conntrack_tg_array[CONNTRACK_TG_MAX] = {
+ [CONNTRACK_TG_MARK_SET] = mark_set,
+ [CONNTRACK_TG_MARK_SAVE] = mark_save,
+ [CONNTRACK_TG_MARK_RESTORE] = mark_restore,
+ [CONNTRACK_TG_SECMARK_SAVE] = secmark_save,
+ [CONNTRACK_TG_SECMARK_RESTORE] = secmark_restore,
+ [CONNTRACK_TG_NOTRACK] = notrack,
+ [CONNTRACK_TG_MANUAL_TIMEOUT] = manual_timeout,
+ [CONNTRACK_TG_VOLATILE_EVENTS] = volatile_events,
+};
+
+static unsigned int
+conntrack_tg(struct sk_buff *skb, const struct net_device *in,
+ const struct net_device *out, unsigned int hooknum,
+ const struct xt_target *target, const void *targinfo)
+{
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ const struct xt_conntrack_tg_info *info = targinfo;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (!ct)
+ return XT_CONTINUE;
+
+ if (ct == &nf_conntrack_untracked)
+ return XT_CONTINUE;
+
+ conntrack_tg_array[info->mode](skb, ct, info);
+
+ return XT_CONTINUE;
+}
+
+static bool
+conntrack_tg_check(const char *tablename, const void *entry,
+ const struct xt_target *target, void *targinfo,
+ unsigned int hook_mask)
+{
+ const struct xt_conntrack_tg_info *info = targinfo;
+
+ switch(info->mode) {
+ case CONNTRACK_TG_MARK_SET:
+ case CONNTRACK_TG_MARK_SAVE:
+ case CONNTRACK_TG_MARK_RESTORE:
+ case CONNTRACK_TG_SECMARK_SAVE:
+ case CONNTRACK_TG_SECMARK_RESTORE:
+ case CONNTRACK_TG_MANUAL_TIMEOUT:
+ case CONNTRACK_TG_VOLATILE_EVENTS:
+ if (strcmp(tablename, "mangle") != 0) {
+ printk(KERN_INFO PFX "use mode %hu in table "
+ "`mangle\'\n", info->mode);
+ return false;
+ }
+ break;
+ case CONNTRACK_TG_NOTRACK:
+ if (strcmp(tablename, "raw") != 0) {
+ printk(KERN_INFO PFX "use mode: %hu in table "
+ "`raw\'\n", info->mode);
+ return false;
+ }
+ break;
+ default:
+ printk(KERN_INFO PFX "unsupported mode: %hu\n", info->mode);
+ return false;
+ }
+
+ if (nf_ct_l3proto_try_module_get(target->family) < 0) {
+ printk(KERN_WARNING "can't load conntrack support for "
+ "proto=%u\n", target->family);
+ return false;
+ }
+ return true;
+}
+
+static void
+conntrack_tg_destroy(const struct xt_target *target, void *targinfo)
+{
+ nf_ct_l3proto_module_put(target->family);
+}
+
+static struct xt_target conntrack_tg_mangle_reg[] __read_mostly = {
+ {
+ .name = "CONNTRACK",
+ .family = AF_INET,
+ .checkentry = conntrack_tg_check,
+ .destroy = conntrack_tg_destroy,
+ .target = conntrack_tg,
+ .targetsize = sizeof(struct xt_conntrack_tg_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "CONNTRACK",
+ .family = AF_INET6,
+ .checkentry = conntrack_tg_check,
+ .destroy = conntrack_tg_destroy,
+ .target = conntrack_tg,
+ .targetsize = sizeof(struct xt_conntrack_tg_info),
+ .table = "mangle",
+ .me = THIS_MODULE,
+ },
+};
+
+static struct xt_target conntrack_tg_raw_reg[] __read_mostly = {
+ {
+ .name = "CONNTRACK",
+ .family = AF_INET,
+ .checkentry = conntrack_tg_check,
+ .destroy = conntrack_tg_destroy,
+ .target = conntrack_tg,
+ .targetsize = sizeof(struct xt_conntrack_tg_info),
+ .table = "raw",
+ .me = THIS_MODULE,
+ },
+ {
+ .name = "CONNTRACK",
+ .family = AF_INET6,
+ .checkentry = conntrack_tg_check,
+ .destroy = conntrack_tg_destroy,
+ .target = conntrack_tg,
+ .targetsize = sizeof(struct xt_conntrack_tg_info),
+ .table = "raw",
+ .me = THIS_MODULE,
+ },
+};
+
+static struct nf_ct_ext_type timeout_extend __read_mostly = {
+ .len = sizeof(struct nf_conn_timeout),
+ .align = __alignof__(struct nf_conn_timeout),
+ .id = NF_CT_EXT_TIMEOUT,
+};
+
+static int __init conntrack_tg_init(void)
+{
+ int ret;
+
+ ret = nf_ct_extend_register(&timeout_extend);
+ if (ret < 0) {
+ printk(KERN_ERR PFX "unable to register extension\n");
+ return ret;
+ }
+
+ ret = xt_register_targets(conntrack_tg_mangle_reg,
+ ARRAY_SIZE(conntrack_tg_mangle_reg));
+ if (ret < 0)
+ nf_ct_extend_unregister(&timeout_extend);
+
+ ret = xt_register_targets(conntrack_tg_raw_reg,
+ ARRAY_SIZE(conntrack_tg_raw_reg));
+ if (ret < 0) {
+ nf_ct_extend_unregister(&timeout_extend);
+ xt_unregister_targets(conntrack_tg_mangle_reg,
+ ARRAY_SIZE(conntrack_tg_mangle_reg));
+ }
+
+ return ret;
+}
+
+static void __exit conntrack_tg_exit(void)
+{
+ nf_ct_extend_unregister(&timeout_extend);
+ xt_unregister_targets(conntrack_tg_mangle_reg,
+ ARRAY_SIZE(conntrack_tg_mangle_reg));
+ xt_unregister_targets(conntrack_tg_raw_reg,
+ ARRAY_SIZE(conntrack_tg_raw_reg));
+}
+
+module_init(conntrack_tg_init);
+module_exit(conntrack_tg_exit);
Index: net-2.6.git/include/linux/netfilter/xt_CONNTRACK.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ net-2.6.git/include/linux/netfilter/xt_CONNTRACK.h 2008-01-02 05:03:40.000000000 +0100
@@ -0,0 +1,22 @@
+#ifndef _XT_CONNTRACK_H_target
+#define _XT_CONNTRACK_H_target
+
+enum {
+ CONNTRACK_TG_MARK_SET = 0,
+ CONNTRACK_TG_MARK_SAVE,
+ CONNTRACK_TG_MARK_RESTORE,
+ CONNTRACK_TG_SECMARK_SAVE,
+ CONNTRACK_TG_SECMARK_RESTORE,
+ CONNTRACK_TG_NOTRACK,
+ CONNTRACK_TG_MANUAL_TIMEOUT,
+ CONNTRACK_TG_VOLATILE_EVENTS,
+ CONNTRACK_TG_MAX
+};
+
+struct xt_conntrack_tg_info {
+ u_int32_t mode;
+ u_int32_t data_0;
+ u_int32_t data_1;
+};
+
+#endif /*_XT_CONNTRACK_H_target */
next prev parent reply other threads:[~2008-01-14 16:29 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-14 16:19 [RFC] generic CONNTRACK target Pablo Neira Ayuso
2008-01-14 16:29 ` Pablo Neira Ayuso [this message]
2008-01-14 17:00 ` Jan Engelhardt
2008-01-15 6:40 ` Patrick McHardy
2008-01-15 12:27 ` Jan Engelhardt
2008-01-15 14:11 ` Patrick McHardy
2008-01-15 6:42 ` Patrick McHardy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=478B8DF1.3060503@netfilter.org \
--to=pablo@netfilter.org \
--cc=kaber@trash.net \
--cc=kernel@linuxace.com \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.