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/
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
--- /dev/null
+/*
+ * "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);
+}
--- /dev/null
+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.
--- /dev/null
+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.
--- /dev/null
+/*
+ * 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);
--- /dev/null
+#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 */
build_TARPIT=m
build_TEE=m
build_condition=m
+build_fuzzy=m
build_geoip=m
build_ipp2p=m
build_ipset=m