All of lore.kernel.org
 help / color / mirror / Atom feed
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);
    }
    
    



  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.