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]
> > 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 /base/ directory
in the 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
/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
-
+ *
-
+ * based on ...
-
+ * iplimit (in fact a shameless copy ;-)
-
+ * (c) 2000 Gerd Knorr
-
+ * Nov 2002: Martin Bene :
-
+ * only ignore TIME_WAIT or gone connections
-
+ *
-
+ *
-
+ * Kernel module to match connection tracking information.
-
+ * GPL (C) 1999 Rusty Russell (rusty@xxxxxxxxxxxxxxx).
-
+ */
-
+#include
-
+#include
-
+#include
-
+#include
-
+#include
-
+#include
-
+#include
-
+
-
+#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));
-
+
-
+ 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);
-
+ 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
-
Jan Du Caju (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
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
-
/* 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);
-
}
阅读(3981) | 评论(0) | 转发(0) |