]> git.ipfire.org Git - thirdparty/xtables-addons.git/commitdiff
fuzzy: import 20050627 code base
authorJan Engelhardt <jengelh@medozas.de>
Sun, 31 Aug 2008 20:44:44 +0000 (16:44 -0400)
committerJan Engelhardt <jengelh@medozas.de>
Mon, 1 Sep 2008 19:22:16 +0000 (15:22 -0400)
extensions/Kbuild
extensions/Mbuild
extensions/libxt_fuzzy.c [new file with mode: 0644]
extensions/libxt_fuzzy.man [new file with mode: 0644]
extensions/xt_fuzzy.Kconfig [new file with mode: 0644]
extensions/xt_fuzzy.c [new file with mode: 0644]
extensions/xt_fuzzy.h [new file with mode: 0644]
mconfig

index f0e018a5693a053956c99d9625e7eafa035451c6..54c04ef2a8d9c65e26f2da399297f300cdb402dd 100644 (file)
@@ -14,6 +14,7 @@ obj-${build_SYSRQ}       += xt_SYSRQ.o
 obj-${build_TARPIT}      += xt_TARPIT.o
 obj-${build_TEE}         += xt_TEE.o
 obj-${build_condition}   += xt_condition.o
+obj-${build_fuzzy}       += xt_fuzzy.o
 obj-${build_geoip}       += xt_geoip.o
 obj-${build_ipp2p}       += xt_ipp2p.o
 obj-${build_ipset}       += ipset/
index d04473332f63772564eff1a3a31b0616221f1625..cf9e51c6401f3fc9d1006f6337656f5bb81361ed 100644 (file)
@@ -7,6 +7,7 @@ obj-${build_SYSRQ}       += libxt_SYSRQ.so
 obj-${build_TARPIT}      += libxt_TARPIT.so
 obj-${build_TEE}         += libxt_TEE.so
 obj-${build_condition}   += libxt_condition.so
+obj-${build_fuzzy}       += libxt_fuzzy.so
 obj-${build_geoip}       += libxt_geoip.so
 obj-${build_ipp2p}       += libxt_ipp2p.so
 obj-${build_portscan}    += libxt_portscan.so
diff --git a/extensions/libxt_fuzzy.c b/extensions/libxt_fuzzy.c
new file mode 100644 (file)
index 0000000..1b42329
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *     "fuzzy" match extension for iptables
+ *     Hime Aguiar e Oliveira Jr. <hime@engineer.com>, 2002 - 2003
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License;
+ *     either version 2 of the License, or any later version, as
+ *     published by the Free Software Foundation.
+ */
+#include <getopt.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xtables.h>
+#include "xt_fuzzy.h"
+
+static void fuzzy_mt_help(void)
+{
+       printf(
+"fuzzy v%s options:\n"
+"                      --lower-limit number (in packets per second)\n"
+"                      --upper-limit number\n"
+,XTABLES_VERSION);
+};
+
+static struct option fuzzy_mt_opts[] = {
+       { "lower-limit", 1 , 0 , '1' } ,
+       { "upper-limit", 1 , 0 , '2' } ,
+       { 0 }
+};
+
+/* Initialize data structures */
+static void fuzzy_mt_init(struct xt_entry_match *m)
+{
+       struct xt_fuzzy_mtinfo *info = (void *)m->data;
+
+       /*
+        * Default rates (I will improve this very soon with something based
+        * on real statistics of the running machine).
+        */
+
+       info->minimum_rate = 1000;
+       info->maximum_rate = 2000;
+}
+
+#define IPT_FUZZY_OPT_MINIMUM  0x01
+#define IPT_FUZZY_OPT_MAXIMUM  0x02
+
+static int fuzzy_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+                          const void *entry, struct xt_entry_match **match)
+{
+       struct xt_fuzzy_mtinfo *info = (void *)(*match)->data;
+
+       uint32_t num;
+
+       switch (c) {
+
+       case '1':
+                       
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,"Can't specify ! --lower-limit");
+
+               if (*flags & IPT_FUZZY_OPT_MINIMUM)
+                       exit_error(PARAMETER_PROBLEM,"Can't specify --lower-limit twice");
+       
+               if (string_to_number(optarg,1,FUZZY_MAX_RATE,&num) == -1 || num < 1)
+                       exit_error(PARAMETER_PROBLEM,"BAD --lower-limit");
+
+               info->minimum_rate = num;
+
+               *flags |= IPT_FUZZY_OPT_MINIMUM;
+               
+               break;
+
+       case '2':
+
+               if (invert)
+                       exit_error(PARAMETER_PROBLEM,"Can't specify ! --upper-limit");
+
+               if (*flags & IPT_FUZZY_OPT_MAXIMUM)
+                       exit_error(PARAMETER_PROBLEM,"Can't specify --upper-limit twice");
+
+               if (string_to_number(optarg,1,FUZZY_MAX_RATE,&num) == -1 || num < 1)
+                       exit_error(PARAMETER_PROBLEM,"BAD --upper-limit");
+
+               info->maximum_rate = num;
+
+               *flags |= IPT_FUZZY_OPT_MAXIMUM;
+
+               break;
+
+       default:
+               return 0;
+       }
+       return 1;
+}
+
+static void fuzzy_mt_check(unsigned int flags)
+{
+}
+
+static void fuzzy_mt_print(const void *ip, const struct xt_entry_match *match,
+                           int numeric)
+{
+       const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
+
+       printf(" fuzzy: lower limit = %u pps - upper limit = %u pps ",info->minimum_rate,info->maximum_rate);
+
+}
+
+/* Saves the union ipt_targinfo in parsable form to stdout. */
+static void fuzzy_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+       const struct xt_fuzzy_mtinfo *info = (const void *)match->data;
+
+       printf("--lower-limit %u ", info->minimum_rate);
+       printf("--upper-limit %u ", info->maximum_rate);
+
+}
+
+static struct xtables_match fuzzy_mt_reg = { 
+       .name          = "fuzzy",
+       .version       = XTABLES_VERSION,
+       .size          = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
+       .userspacesize = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
+       .help          = fuzzy_mt_help,
+       .init          = fuzzy_mt_init,
+       .parse         = fuzzy_mt_parse,
+       .final_check   = fuzzy_mt_check,
+       .print         = fuzzy_mt_print,
+       .save          = fuzzy_mt_save,
+       .extra_opts    = fuzzy_mt_opts,
+};
+
+static void _init(void)
+{
+       xtables_register_match(&fuzzy_mt_reg);
+}
diff --git a/extensions/libxt_fuzzy.man b/extensions/libxt_fuzzy.man
new file mode 100644 (file)
index 0000000..c2bed1e
--- /dev/null
@@ -0,0 +1,7 @@
+This module matches a rate limit based on a fuzzy logic controller (FLC).
+.TP
+\fB--lower-limit\fP \fInumber\fP
+Specifies the lower limit, in packets per second.
+.TP
+\fB--upper-limit\fP \fInumber\fP
+Specifies the upper limit, also in packets per second.
diff --git a/extensions/xt_fuzzy.Kconfig b/extensions/xt_fuzzy.Kconfig
new file mode 100644 (file)
index 0000000..7e1232e
--- /dev/null
@@ -0,0 +1,6 @@
+config NETFILTER_XT_MATCH_FUZZY
+       tristate '"fuzzy" match support'
+       depends on NETFILTER_XTABLES && NETFILTER_ADVANCED
+       ---help---
+       This extension allows you to match on packets according to a fuzzy
+       logic based law.
diff --git a/extensions/xt_fuzzy.c b/extensions/xt_fuzzy.c
new file mode 100644 (file)
index 0000000..27c6ca4
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *     This module implements a simple TSK FLC (Takagi-Sugeno-Kang Fuzzy Logic
+ *     Controller) that aims to limit, in an adaptive and flexible way, the
+ *     packet rate crossing a given stream. It serves as an initial and very
+ *     simple (but effective) example of how Fuzzy Logic techniques can be
+ *     applied to defeat DoS attacks.
+ *
+ *     As a matter of fact, Fuzzy Logic can help us to insert any "behavior"
+ *     into our code in a precise, adaptive and efficient manner.
+ *
+ *     The goal is very similar to that of "limit" match, but using techniques
+ *     of Fuzzy Control, that allow us to shape the transfer functions
+ *     precisely, avoiding over and undershoots - and stuff like that.
+ *
+ * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
+ * 2002-08-17  : Changed to eliminate floating point operations .
+ * 2002-08-23  : Coding style changes .
+ * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <net/tcp.h>
+#include <linux/netfilter/x_tables.h>
+#include "xt_fuzzy.h"
+#include "compat_xtables.h"
+
+/*
+ * Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
+ * Expressed in percentage.
+ */
+
+#define PAR_LOW                1/100
+#define PAR_HIGH       1
+
+static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
+
+MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
+MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ipt_fuzzy");
+
+static  uint8_t mf_high(uint32_t tx,uint32_t mini,uint32_t maxi)
+{
+       if (tx >= maxi) return 100;
+
+       if (tx <= mini) return 0;
+
+       return ((100 * (tx-mini)) / (maxi-mini));
+}
+
+static uint8_t mf_low(uint32_t tx,uint32_t mini,uint32_t maxi)
+{
+       if (tx <= mini) return 100;
+
+       if (tx >= maxi) return 0;
+
+       return ((100 * (maxi - tx)) / (maxi - mini));
+
+}
+
+static bool
+fuzzy_mt(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)
+{
+       /* From userspace */
+
+       struct xt_fuzzy_mtinfo *info = (void *)matchinfo;
+
+       unsigned long amount;
+       uint8_t howhigh, howlow, random_number;
+
+
+       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
+
+       info->bytes_total += skb->len;
+       ++info->packets_total;
+
+       info->present_time = jiffies;
+
+       if (info->present_time >= info->previous_time)
+               amount = info->present_time - info->previous_time;
+       else {
+               /*
+                * There was a transition: I choose to re-sample
+                * and keep the old acceptance rate...
+                */
+
+               amount = 0;
+               info->previous_time = info->present_time;
+               info->bytes_total = info->packets_total = 0;
+            };
+
+       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
+
+               info->mean_rate = (uint32_t) ((HZ * info->packets_total) \
+                                       / amount);
+
+               info->previous_time = info->present_time;
+               info->bytes_total = info->packets_total = 0;
+
+               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
+               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
+
+               info->acceptance_rate = (uint8_t) \
+                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
+
+               /*
+                * In fact, the above defuzzification would require a
+                * denominator proportional to (howhigh+howlow) but, in this
+                * particular case, that expression is constant.
+                *
+                * An imediate consequence is that it is not necessary to call
+                * both mf_high and mf_low - but to keep things understandable,
+                * I did so.
+                */
+
+       }
+
+       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
+
+
+       if (info->acceptance_rate < 100)
+       {
+               get_random_bytes((void *)(&random_number), 1);
+
+               if (random_number <= (255 * info->acceptance_rate) / 100)
+                       /*
+                        * If within the acceptance, it can pass
+                        * => do not match.
+                        */
+                       return 0;
+               else
+                       /* It cannot pass (it matches) */
+                       return 1;
+       };
+
+       /* acceptance_rate == 100 % => Everything passes ... */
+       return 0;
+
+}
+
+static bool
+fuzzy_mt_check(const char *table, const void *ip, const struct xt_match *match,
+               void *matchinfo, unsigned int hook_mask)
+{
+
+       const struct xt_fuzzy_mtinfo *info = matchinfo;
+
+       if ((info->minimum_rate < FUZZY_MIN_RATE) || (info->maximum_rate > FUZZY_MAX_RATE)
+        || (info->minimum_rate >= info->maximum_rate)) {
+               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+static struct xt_match fuzzy_mt_reg = {
+       .name       = "fuzzy",
+       .revision   = 0,
+       .family     = PF_INET,
+       .match      = fuzzy_mt,
+       .checkentry = fuzzy_mt_check,
+       .matchsize  = XT_ALIGN(sizeof(struct xt_fuzzy_mtinfo)),
+       .me         = THIS_MODULE,
+};
+
+static int __init fuzzy_mt_init(void)
+{
+       if (xt_register_match(&fuzzy_mt_reg))
+               return -EINVAL;
+
+       return 0;
+}
+
+static void __exit fuzzy_mt_exit(void)
+{
+       xt_unregister_match(&fuzzy_mt_reg);
+}
+
+module_init(fuzzy_mt_init);
+module_exit(fuzzy_mt_exit);
diff --git a/extensions/xt_fuzzy.h b/extensions/xt_fuzzy.h
new file mode 100644 (file)
index 0000000..b3ea394
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _LINUX_NETFILTER_XT_FUZZY_H
+#define _LINUX_NETFILTER_XT_FUZZY_H 1
+
+enum {
+       FUZZY_MIN_RATE = 3,
+       FUZZY_MAX_RATE = 10000000,
+};
+
+struct xt_fuzzy_mtinfo {
+       uint32_t minimum_rate;
+       uint32_t maximum_rate;
+       uint32_t packets_total;
+       uint32_t bytes_total;
+       uint32_t previous_time;
+       uint32_t present_time;
+       uint32_t mean_rate;
+       uint8_t acceptance_rate;
+};
+
+#endif /* _LINUX_NETFILTER_XT_FUZZY_H */
diff --git a/mconfig b/mconfig
index 02bc21c1aafe88a584e07325b34c82d5fb66c4a1..a86028433217a7799cdd978c7b7db8cbe98998a3 100644 (file)
--- a/mconfig
+++ b/mconfig
@@ -9,6 +9,7 @@ build_SYSRQ=m
 build_TARPIT=m
 build_TEE=m
 build_condition=m
+build_fuzzy=m
 build_geoip=m
 build_ipp2p=m
 build_ipset=m