* xt_connlimit kernel 20070620
@ 2007-06-19 22:41 Jan Engelhardt
2007-06-19 22:41 ` xt_connlimit iptables 20070620 Jan Engelhardt
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-19 22:41 UTC (permalink / raw)
To: kaber; +Cc: Netfilter Developer Mailing List
[-- Attachment #1: Type: TEXT/PLAIN, Size: 10016 bytes --]
Adds the xt_connlimit match to the kernel.
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
include/linux/netfilter/xt_connlimit.h | 14 +
net/netfilter/Kconfig | 7
net/netfilter/Makefile | 1
net/netfilter/xt_connlimit.c | 259 +++++++++++++++++++++++++++++++++
4 files changed, 281 insertions(+)
Index: linux-2.6.22/include/linux/netfilter/xt_connlimit.h
===================================================================
--- /dev/null
+++ linux-2.6.22/include/linux/netfilter/xt_connlimit.h
@@ -0,0 +1,14 @@
+#ifndef _XT_CONNLIMIT_H
+#define _XT_CONNLIMIT_H
+
+struct xt_connlimit_data;
+
+struct xt_connlimit_info {
+ u_int32_t mask;
+ unsigned int limit, inverse;
+
+ /* this needs to be at the end */
+ struct xt_connlimit_data *data;
+};
+
+#endif /* _XT_CONNLIMIT_H */
Index: linux-2.6.22/net/netfilter/Kconfig
===================================================================
--- linux-2.6.22.orig/net/netfilter/Kconfig
+++ linux-2.6.22/net/netfilter/Kconfig
@@ -411,6 +411,13 @@ config NETFILTER_XT_MATCH_CONNBYTES
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_CONNLIMIT
+ tristate '"connlimit" match support"'
+ depends on NETFILTER_XTABLES && NF_CONNTRACK_IPV4
+ ---help---
+ This match allows you to match against the number of parallel TCP
+ connections to a server per client IP address (or address block).
+
config NETFILTER_XT_MATCH_CONNMARK
tristate '"connmark" connection mark match support'
depends on NETFILTER_XTABLES
Index: linux-2.6.22/net/netfilter/Makefile
===================================================================
--- linux-2.6.22.orig/net/netfilter/Makefile
+++ linux-2.6.22/net/netfilter/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSEC
# matches
obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
Index: linux-2.6.22/net/netfilter/xt_connlimit.c
===================================================================
--- /dev/null
+++ linux-2.6.22/net/netfilter/xt_connlimit.c
@@ -0,0 +1,259 @@
+/*
+ * netfilter module to limit the number of parallel tcp
+ * connections per IP address.
+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
+ * only ignore TIME_WAIT or gone connections
+ * © Jan Engelhardt <jengelh@gmx.de>, 2007
+ *
+ * based on ...
+ *
+ * Kernel module to match connection tracking information.
+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
+ */
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/jhash.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/netfilter/nf_conntrack_tcp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_connlimit.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_tuple.h>
+
+#define DEBUG 0
+
+/* we will save the tuples of all connections we care about */
+struct xt_connlimit_conn {
+ struct list_head list;
+ struct nf_conntrack_tuple tuple;
+};
+
+struct xt_connlimit_data {
+ struct list_head iphash[256];
+ spinlock_t lock;
+};
+
+static u_int32_t connlimit_iphash_rnd;
+
+static inline unsigned int connlimit_iphash(u_int32_t addr)
+{
+ return jhash_1word(addr, connlimit_iphash_rnd);
+}
+
+static int count_them(struct xt_connlimit_data *data, u_int32_t addr,
+ u_int32_t mask, struct nf_conn *ct)
+{
+#if DEBUG
+ static const char const *tcp_state[] = {
+ "none", "established", "syn_sent", "syn_recv", "fin_wait",
+ "time_wait", "close", "close_wait", "last_ack", "listen"
+ };
+#endif
+ struct nf_conntrack_tuple_hash *found;
+ struct nf_conntrack_tuple tuple;
+ struct xt_connlimit_conn *conn;
+ const struct list_head *lh;
+ struct nf_conn *found_ct;
+ struct list_head *hash;
+ bool addit = true;
+ int matches = 0;
+
+ tuple = ct->tuplehash[0].tuple;
+ hash = &data->iphash[connlimit_iphash(addr & mask)];
+
+ /* check the saved connections */
+ list_for_each(lh, hash) {
+ conn = list_entry(lh, struct xt_connlimit_conn, list);
+ found = nf_conntrack_find_get(&conn->tuple, ct);
+ found_ct = NULL;
+
+ if (found != NULL &&
+ (found_ct = nf_ct_tuplehash_to_ctrack(found)) != NULL &&
+ memcmp(&conn->tuple, &tuple, sizeof(tuple)) == 0 &&
+ found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT)
+ /*
+ * Just to be sure we have it only once in the list.
+ * We should not see tuples twice unless someone hooks
+ * this into a table without "-p tcp --syn".
+ */
+ addit = false;
+
+#if DEBUG
+ printk(KERN_WARNING "xt_connlimit [%u]: src=%u.%u.%u.%u:%u "
+ "dst=%u.%u.%u.%u:%d %s\n",
+ connlimit_iphash(addr & mask),
+ NIPQUAD(conn->tuple.src.u3.ip),
+ ntohs(conn->tuple.src.u.tcp.port),
+ NIPQUAD(conn->tuple.dst.u3.ip),
+ ntohs(conn->tuple.dst.u.tcp.port),
+ (found == NULL) ? "gone" :
+ tcp_state[found_ct->proto.tcp.state]);
+#endif
+
+ if (found == NULL) {
+ /* this one is gone */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ continue;
+ }
+
+ if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
+ /*
+ * we do not care about connections which are
+ * closed already -> ditch it
+ */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ nf_conntrack_put(&found_ct->ct_general);
+ continue;
+ }
+
+ if ((addr & mask) == (conn->tuple.src.u3.ip & mask))
+ /* same source network -> be counted! */
+ ++matches;
+
+ nf_conntrack_put(&found_ct->ct_general);
+ }
+
+ if (addit) {
+ /* save the new connection in our list */
+#if DEBUG
+ printk(KERN_WARNING "xt_connlimit [%u]: src=%u.%u.%u.%u:%u "
+ "dst=%u.%u.%u.%u:%u new\n",
+ connlimit_iphash(addr & mask),
+ NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port),
+ NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port));
+#endif
+
+ conn = kzalloc(sizeof(*conn), GFP_ATOMIC);
+ if (conn == NULL)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&conn->list);
+ conn->tuple = tuple;
+ list_add(&conn->list, hash);
+ ++matches;
+ }
+
+ return matches;
+}
+
+static bool connlimit_match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const struct xt_match *match,
+ const void *matchinfo, int offset,
+ unsigned int protoff, bool *hotdrop)
+{
+ const struct xt_connlimit_info *info = matchinfo;
+ enum ip_conntrack_info ctinfo;
+ const struct iphdr *iph;
+ int connections, rv;
+ struct nf_conn *ct;
+
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct == NULL) {
+ printk(KERN_INFO "xt_connlimit: INVALID connection\n");
+ *hotdrop = 1;
+ return false;
+ }
+
+ iph = ip_hdr(skb);
+ spin_lock_bh(&info->data->lock);
+ connections = count_them(info->data, iph->saddr, info->mask, ct);
+ spin_unlock_bh(&info->data->lock);
+
+ if (connections < 0) {
+ /* kmalloc failed, drop it entirely */
+ printk(KERN_DEBUG "xt_connlimit: kmalloc failed\n");
+ *hotdrop = 1;
+ return false;
+ }
+
+ rv = info->inverse ^ (connections > info->limit);
+#if DEBUG
+ printk(KERN_DEBUG "xt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
+ "connections=%d limit=%u match=%s\n",
+ NIPQUAD(iph->saddr), NIPQUAD(info->mask),
+ connections, info->limit, match ? "yes" : "no");
+#endif
+
+ return rv;
+}
+
+static bool connlimit_check(const char *tablename, const void *ip,
+ const struct xt_match *match, void *matchinfo,
+ unsigned int hook_mask)
+{
+ struct xt_connlimit_info *info = matchinfo;
+ unsigned int i;
+
+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+ printk(KERN_WARNING "cannot load conntrack support for "
+ "address family %u\n", match->family);
+ return false;
+ }
+
+ /* init private data */
+ info->data = kmalloc(sizeof(struct xt_connlimit_data), GFP_KERNEL);
+ spin_lock_init(&info->data->lock);
+ for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i)
+ INIT_LIST_HEAD(&info->data->iphash[i]);
+
+ return true;
+}
+
+static void connlimit_destroy(const struct xt_match *match, void *matchinfo)
+{
+ struct xt_connlimit_info *info = matchinfo;
+ struct xt_connlimit_conn *conn;
+ struct list_head *hash;
+ struct list_head *hash_next;
+ unsigned int i;
+
+ nf_ct_l3proto_module_put(match->family);
+
+ for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) {
+ list_for_each_safe(hash, hash_next, &info->data->iphash[i]) {
+ conn = list_entry(hash, struct xt_connlimit_conn, list);
+ list_del(hash);
+ kfree(conn);
+ }
+ }
+
+ kfree(info->data);
+}
+
+static struct xt_match connlimit_reg = {
+ .name = "connlimit",
+ .family = AF_INET,
+ .checkentry = connlimit_check,
+ .match = connlimit_match,
+ .matchsize = sizeof(struct xt_connlimit_info),
+ .destroy = connlimit_destroy,
+ .me = THIS_MODULE,
+};
+
+static int __init xt_connlimit_init(void)
+{
+ get_random_bytes(&connlimit_iphash_rnd, sizeof(connlimit_iphash_rnd));
+ return xt_register_match(&connlimit_reg);
+}
+
+static void __exit xt_connlimit_exit(void)
+{
+ xt_unregister_match(&connlimit_reg);
+}
+
+module_init(xt_connlimit_init);
+module_exit(xt_connlimit_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_connlimit");
^ permalink raw reply [flat|nested] 15+ messages in thread
* xt_connlimit iptables 20070620
2007-06-19 22:41 xt_connlimit kernel 20070620 Jan Engelhardt
@ 2007-06-19 22:41 ` Jan Engelhardt
2007-06-19 22:45 ` xt_connlimit kernel 20070620 Jan Engelhardt
2007-06-20 9:47 ` Pablo Neira Ayuso
2 siblings, 0 replies; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-19 22:41 UTC (permalink / raw)
To: kaber; +Cc: Netfilter Developer Mailing List
Subject: Add connlimit to iptables.
Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
---
extensions/.connlimit-test | 2
extensions/libipt_connlimit.c | 129 ++++++++++++++++++++++++++++++++++++++++
extensions/libipt_connlimit.man | 21 ++++++
3 files changed, 152 insertions(+)
Index: iptables/extensions/.connlimit-test
===================================================================
--- /dev/null
+++ iptables/extensions/.connlimit-test
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f "$KERNEL_DIR/include/linux/netfilter/xt_connlimit.h" ] && echo connlimit
Index: iptables/extensions/libipt_connlimit.c
===================================================================
--- /dev/null
+++ iptables/extensions/libipt_connlimit.c
@@ -0,0 +1,129 @@
+/* Shared library add-on to iptables to add connection limit support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+#include <iptables.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter/xt_connlimit.h>
+
+/* Function which prints out usage message. */
+static void help(void)
+{
+ printf(
+"connlimit v%s options:\n"
+"[!] --connlimit-above n match if the number of existing tcp connections is (not) above n\n"
+" --connlimit-mask n group hosts using mask\n"
+"\n", IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+ {"connlimit-above", 1, NULL, '1'},
+ {"connlimit-mask", 1, NULL, '2'},
+ {NULL},
+};
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ipt_entry *entry, unsigned int *nfcache,
+ struct ipt_entry_match **match)
+{
+ struct xt_connlimit_info *info = (void *)(*match)->data;
+ int i;
+
+ if (!(*flags & 2))
+ /*
+ * set default mask unless we have already seen a mask option
+ */
+ info->mask = htonl(0xFFFFFFFF);
+
+ switch (c) {
+ case '1':
+ check_inverse(optarg, &invert, &optind, 0);
+ info->limit = strtoul(argv[optind-1], NULL, 0);
+ info->inverse = invert;
+ *flags |= 1;
+ break;
+
+ case '2':
+ i = strtol(argv[optind-1], NULL, 0);
+ if (i < 0 || i > 32)
+ exit_error(PARAMETER_PROBLEM,
+ "--connlimit-mask must be between 0 and 32");
+
+ if (i == 0)
+ info->mask = 0;
+ else
+ info->mask = htonl(0xFFFFFFFF << (32 - i));
+
+ *flags |= 2;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Final check */
+static void final_check(unsigned int flags)
+{
+ if (!(flags & 1))
+ exit_error(PARAMETER_PROBLEM, "You must specify `--connlimit-above'");
+}
+
+static int count_bits(u_int32_t mask)
+{
+ int i, bits;
+
+ for (bits = 0, i = 31; i >= 0; i--) {
+ if (mask & htonl((u_int32_t)1 << i)) {
+ bits++;
+ continue;
+ }
+ break;
+ }
+ return bits;
+}
+
+/* Prints out the matchinfo. */
+static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match,
+ int numeric)
+{
+ const struct xt_connlimit_info *info = (const void *)match->data;
+
+ printf("#conn/%d %s %d ", count_bits(info->mask),
+ info->inverse ? "<" : ">", info->limit);
+}
+
+/* Saves the matchinfo in parsable form to stdout. */
+static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+{
+ const struct xt_connlimit_info *info = (const void *)match->data;
+
+ printf("%s--connlimit-above %u --connlimit-mask %u ",
+ info->inverse ? "! " : "", info->limit,
+ count_bits(info->mask));
+}
+
+static struct iptables_match connlimit = {
+ .name = "connlimit",
+ .version = IPTABLES_VERSION,
+ .size = IPT_ALIGN(sizeof(struct xt_connlimit_info)),
+ .userspacesize = offsetof(struct xt_connlimit_info, data),
+ .help = help,
+ .parse = parse,
+ .final_check = final_check,
+ .print = print,
+ .save = save,
+ .extra_opts = opts,
+};
+
+static __attribute__((constructor)) void libipt_connlimit_init(void)
+{
+ register_match(&connlimit);
+}
Index: iptables/extensions/libipt_connlimit.man
===================================================================
--- /dev/null
+++ iptables/extensions/libipt_connlimit.man
@@ -0,0 +1,21 @@
+Allows you to restrict the number of parallel TCP connections to a
+server per client IP address (or address block).
+.TP
+[\fB!\fR] \fB--connlimit-above \fIn\fR
+match if the number of existing tcp connections is (not) above n
+.TP
+.BI "--connlimit-mask " "bits"
+group hosts using mask
+.P
+Examples:
+.TP
+# allow 2 telnet connections per client host
+iptables -A INPUT -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
+.TP
+# you can also match the other way around:
+iptables -A INPUT -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
+.TP
+# limit the nr of parallel http requests to 16 per class C sized \
+network (24 bit netmask)
+iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16
+--connlimit-mask 24 -j REJECT
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-19 22:41 xt_connlimit kernel 20070620 Jan Engelhardt
2007-06-19 22:41 ` xt_connlimit iptables 20070620 Jan Engelhardt
@ 2007-06-19 22:45 ` Jan Engelhardt
2007-06-20 9:47 ` Pablo Neira Ayuso
2 siblings, 0 replies; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-19 22:45 UTC (permalink / raw)
To: kaber; +Cc: Netfilter Developer Mailing List
On Jun 20 2007 00:41, Jan Engelhardt wrote:
>Adds the xt_connlimit match to the kernel.
Screw it, crashes...
Jan
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-19 22:41 xt_connlimit kernel 20070620 Jan Engelhardt
2007-06-19 22:41 ` xt_connlimit iptables 20070620 Jan Engelhardt
2007-06-19 22:45 ` xt_connlimit kernel 20070620 Jan Engelhardt
@ 2007-06-20 9:47 ` Pablo Neira Ayuso
2007-06-20 10:29 ` Jan Engelhardt
2 siblings, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-20 9:47 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List, kaber
Jan Engelhardt wrote:
> Adds the xt_connlimit match to the kernel.
>
> Signed-off-by: Jan Engelhardt <jengelh@gmx.de>
>
> ---
> include/linux/netfilter/xt_connlimit.h | 14 +
> net/netfilter/Kconfig | 7
> net/netfilter/Makefile | 1
> net/netfilter/xt_connlimit.c | 259 +++++++++++++++++++++++++++++++++
> 4 files changed, 281 insertions(+)
>
> Index: linux-2.6.22/include/linux/netfilter/xt_connlimit.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6.22/include/linux/netfilter/xt_connlimit.h
> @@ -0,0 +1,14 @@
> +#ifndef _XT_CONNLIMIT_H
> +#define _XT_CONNLIMIT_H
> +
> +struct xt_connlimit_data;
> +
> +struct xt_connlimit_info {
> + u_int32_t mask;
> + unsigned int limit, inverse;
> +
> + /* this needs to be at the end */
> + struct xt_connlimit_data *data;
^^^
IIRC, this should be:
struct xt_connlimit_data __attribute__((aligned(8))) *data;
to avoid problems with 32/64 bits architectures.
> +};
> +
> +#endif /* _XT_CONNLIMIT_H */
> Index: linux-2.6.22/net/netfilter/xt_connlimit.c
> ===================================================================
[...]
> +
> + if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
> + /*
> + * we do not care about connections which are
> + * closed already -> ditch it
> + */
> + lh = lh->prev;
> + list_del(lh->next);
> + kfree(conn);
> + nf_conntrack_put(&found_ct->ct_general);
> + continue;
> + }
This match seems completely dependent of TCP. I think that it would be
worth a rework. Luke, use the connection tracking event API :)
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 9:47 ` Pablo Neira Ayuso
@ 2007-06-20 10:29 ` Jan Engelhardt
2007-06-20 11:07 ` Pablo Neira Ayuso
0 siblings, 1 reply; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-20 10:29 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Developer Mailing List, kaber
On Jun 20 2007 11:47, Pablo Neira Ayuso wrote:
>> +
>> +struct xt_connlimit_info {
>> + u_int32_t mask;
>> + unsigned int limit, inverse;
>> +
>> + /* this needs to be at the end */
>> + struct xt_connlimit_data *data;
> ^^^
> IIRC, this should be:
>
> struct xt_connlimit_data __attribute__((aligned(8))) *data;
>
> to avoid problems with 32/64 bits architectures.
->data is a member that is only used by the kernel. Is the aligned(8)
still needed?
>> + if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
>> + /*
>> + * we do not care about connections which are
>> + * closed already -> ditch it
>> + */
>> + lh = lh->prev;
>> + list_del(lh->next);
>> + kfree(conn);
>> + nf_conntrack_put(&found_ct->ct_general);
>> + continue;
>> + }
>
> This match seems completely dependent of TCP.
But it works with UDP too. This if() block looks merely like a
watch-out-for-TCP exception. (And obviously, lacks SCTP/DCCP checking.)
> I think that it would be worth a
> rework. Luke, use the connection tracking event API :)
Where may I find examples?
Jan
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 10:29 ` Jan Engelhardt
@ 2007-06-20 11:07 ` Pablo Neira Ayuso
2007-06-20 11:32 ` Jan Engelhardt
0 siblings, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-20 11:07 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List, kaber
Jan Engelhardt wrote:
> On Jun 20 2007 11:47, Pablo Neira Ayuso wrote:
>>> +
>>> +struct xt_connlimit_info {
>>> + u_int32_t mask;
>>> + unsigned int limit, inverse;
>>> +
>>> + /* this needs to be at the end */
>>> + struct xt_connlimit_data *data;
>> ^^^
>> IIRC, this should be:
>>
>> struct xt_connlimit_data __attribute__((aligned(8))) *data;
>>
>> to avoid problems with 32/64 bits architectures.
>
> ->data is a member that is only used by the kernel. Is the aligned(8)
> still needed?
Yes, some architectures use 64 bits for long/pointers in kernel space
but use 32 bits in userspace. Since the private match info memory blob
is passed from userspace to kernel, the size checking fails. This won't
be a problem if we wouldn't share structure between kernel and
userspace. IIRC, even for the 32/64 bits compatibility mode for x86_64
leads to problems. Solution: we force 8 bytes allocation
>>> + if (found_ct->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
>>> + /*
>>> + * we do not care about connections which are
>>> + * closed already -> ditch it
>>> + */
>>> + lh = lh->prev;
>>> + list_del(lh->next);
>>> + kfree(conn);
>>> + nf_conntrack_put(&found_ct->ct_general);
>>> + continue;
>>> + }
>> This match seems completely dependent of TCP.
>
> But it works with UDP too. This if() block looks merely like a
> watch-out-for-TCP exception. (And obviously, lacks SCTP/DCCP checking.)
I see, still I think that it would be worth to make it completely
independent of it.
>> I think that it would be worth a
>> rework. Luke, use the connection tracking event API :)
>
> Where may I find examples?
Have a look at nf_conntrack_netlink.c look for the x_events() function.
If you have more questions on it. Let me know.
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 11:07 ` Pablo Neira Ayuso
@ 2007-06-20 11:32 ` Jan Engelhardt
2007-06-20 12:01 ` Pablo Neira Ayuso
0 siblings, 1 reply; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-20 11:32 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Developer Mailing List, kaber
On Jun 20 2007 13:07, Pablo Neira Ayuso wrote:
>>
>> But it works with UDP too. This if() block looks merely like a
>> watch-out-for-TCP exception. (And obviously, lacks SCTP/DCCP checking.)
>
> I see, still I think that it would be worth to make it completely independent
> of it.
UDP does not have a transition from ESTABLISHED -> TIME_WAIT, to begin with.
>> > I think that it would be worth a
>> > rework. Luke, use the connection tracking event API :)
>>
>> Where may I find examples?
>
> Have a look at nf_conntrack_netlink.c look for the x_events() function. If
> you have more questions on it. Let me know.
I think netlink is an overkill here. Well, at least I could not find
something usable right away.
Something like
myfunction( ??? )
{
/* kill connlimit entry */
}
__init init_module()
{
nf_register_whatever(ON_TCP_TRANSITION, myfunction);
}
I just don't see any modules (matches, targets) that use events yet.
Could you cook it up?
Jan
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 11:32 ` Jan Engelhardt
@ 2007-06-20 12:01 ` Pablo Neira Ayuso
2007-06-20 12:35 ` Jan Engelhardt
2007-06-20 12:47 ` Patrick McHardy
0 siblings, 2 replies; 15+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-20 12:01 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Netfilter Developer Mailing List, kaber
Jan Engelhardt wrote:
> On Jun 20 2007 13:07, Pablo Neira Ayuso wrote:
>>> But it works with UDP too. This if() block looks merely like a
>>> watch-out-for-TCP exception. (And obviously, lacks SCTP/DCCP checking.)
>> I see, still I think that it would be worth to make it completely independent
>> of it.
>
> UDP does not have a transition from ESTABLISHED -> TIME_WAIT, to begin with.
But the event API has the DESTROY transition. There are three kind of
events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
the entry from the hashtable.
>>>> I think that it would be worth a
>>>> rework. Luke, use the connection tracking event API :)
>>> Where may I find examples?
>> Have a look at nf_conntrack_netlink.c look for the x_events() function. If
>> you have more questions on it. Let me know.
>
> I think netlink is an overkill here. Well, at least I could not find
> something usable right away.
No, I didn't mean to use netlink. Just the connection tracking event
API. See the example below.
> Something like
>
> myfunction( ??? )
> {
> /* kill connlimit entry */
> }
>
> __init init_module()
> {
> nf_register_whatever(ON_TCP_TRANSITION, myfunction);
> }
>
> I just don't see any modules (matches, targets) that use events yet.
> Could you cook it up?
Does this give you a clue?
static int event(struct notifier_block *this, unsigned long events, void
*ptr)
{
struct nf_conn *ct = (struct nf_conn *)ptr;
if (ct == &nf_conntrack_untracked)
return NOTIFY_DONE;
if (events & IPCT_NEW)
printk("ct %p has been created\n", ct);
if (events & IPCT_DESTROY)
printk("ct %p has been destroy\n", ct);
return NOTIFY_DONE;
}
static struct notifier_block ctnl_notifier = {
.notifier_call = event,
};
static int __init init(void)
{
ret = nf_conntrack_register_notifier(&ctnl_notifier);
...
}
...
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 12:01 ` Pablo Neira Ayuso
@ 2007-06-20 12:35 ` Jan Engelhardt
2007-06-20 12:47 ` Patrick McHardy
1 sibling, 0 replies; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-20 12:35 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Netfilter Developer Mailing List, kaber
On Jun 20 2007 14:01, Pablo Neira Ayuso wrote:
> Does this give you a clue?
It is a start. Thank you.
> static int event(struct notifier_block *this, unsigned long events, void *ptr)
> {
> struct nf_conn *ct = (struct nf_conn *)ptr;
>
> if (ct == &nf_conntrack_untracked)
> return NOTIFY_DONE;
>
> if (events & IPCT_NEW)
> printk("ct %p has been created\n", ct);
> if (events & IPCT_DESTROY)
> printk("ct %p has been destroy\n", ct);
Correct me if I am wrong, but I think DESTROY is thrown when the connection
_really_ disappears, e.g. disappear from `conntrack -L`
(/proc/net/ip_conntrack). But TIME_WAIT connections still show up in
/proc/net/ip_conntrack and/or `conntrack -L`.
Or not?
Jan
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 12:01 ` Pablo Neira Ayuso
2007-06-20 12:35 ` Jan Engelhardt
@ 2007-06-20 12:47 ` Patrick McHardy
2007-06-20 12:56 ` Jan Engelhardt
2007-06-21 15:39 ` Pablo Neira Ayuso
1 sibling, 2 replies; 15+ messages in thread
From: Patrick McHardy @ 2007-06-20 12:47 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Jan Engelhardt, Netfilter Developer Mailing List
Pablo Neira Ayuso wrote:
> Jan Engelhardt wrote:
>
>> UDP does not have a transition from ESTABLISHED -> TIME_WAIT, to begin
>> with.
>
>
> But the event API has the DESTROY transition. There are three kind of
> events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
> the entry from the hashtable.
Thats not a bad idea, but I always considered the notifier chains
overkill just for ctnetlink and thought about replacing them by
simple hooks. Adding another user for them would need some good
justification, also since it quite heavily adds to the overhead
for packet processing.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 12:47 ` Patrick McHardy
@ 2007-06-20 12:56 ` Jan Engelhardt
2007-06-21 15:39 ` Pablo Neira Ayuso
1 sibling, 0 replies; 15+ messages in thread
From: Jan Engelhardt @ 2007-06-20 12:56 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Netfilter Developer Mailing List, Pablo Neira Ayuso
On Jun 20 2007 14:47, Patrick McHardy wrote:
>Pablo Neira Ayuso wrote:
>> Jan Engelhardt wrote:
>>
>>> UDP does not have a transition from ESTABLISHED -> TIME_WAIT, to begin
>>> with.
>>
>> But the event API has the DESTROY transition. There are three kind of
>> events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
>> the entry from the hashtable.
>
>Thats not a bad idea, but I always considered the notifier chains
>overkill just for ctnetlink and thought about replacing them by
>simple hooks. Adding another user for them would need some good
>justification, also since it quite heavily adds to the overhead
>for packet processing.
In that case, let's move that issue to later and go with the
current approach :)
One thing catched my eye:
if (found != NULL &&
(found_ct = nf_ct_tuplehash_to_ctrack(found)) != NULL &&
memcmp(&conn->tuple, &tuple, sizeof(tuple)) == 0 &&
found_ct->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT)
I think we need to assure that the connection is actually TCP before
comparing ->proto.tcp.state. A check is needed, but which?
conn->tuple.dst.proto == IPPROTO_TCP or
found->tuple.dst.proto == IPPROTO_TCP,
or something completely different?
Jan
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-20 12:47 ` Patrick McHardy
2007-06-20 12:56 ` Jan Engelhardt
@ 2007-06-21 15:39 ` Pablo Neira Ayuso
2007-06-21 15:44 ` Patrick McHardy
1 sibling, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-21 15:39 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jan Engelhardt, Netfilter Developer Mailing List
Patrick McHardy wrote:
> Pablo Neira Ayuso wrote:
>> But the event API has the DESTROY transition. There are three kind of
>> events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
>> the entry from the hashtable.
>
> Thats not a bad idea, but I always considered the notifier chains
> overkill just for ctnetlink and thought about replacing them by
> simple hooks. Adding another user for them would need some good
> justification, also since it quite heavily adds to the overhead
> for packet processing.
The call_chain would be called only to catch DESTROY events (at timer
expiration). No need to register notifications for the the event NEW
since it can be get from the packet itself from ctinfo.
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-21 15:39 ` Pablo Neira Ayuso
@ 2007-06-21 15:44 ` Patrick McHardy
2007-06-21 15:50 ` Pablo Neira Ayuso
0 siblings, 1 reply; 15+ messages in thread
From: Patrick McHardy @ 2007-06-21 15:44 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Jan Engelhardt, Netfilter Developer Mailing List
Pablo Neira Ayuso wrote:
> Patrick McHardy wrote:
>
>>Pablo Neira Ayuso wrote:
>>
>>>But the event API has the DESTROY transition. There are three kind of
>>>events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
>>>the entry from the hashtable.
>>
>>Thats not a bad idea, but I always considered the notifier chains
>>overkill just for ctnetlink and thought about replacing them by
>>simple hooks. Adding another user for them would need some good
>>justification, also since it quite heavily adds to the overhead
>>for packet processing.
>
>
> The call_chain would be called only to catch DESTROY events (at timer
> expiration). No need to register notifications for the the event NEW
> since it can be get from the packet itself from ctinfo.
We only have a single notifier chain.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-21 15:44 ` Patrick McHardy
@ 2007-06-21 15:50 ` Pablo Neira Ayuso
2007-06-21 15:51 ` Patrick McHardy
0 siblings, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2007-06-21 15:50 UTC (permalink / raw)
To: Patrick McHardy; +Cc: Jan Engelhardt, Netfilter Developer Mailing List
Patrick McHardy wrote:
> Pablo Neira Ayuso wrote:
>> Patrick McHardy wrote:
>>
>>> Pablo Neira Ayuso wrote:
>>>
>>>> But the event API has the DESTROY transition. There are three kind of
>>>> events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
>>>> the entry from the hashtable.
>>> Thats not a bad idea, but I always considered the notifier chains
>>> overkill just for ctnetlink and thought about replacing them by
>>> simple hooks. Adding another user for them would need some good
>>> justification, also since it quite heavily adds to the overhead
>>> for packet processing.
>>
>> The call_chain would be called only to catch DESTROY events (at timer
>> expiration). No need to register notifications for the the event NEW
>> since it can be get from the packet itself from ctinfo.
>
> We only have a single notifier chain.
Worth to split them into three chains?
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: xt_connlimit kernel 20070620
2007-06-21 15:50 ` Pablo Neira Ayuso
@ 2007-06-21 15:51 ` Patrick McHardy
0 siblings, 0 replies; 15+ messages in thread
From: Patrick McHardy @ 2007-06-21 15:51 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Jan Engelhardt, Netfilter Developer Mailing List
Pablo Neira Ayuso wrote:
> Patrick McHardy wrote:
>
>>Pablo Neira Ayuso wrote:
>>
>>>Patrick McHardy wrote:
>>>
>>>
>>>>Pablo Neira Ayuso wrote:
>>>>
>>>>
>>>>>But the event API has the DESTROY transition. There are three kind of
>>>>>events: NEW, UPDATE and DESTROY. Just wait for DESTROY events to release
>>>>>the entry from the hashtable.
>>>>
>>>>Thats not a bad idea, but I always considered the notifier chains
>>>>overkill just for ctnetlink and thought about replacing them by
>>>>simple hooks. Adding another user for them would need some good
>>>>justification, also since it quite heavily adds to the overhead
>>>>for packet processing.
>>>
>>>The call_chain would be called only to catch DESTROY events (at timer
>>>expiration). No need to register notifications for the the event NEW
>>>since it can be get from the packet itself from ctinfo.
>>
>>We only have a single notifier chain.
>
>
> Worth to split them into three chains?
For connlimit? No.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2007-06-21 15:51 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-06-19 22:41 xt_connlimit kernel 20070620 Jan Engelhardt
2007-06-19 22:41 ` xt_connlimit iptables 20070620 Jan Engelhardt
2007-06-19 22:45 ` xt_connlimit kernel 20070620 Jan Engelhardt
2007-06-20 9:47 ` Pablo Neira Ayuso
2007-06-20 10:29 ` Jan Engelhardt
2007-06-20 11:07 ` Pablo Neira Ayuso
2007-06-20 11:32 ` Jan Engelhardt
2007-06-20 12:01 ` Pablo Neira Ayuso
2007-06-20 12:35 ` Jan Engelhardt
2007-06-20 12:47 ` Patrick McHardy
2007-06-20 12:56 ` Jan Engelhardt
2007-06-21 15:39 ` Pablo Neira Ayuso
2007-06-21 15:44 ` Patrick McHardy
2007-06-21 15:50 ` Pablo Neira Ayuso
2007-06-21 15:51 ` Patrick McHardy
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.