RE: IPLIMIT Patch UDP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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);
    }
    
    




[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux