From: "Ing. CIP Alejandro Celi "Mariategui <alex@linux.org.pe>
To: Jan Du Caju <Jan.DuCaju@kuleuven.net>
Cc: netfilter@lists.netfilter.org
Subject: RE: IPLIMIT Patch UDP
Date: 24 Feb 2003 15:41:00 -0500 [thread overview]
Message-ID: <1046119262.1237.18.camel@alex.pcprices.com.pe> (raw)
In-Reply-To: <20030221214109.GB19981@kuleuven.net>
Thank You very much, Jan and Joel, I will try with udplimit right now!!!
Alex
El vie, 21-02-2003 a las 16:41, Jan Du Caju escribió:
Hi again,
Jan Du Caju wrote:
> > Ing. CIP Alejandro Celi Mariategui wrote:
> >
> > (Sorry, but my english is very bad)
> > Hi,
> > I compile with p-o-m the server kernel with IPLIMIT Patch by Gerd
> > Knorr
> > [1]<kraxel@bytesex.org>
> > It work fine, i can limit ex: max 10 TCP connections on the server,
> > but i want to limit the UDP connections to 10 (max).
> > How I can do it?
> This week I made a updlimit patch (shameless copy of iplimit ;-)
> I will post it this afternoon/evening when I have more time (and
> a cross post to the netfilter-devel list. Maybe they like it)
In attachment you will find:
udplimit.patch
udplimit.patch.config.in
udplimit.patch.configure.help
udplimit.patch.help
udplimit.patch.makefile
put those under <patch-o-matic>/base/ directory
in the <patch-o-matic> directory you run: ./runme base
(don't forget to select udplimit ;-)
recompile your kernel (with Connections/UDP limit match support
CONFIG_IP_NF_MATCH_UDPLIMIT ;-)
Place the other file attachment (libipt_udplimit.c) in the directory
<iptables>/extensions/
in this directory you will also find the file Makefile where you add
udplimit just after iplimit
recompile iptables
Hope this helps (it works for me :-)
Greetz,
Jan.
--------------------------------------------- KULeuvenNet -----
____________________________________________________________________
diff -urN -x *~ -x [Cc]onfig.* -x Makefile vanilla-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c linux-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c
--- vanilla-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c Fri Feb 21 17:20:55 2003
+++ linux-2.4.21-pre4/net/ipv4/netfilter/ipt_udplimit.c Fri Feb 21 17:17:38 2003
@@ -0,0 +1,215 @@
+/*
+ * netfilter module to limit the number of parallel udp
+ * connections per IP address.
+ * Jan Du Caju <Jan.DuCaju@kuleuven.net>
+ *
+ * based on ...
+ * iplimit (in fact a shameless copy ;-)
+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
+ * only ignore TIME_WAIT or gone connections
+ *
+ *
+ * Kernel module to match connection tracking information.
+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_iplimit.h>
+
+#define DEBUG 0
+
+MODULE_LICENSE("GPL");
+
+/* we'll save the tuples of all connections we care about */
+struct ipt_iplimit_conn
+{
+ struct list_head list;
+ struct ip_conntrack_tuple tuple;
+};
+
+struct ipt_iplimit_data {
+ spinlock_t lock;
+ struct list_head iphash[256];
+};
+
+static int ipt_iphash(u_int32_t addr)
+{
+ int hash;
+
+ hash = addr & 0xff;
+ hash ^= (addr >> 8) & 0xff;
+ hash ^= (addr >> 16) & 0xff;
+ hash ^= (addr >> 24) & 0xff;
+ return hash;
+}
+
+static int count_them(struct ipt_iplimit_data *data,
+ u_int32_t addr, u_int32_t mask,
+ struct ip_conntrack *ct)
+{
+ int addit = 1, matches = 0;
+ struct ip_conntrack_tuple tuple;
+ struct ip_conntrack_tuple_hash *found;
+ struct ipt_iplimit_conn *conn;
+ struct list_head *hash,*lh;
+
+ spin_lock(&data->lock);
+ tuple = ct->tuplehash[0].tuple;
+ hash = &data->iphash[ipt_iphash(addr & mask)];
+
+ /* check the saved connections */
+ for (lh = hash->next; lh != hash; lh = lh->next) {
+ conn = list_entry(lh,struct ipt_iplimit_conn,list);
+ found = ip_conntrack_find_get(&conn->tuple,ct);
+ if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
+ found != NULL) {
+ addit = 0;
+ }
+#if DEBUG
+ printk("ipt_udplimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d\n",
+ ipt_iphash(addr & mask),
+ NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.udp.port),
+ NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.udp.port));
+#endif
+ if (NULL == found) {
+ /* this one is gone */
+ lh = lh->prev;
+ list_del(lh->next);
+ kfree(conn);
+ continue;
+ }
+ if ((addr & mask) == (conn->tuple.src.ip & mask)) {
+ /* same source IP address -> be counted! */
+ matches++;
+ }
+ nf_conntrack_put(&found->ctrack->infos[0]);
+ }
+ if (addit) {
+ /* save the new connection in our list */
+#if DEBUG
+ printk("ipt_udplimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
+ ipt_iphash(addr & mask),
+ NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
+ NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
+#endif
+ conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
+ if (NULL == conn)
+ return -1;
+ memset(conn,0,sizeof(*conn));
+ INIT_LIST_HEAD(&conn->list);
+ conn->tuple = tuple;
+ list_add(&conn->list,hash);
+ matches++;
+ }
+ spin_unlock(&data->lock);
+ return matches;
+}
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ const struct ipt_iplimit_info *info = matchinfo;
+ int connections, match;
+ struct ip_conntrack *ct;
+ enum ip_conntrack_info ctinfo;
+
+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
+ if (NULL == ct) {
+ printk("ipt_udplimit: Oops: invalid ct state ?\n");
+ *hotdrop = 1;
+ return 0;
+ }
+ connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
+ if (-1 == connections) {
+ printk("ipt_udplimit: Hmm, kmalloc failed :-(\n");
+ *hotdrop = 1; /* let's free some memory :-) */
+ return 0;
+ }
+ match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
+#if DEBUG
+ printk("ipt_udplimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
+ "connections=%d limit=%d match=%s\n",
+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
+ connections, info->limit, match ? "yes" : "no");
+#endif
+
+ return match;
+}
+
+static int check(const char *tablename,
+ const struct ipt_ip *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ struct ipt_iplimit_info *info = matchinfo;
+ int i;
+
+ /* verify size */
+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_iplimit_info)))
+ return 0;
+
+ /* refuse anything but udp */
+ if (ip->proto != IPPROTO_UDP)
+ return 0;
+
+ /* init private data */
+ info->data = kmalloc(sizeof(struct ipt_iplimit_data),GFP_KERNEL);
+ spin_lock_init(&(info->data->lock));
+ for (i = 0; i < 256; i++)
+ INIT_LIST_HEAD(&(info->data->iphash[i]));
+
+ return 1;
+}
+
+static void destroy(void *matchinfo, unsigned int matchinfosize)
+{
+ struct ipt_iplimit_info *info = matchinfo;
+ struct ipt_iplimit_conn *conn;
+ struct list_head *hash;
+ int i;
+
+ /* cleanup */
+ for (i = 0; i < 256; i++) {
+ hash = &(info->data->iphash[i]);
+ while (hash != hash->next) {
+ conn = list_entry(hash->next,struct ipt_iplimit_conn,list);
+ list_del(hash->next);
+ kfree(conn);
+ }
+ }
+ kfree(info->data);
+}
+
+static struct ipt_match udplimit_match
+= { { NULL, NULL }, "udplimit", &match, &check, &destroy, THIS_MODULE };
+
+static int __init init(void)
+{
+ /* NULL if ip_conntrack not a module */
+ if (ip_conntrack_module)
+ __MOD_INC_USE_COUNT(ip_conntrack_module);
+ return ipt_register_match(&udplimit_match);
+}
+
+static void __exit fini(void)
+{
+ ipt_unregister_match(&udplimit_match);
+ if (ip_conntrack_module)
+ __MOD_DEC_USE_COUNT(ip_conntrack_module);
+}
+
+module_init(init);
+module_exit(fini);
____________________________________________________________________
dep_tristate ' Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
dep_tristate ' Connections/UDP limit match support' CONFIG_IP_NF_MATCH_UDPLIMIT $CONFIG_IP_NF_IPTABLES
____________________________________________________________________
obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
obj-$(CONFIG_IP_NF_MATCH_UDPLIMIT) += ipt_udplimit.o
____________________________________________________________________
Author: Gerd Knorr <kraxel@bytesex.org>
Jan Du Caju <Jan.DuCaju@kuleuven.net> (I just made a shameless copy
of iplimit of Gerd Knorr ;-)
Status: ItWorksForMe[tm]
This adds CONFIG_IP_NF_MATCH_UDPLIMIT match allows you to restrict the
number of parallel UDP connections to a server per client IP address
(or address block).
Examples:
# allow 5 udp connections per client host
iptables -p udp -m udplimit --udplimit-above 5 -j REJECT
# you can also match the other way around:
iptables -p udp -m udplimit ! --udplimit-above 5 -j ACCEPT
# limit the nr of parallel http requests to 16 per class C sized
# network (24 bit netmask)
iptables -p udp --dport 161 -m udplimit --udplimit-above 16 \
--iplimit-mask 24 -j REJECT
____________________________________________________________________
CONFIG_IP_NF_MATCH_STATE
Connections/UDP limit match support
CONFIG_IP_NF_MATCH_UDPLIMIT
This match allows you to restrict the number of parallel UDP
connections to a server per client IP address (or address block).
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
____________________________________________________________________
/* Shared library add-on to iptables to add state tracking 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_ipv4/ipt_iplimit.h>
/* Function which prints out usage message. */
static void
help(void)
{
printf(
"udplimit v%s options:\n"
"[!] --udplimit-above n match if the number of existing udp connections is (not) above n\n"
" --udplimit-mask n group hosts using mask\n"
"\n", IPTABLES_VERSION);
}
static struct option opts[] = {
{ "udplimit-above", 1, 0, '1' },
{ "udplimit-mask", 1, 0, '2' },
{0}
};
/* Initialize the match. */
static void
init(struct ipt_entry_match *m, unsigned int *nfcache)
{
/* Can't cache this */
*nfcache |= NFC_UNKNOWN;
}
/* 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 ipt_iplimit_info *info = (struct ipt_iplimit_info*)(*match)->data;
if (0 == (*flags & 2)) {
/* set default mask unless we've already seen a mask option */
info->mask = htonl(0xFFFFFFFF);
}
switch (c) {
case '1':
check_inverse(optarg, &invert, &optind, 0);
info->limit = atoi(argv[optind-1]);
info->inverse = invert;
*flags |= 1;
break;
case '2':
info->mask = htonl(0xFFFFFFFF << (32 - atoi(argv[optind-1])));
*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 `--udplimit-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)
{
struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)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)
{
struct ipt_iplimit_info *info = (struct ipt_iplimit_info*)match->data;
printf("%s--udplimit-above %d ",info->inverse ? "! " : "",info->limit);
printf("--udplimit-mask %d ",count_bits(info->mask));
}
static struct iptables_match udplimit = {
name: "udplimit",
version: IPTABLES_VERSION,
size: IPT_ALIGN(sizeof(struct ipt_iplimit_info)),
userspacesize: offsetof(struct ipt_iplimit_info,data),
help: help,
init: init,
parse: parse,
final_check: final_check,
print: print,
save: save,
extra_opts: opts
};
void _init(void)
{
register_match(&udplimit);
}
next prev parent reply other threads:[~2003-02-24 20:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-02-21 21:41 IPLIMIT Patch UDP Jan Du Caju
2003-02-24 20:41 ` Ing. CIP Alejandro Celi Mariategui [this message]
-- strict thread matches above, loose matches on Subject: below --
2003-02-21 21:54 Jan Du Caju
2003-01-30 20:48 Looking for Log Analyzer Susan Sagan
2003-02-19 16:26 ` Hervé Eychenne
2003-02-20 23:50 ` IPLIMIT Patch UDP Ing. CIP Alejandro Celi Mariategui
2003-02-21 8:12 ` Jan Du Caju
2003-02-21 8:22 ` Joel Newkirk
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=1046119262.1237.18.camel@alex.pcprices.com.pe \
--to=alex@linux.org.pe \
--cc=Jan.DuCaju@kuleuven.net \
--cc=netfilter@lists.netfilter.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.