Ticket #6168: netfilter-connlimit.patch

File netfilter-connlimit.patch, 10.8 KB (added by arteqw@…, 8 years ago)
  • package/kernel/modules/netfilter.mk

    a b endef 
    7272 
    7373$(eval $(call KernelPackage,ipt-conntrack-extra)) 
    7474 
     75define KernelPackage/ipt-connlimit 
     76  SUBMENU:=$(NF_MENU) 
     77  TITLE:=Connection tracking connlimit 
     78  DEPENDS:= kmod-ipt-core +kmod-ipt-conntrack 
     79  FILES:=$(LINUX_DIR)/net/ipv4/netfilter/ipt_connlimit.$(LINUX_KMOD_SUFFIX) 
     80  KCONFIG:=CONFIG_IP_NF_MATCH_CONNLIMIT 
     81  AUTOLOAD:=$(call AutoLoad,49,ipt_connlimit) 
     82endef 
     83 
     84define KernelPackage/ipt-connlimit/description 
     85 Kernel modules support for a connlimit connection tracking  
     86endef 
     87 
     88$(eval $(call KernelPackage,ipt-connlimit)) 
    7589 
    7690define KernelPackage/ipt-filter 
    7791  SUBMENU:=$(NF_MENU) 
  • target/linux/generic-2.4/config-default

    a b CONFIG_IP_NF_MATCH_CONDITION=m 
    232232CONFIG_IP_NF_MATCH_CONNBYTES=m 
    233233CONFIG_IP_NF_MATCH_CONNMARK=m 
    234234CONFIG_IP_NF_MATCH_CONNTRACK=m 
     235CONFIG_IP_NF_MATCH_CONNLIMIT=m 
    235236CONFIG_IP_NF_MATCH_DSCP=m 
    236237CONFIG_IP_NF_MATCH_ECN=m 
    237238CONFIG_IP_NF_MATCH_HELPER=m 
  • new file target/linux/generic-2.4/patches/627-netfilter-connlimit.patch

    - +  
     1diff -urN linux-2.4.35.4/Documentation/Configure.help linux-2.4.35.4-patched/Documentation/Configure.help 
     2--- linux-2.4.35.4/Documentation/Configure.help 2007-11-17 18:23:15.000000000 +0100 
     3+++ linux-2.4.35.4-patched/Documentation/Configure.help 2009-11-16 15:56:18.000000000 +0100 
     4@@ -3000,6 +3000,14 @@ 
     5   If you want to compile it as a module, say M here and read 
     6   <file:Documentation/modules.txt>.  If unsure, say `N'. 
     7  
     8+Connections/IP limit match support 
     9+CONFIG_IP_NF_MATCH_CONNLIMIT 
     10+  This match allows you to restrict the number of parallel TCP 
     11+  connections to a server per client IP address (or address block). 
     12+ 
     13+  If you want to compile it as a module, say M here and read 
     14+  Documentation/modules.txt.  If unsure, say `N'. 
     15+ 
     16 Unclean match support 
     17 CONFIG_IP_NF_MATCH_UNCLEAN 
     18   Unclean packet matching matches any strange or invalid packets, by 
     19diff -urN linux-2.4.35.4/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.4.35.4-patched/include/linux/netfilter_ipv4/ipt_connlimit.h 
     20--- linux-2.4.35.4/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100 
     21+++ linux-2.4.35.4-patched/include/linux/netfilter_ipv4/ipt_connlimit.h 2009-11-16 15:56:18.000000000 +0100 
     22@@ -0,0 +1,12 @@ 
     23+#ifndef _IPT_CONNLIMIT_H 
     24+#define _IPT_CONNLIMIT_H 
     25+ 
     26+struct ipt_connlimit_data; 
     27+ 
     28+struct ipt_connlimit_info { 
     29+       int limit; 
     30+       int inverse; 
     31+       u_int32_t mask; 
     32+       struct ipt_connlimit_data *data; 
     33+}; 
     34+#endif /* _IPT_CONNLIMIT_H */ 
     35diff -urN linux-2.4.35.4/net/ipv4/netfilter/Config.in linux-2.4.35.4-patched/net/ipv4/netfilter/Config.in 
     36--- linux-2.4.35.4/net/ipv4/netfilter/Config.in 2007-11-17 18:23:15.000000000 +0100 
     37+++ linux-2.4.35.4-patched/net/ipv4/netfilter/Config.in 2009-11-16 15:56:18.000000000 +0100 
     38@@ -63,6 +64,7 @@ 
     39   fi 
     40   if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then 
     41     dep_tristate '  Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES  
     42+    dep_tristate '  Connections/IP limit match support' CONFIG_IP_NF_MATCH_CONNLIMIT $CONFIG_IP_NF_IPTABLES 
     43     dep_tristate '  Connection tracking match support' CONFIG_IP_NF_MATCH_CONNTRACK $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES  
     44        if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then 
     45          dep_tristate '  Connection mark match support' CONFIG_IP_NF_MATCH_CONNMARK $CONFIG_IP_NF_IPTABLES 
     46diff -urN linux-2.4.35.4/net/ipv4/netfilter/ipt_connlimit.c linux-2.4.35.4-patched/net/ipv4/netfilter/ipt_connlimit.c 
     47--- linux-2.4.35.4/net/ipv4/netfilter/ipt_connlimit.c   1970-01-01 01:00:00.000000000 +0100 
     48+++ linux-2.4.35.4-patched/net/ipv4/netfilter/ipt_connlimit.c   2009-11-16 15:56:18.000000000 +0100 
     49@@ -0,0 +1,222 @@ 
     50+/* 
     51+ * netfilter module to limit the number of parallel tcp 
     52+ * connections per IP address. 
     53+ *   (c) 2000 Gerd Knorr <kraxel@bytesex.org> 
     54+ *   Nov 2002: Martin Bene <martin.bene@icomedias.com>: 
     55+ *             only ignore TIME_WAIT or gone connections 
     56+ * 
     57+ * based on ... 
     58+ * 
     59+ * Kernel module to match connection tracking information. 
     60+ * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au). 
     61+ */ 
     62+#include <linux/module.h> 
     63+#include <linux/skbuff.h> 
     64+#include <linux/list.h> 
     65+#include <linux/version.h> 
     66+#include <linux/netfilter_ipv4/ip_conntrack.h> 
     67+#include <linux/netfilter_ipv4/ip_conntrack_core.h> 
     68+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h> 
     69+#include <linux/netfilter_ipv4/ip_tables.h> 
     70+#include <linux/netfilter_ipv4/ipt_connlimit.h> 
     71+ 
     72+#define DEBUG 0 
     73+ 
     74+MODULE_LICENSE("GPL"); 
     75+ 
     76+/* we'll save the tuples of all connections we care about */ 
     77+struct ipt_connlimit_conn 
     78+{ 
     79+        struct list_head list; 
     80+       struct ip_conntrack_tuple tuple; 
     81+}; 
     82+ 
     83+struct ipt_connlimit_data { 
     84+       spinlock_t lock; 
     85+       struct list_head iphash[256]; 
     86+}; 
     87+ 
     88+static inline unsigned ipt_iphash(const unsigned addr) 
     89+{ 
     90+       return ((addr ^ (addr >> 8) ^ (addr >> 16) ^ (addr >> 24)) & 0xff); 
     91+} 
     92+ 
     93+static int count_them(struct ipt_connlimit_data *data, 
     94+                     u_int32_t addr, u_int32_t mask, 
     95+                     struct ip_conntrack *ct) 
     96+{ 
     97+#if DEBUG 
     98+       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv", 
     99+                                    "fin_wait", "time_wait", "close", "close_wait", 
     100+                                    "last_ack", "listen" }; 
     101+#endif 
     102+       int addit = 1, matches = 0; 
     103+       struct ip_conntrack_tuple tuple; 
     104+       struct ip_conntrack_tuple_hash *found; 
     105+       struct ipt_connlimit_conn *conn; 
     106+       struct list_head *hash,*lh; 
     107+ 
     108+       spin_lock_bh(&data->lock); 
     109+       tuple = ct->tuplehash[0].tuple; 
     110+       hash = &data->iphash[ipt_iphash(addr & mask)]; 
     111+ 
     112+       /* check the saved connections */ 
     113+       for (lh = hash->next; lh != hash; lh = lh->next) { 
     114+               conn = list_entry(lh,struct ipt_connlimit_conn,list); 
     115+               found = ip_conntrack_find_get(&conn->tuple,ct); 
     116+               if (found != NULL && 
     117+                   0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) && 
     118+                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) { 
     119+                       /* Just to be sure we have it only once in the list. 
     120+                          We should'nt see tuples twice unless someone hooks this 
     121+                          into a table without "-p tcp --syn" */ 
     122+                       addit = 0; 
     123+               } 
     124+#if DEBUG 
     125+               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n", 
     126+                      ipt_iphash(addr & mask), 
     127+                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port), 
     128+                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port), 
     129+                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone"); 
     130+#endif 
     131+               if (NULL == found) { 
     132+                       /* this one is gone */ 
     133+                       lh = lh->prev; 
     134+                       list_del(lh->next); 
     135+                       kfree(conn); 
     136+                       continue; 
     137+               } 
     138+               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) { 
     139+                       /* we don't care about connections which are 
     140+                          closed already -> ditch it */ 
     141+                       lh = lh->prev; 
     142+                       list_del(lh->next); 
     143+                       kfree(conn); 
     144+                       nf_conntrack_put(&found->ctrack->infos[0]); 
     145+                       continue; 
     146+               } 
     147+               if ((addr & mask) == (conn->tuple.src.ip & mask)) { 
     148+                       /* same source IP address -> be counted! */ 
     149+                       matches++; 
     150+               } 
     151+               nf_conntrack_put(&found->ctrack->infos[0]); 
     152+       } 
     153+       if (addit) { 
     154+               /* save the new connection in our list */ 
     155+#if DEBUG 
     156+               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n", 
     157+                      ipt_iphash(addr & mask), 
     158+                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port), 
     159+                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port)); 
     160+#endif 
     161+               conn = kmalloc(sizeof(*conn),GFP_ATOMIC); 
     162+               if (NULL == conn) 
     163+                       return -1; 
     164+               memset(conn,0,sizeof(*conn)); 
     165+               INIT_LIST_HEAD(&conn->list); 
     166+               conn->tuple = tuple; 
     167+               list_add(&conn->list,hash); 
     168+               matches++; 
     169+       } 
     170+       spin_unlock_bh(&data->lock); 
     171+       return matches; 
     172+} 
     173+ 
     174+static int 
     175+match(const struct sk_buff *skb, 
     176+      const struct net_device *in, 
     177+      const struct net_device *out, 
     178+      const void *matchinfo, 
     179+      int offset, 
     180+      const void *hdr, 
     181+      u_int16_t datalen, 
     182+      int *hotdrop) 
     183+{ 
     184+       const struct ipt_connlimit_info *info = matchinfo; 
     185+       int connections, match; 
     186+       struct ip_conntrack *ct; 
     187+       enum ip_conntrack_info ctinfo; 
     188+ 
     189+       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); 
     190+       if (NULL == ct) { 
     191+               printk("ipt_connlimit: Oops: invalid ct state ?\n"); 
     192+               *hotdrop = 1; 
     193+               return 0; 
     194+       } 
     195+       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct); 
     196+       if (-1 == connections) { 
     197+               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n"); 
     198+               *hotdrop = 1; /* let's free some memory :-) */ 
     199+               return 0; 
     200+       } 
     201+        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit); 
     202+#if DEBUG 
     203+       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u " 
     204+              "connections=%d limit=%d match=%s\n", 
     205+              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask), 
     206+              connections, info->limit, match ? "yes" : "no"); 
     207+#endif 
     208+ 
     209+       return match; 
     210+} 
     211+ 
     212+static int check(const char *tablename, 
     213+                const struct ipt_ip *ip, 
     214+                void *matchinfo, 
     215+                unsigned int matchsize, 
     216+                unsigned int hook_mask) 
     217+{ 
     218+       struct ipt_connlimit_info *info = matchinfo; 
     219+       int i; 
     220+ 
     221+       /* verify size */ 
     222+       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info))) 
     223+               return 0; 
     224+ 
     225+       /* refuse anything but tcp */ 
     226+       if (ip->proto != IPPROTO_TCP) 
     227+               return 0; 
     228+ 
     229+       /* init private data */ 
     230+       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL); 
     231+       spin_lock_init(&(info->data->lock)); 
     232+       for (i = 0; i < 256; i++) 
     233+               INIT_LIST_HEAD(&(info->data->iphash[i])); 
     234+        
     235+       return 1; 
     236+} 
     237+ 
     238+static void destroy(void *matchinfo, unsigned int matchinfosize) 
     239+{ 
     240+       struct ipt_connlimit_info *info = matchinfo; 
     241+       struct ipt_connlimit_conn *conn; 
     242+       struct list_head *hash; 
     243+       int i; 
     244+ 
     245+       /* cleanup */ 
     246+       for (i = 0; i < 256; i++) { 
     247+               hash = &(info->data->iphash[i]); 
     248+               while (hash != hash->next) { 
     249+                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list); 
     250+                       list_del(hash->next); 
     251+                       kfree(conn); 
     252+               } 
     253+       } 
     254+       kfree(info->data); 
     255+} 
     256+ 
     257+static struct ipt_match connlimit_match 
     258+= { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE }; 
     259+ 
     260+static int __init init(void) 
     261+{ 
     262+       return ipt_register_match(&connlimit_match); 
     263+} 
     264+ 
     265+static void __exit fini(void) 
     266+{ 
     267+       ipt_unregister_match(&connlimit_match); 
     268+} 
     269+ 
     270+module_init(init); 
     271+module_exit(fini); 
     272diff -urN linux-2.4.35.4/net/ipv4/netfilter/Makefile linux-2.4.35.4-patched/net/ipv4/netfilter/Makefile 
     273--- linux-2.4.35.4/net/ipv4/netfilter/Makefile  2007-11-17 18:23:15.000000000 +0100 
     274+++ linux-2.4.35.4-patched/net/ipv4/netfilter/Makefile  2009-11-16 15:56:18.000000000 +0100 
     275@@ -117,6 +118,7 @@ 
     276  
     277 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 
     278 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o 
     279+obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o 
     280 obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o 
     281 obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o 
     282 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o