Add TARPIT target (#1046)
authorFlorian Fainelli <florian@openwrt.org>
Sun, 17 Dec 2006 14:54:13 +0000 (14:54 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Sun, 17 Dec 2006 14:54:13 +0000 (14:54 +0000)
SVN-Revision: 5819

openwrt/package/iptables/Config.in
openwrt/target/linux/linux-2.4/config/brcm
openwrt/target/linux/linux-2.4/patches/generic/122-netfilter_TARPIT.patch [new file with mode: 0644]
openwrt/target/linux/netfilter.mk

index 7c5e136c70efd43632ce30ebd24aab7d4de45629..d5171c09d15d7264b43fcc6dfef7e674d073a2a4 100644 (file)
@@ -49,6 +49,7 @@ config BR2_PACKAGE_IPTABLES_MOD_EXTRA
             * libipt_physdev
             * libipt_pkttype
             * libipt_recent
+           * libipt_TARPIT
 
 config BR2_PACKAGE_IPTABLES_MOD_FILTER
        tristate "iptables-mod-filter - Iptables extension for packet content inspection"
index e5c9bb28d9dc9cc7c53fa57d094cc87241be3f31..5318be549e7af613645f356da29f1d456e047ab9 100644 (file)
@@ -392,6 +392,7 @@ CONFIG_IP_NF_MATCH_PHYSDEV=m
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
 CONFIG_IP_NF_TARGET_MIRROR=m
+CONFIG_IP_NF_TARGET_TARPIT=m
 CONFIG_IP_NF_NAT=y
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
diff --git a/openwrt/target/linux/linux-2.4/patches/generic/122-netfilter_TARPIT.patch b/openwrt/target/linux/linux-2.4/patches/generic/122-netfilter_TARPIT.patch
new file mode 100644 (file)
index 0000000..7580b5a
--- /dev/null
@@ -0,0 +1,340 @@
+diff -urN linux-2.4-brcm.orig/Documentation/Configure.help linux-2.4-brcm/Documentation/Configure.help
+--- linux-2.4-brcm.orig/Documentation/Configure.help   2006-12-08 20:40:01.000000000 +0000
++++ linux-2.4-brcm/Documentation/Configure.help        2006-12-08 21:01:59.000000000 +0000
+@@ -3025,6 +3025,21 @@
+   If you want to compile it as a module, say M here and read
+   <file:Documentation/modules.txt>.  If unsure, say `N'.
++TARPIT target support
++CONFIG_IP_NF_TARGET_TARPIT
++  Adds a TARPIT target to iptables, which captures and holds
++  incoming TCP connections using no local per-connection resources.
++  Connections are accepted, but immediately switched to the persist
++  state (0 byte window), in which the remote side stops sending data
++  and asks to continue every 60-240 seconds.  Attempts to close the
++  connection are ignored, forcing the remote side to time out the
++  connection in 12-24 minutes.
++
++  This offers similar functionality to LaBrea
++  <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
++  hardware or IPs.  Any TCP port that you would normally DROP or REJECT
++  can instead become a tarpit.
++
+ REJECT target support
+ CONFIG_IP_NF_TARGET_REJECT
+   The REJECT target allows a filtering rule to specify that an ICMP
+diff -urN linux-2.4-brcm.orig/net/ipv4/netfilter/Config.in linux-2.4-brcm/net/ipv4/netfilter/Config.in
+--- linux-2.4-brcm.orig/net/ipv4/netfilter/Config.in   2006-12-08 20:39:48.000000000 +0000
++++ linux-2.4-brcm/net/ipv4/netfilter/Config.in        2006-12-08 21:01:59.000000000 +0000
+@@ -68,6 +68,7 @@
+     dep_tristate '    REJECT target support' CONFIG_IP_NF_TARGET_REJECT $CONFIG_IP_NF_FILTER
+     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+       dep_tristate '    MIRROR target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_MIRROR $CONFIG_IP_NF_FILTER
++      dep_tristate '    TARPIT target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_TARPIT $CONFIG_IP_NF_FILTER
+     fi
+   fi
+diff -urN linux-2.4-brcm.orig/net/ipv4/netfilter/ipt_TARPIT.c linux-2.4-brcm/net/ipv4/netfilter/ipt_TARPIT.c
+--- linux-2.4-brcm.orig/net/ipv4/netfilter/ipt_TARPIT.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4-brcm/net/ipv4/netfilter/ipt_TARPIT.c     2006-12-08 21:01:58.000000000 +0000
+@@ -0,0 +1,284 @@
++/* 
++ * Kernel module to capture and hold incoming TCP connections using 
++ * no local per-connection resources.
++ * 
++ * Based on ipt_REJECT.c and offering functionality similar to 
++ * LaBrea <http://www.hackbusters.net/LaBrea/>.
++ * 
++ * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
++ * 
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ * 
++ * Goal:
++ * - Allow incoming TCP connections to be established.
++ * - Passing data should result in the connection being switched to the 
++ *   persist state (0 byte window), in which the remote side stops sending 
++ *   data and asks to continue every 60 seconds.
++ * - Attempts to shut down the connection should be ignored completely, so 
++ *   the remote side ends up having to time it out.
++ *
++ * This means:
++ * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
++ * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
++ * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <net/ip.h>
++#include <net/tcp.h>
++#include <net/icmp.h>
++struct in_device;
++#include <net/route.h>
++#include <linux/random.h>
++#include <linux/netfilter_ipv4/ip_tables.h>
++
++#if 0
++#define DEBUGP printk
++#else
++#define DEBUGP(format, args...)
++#endif
++
++
++/* Stolen from ip_finish_output2 */
++static int ip_direct_send(struct sk_buff *skb)
++{
++      struct dst_entry *dst = skb->dst;
++      struct hh_cache *hh = dst->hh;
++
++      if (hh) {    
++              read_lock_bh(&hh->hh_lock);
++              memcpy(skb->data - 16, hh->hh_data, 16);
++                read_unlock_bh(&hh->hh_lock);
++                skb_push(skb, hh->hh_len);
++                return hh->hh_output(skb);
++        } else if (dst->neighbour)
++                return dst->neighbour->output(skb);
++
++      if (net_ratelimit())
++              printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
++        kfree_skb(skb);
++        return -EINVAL;
++}
++
++
++/* Send reply */
++static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
++{
++      struct sk_buff *nskb;
++      struct rtable *nrt;
++      struct tcphdr *otcph, *ntcph;
++      unsigned int otcplen;
++      u_int16_t tmp;
++
++      /* A truncated TCP header isn't going to be useful */
++      if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
++              return;
++
++      otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
++                                  + oskb->nh.iph->ihl);
++      otcplen = oskb->len - oskb->nh.iph->ihl*4;
++
++      /* No replies for RST or FIN */
++      if (otcph->rst || otcph->fin)
++              return;
++
++      /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
++      if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
++              return;
++
++      /* Check checksum. */
++      if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
++                       oskb->nh.iph->daddr,
++                       csum_partial((char *)otcph, otcplen, 0)) != 0)
++              return;
++
++      /* Copy skb (even if skb is about to be dropped, we can't just
++           clone it because there may be other things, such as tcpdump,
++           interested in it) */
++      nskb = skb_copy(oskb, GFP_ATOMIC);
++      if (!nskb)
++              return;
++
++      /* This packet will not be the same as the other: clear nf fields */
++      nf_conntrack_put(nskb->nfct);
++      nskb->nfct = NULL;
++      nskb->nfcache = 0;
++#ifdef CONFIG_NETFILTER_DEBUG
++      nskb->nf_debug = 0;
++#endif
++
++      ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
++
++      /* Truncate to length (no data) */
++      ntcph->doff = sizeof(struct tcphdr)/4;
++      skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
++      nskb->nh.iph->tot_len = htons(nskb->len);
++
++      /* Swap source and dest */
++      nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
++      tmp = ntcph->source;
++      ntcph->source = ntcph->dest;
++      ntcph->dest = tmp;
++
++      /* Use supplied sequence number or make a new one */
++      ntcph->seq = otcph->ack ? otcph->ack_seq 
++                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
++                                                      nskb->nh.iph->daddr, 
++                                                      ntcph->source, 
++                                                      ntcph->dest));
++
++      /* Our SYN-ACKs must have a >0 window */
++      ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
++
++      ntcph->urg_ptr = 0;
++
++      /* Reset flags */
++      ((u_int8_t *)ntcph)[13] = 0;
++
++      if (otcph->syn && otcph->ack) {
++              ntcph->rst = 1;
++              ntcph->ack_seq = 0;
++      } else {
++              ntcph->syn = otcph->syn;
++              ntcph->ack = 1;
++              ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
++      }
++
++      /* Adjust TCP checksum */
++      ntcph->check = 0;
++      ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
++                                 nskb->nh.iph->saddr,
++                                 nskb->nh.iph->daddr,
++                                 csum_partial((char *)ntcph,
++                                              sizeof(struct tcphdr), 0));
++
++      /* Adjust IP TTL */
++      nskb->nh.iph->ttl = sysctl_ip_default_ttl;
++
++      /* Set DF, id = 0 */
++      nskb->nh.iph->frag_off = htons(IP_DF);
++      nskb->nh.iph->id = 0;
++
++      /* Adjust IP checksum */
++      nskb->nh.iph->check = 0;
++      nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
++                                         nskb->nh.iph->ihl);
++
++      if (ip_route_output(&nrt, nskb->nh.iph->daddr, 
++                          local ? nskb->nh.iph->saddr : 0,
++                          RT_TOS(nskb->nh.iph->tos) | RTO_CONN, 
++                          0) != 0)
++              goto free_nskb;
++
++      dst_release(nskb->dst);
++      nskb->dst = &nrt->u.dst;
++
++      /* "Never happens" */
++      if (nskb->len > nskb->dst->pmtu)
++              goto free_nskb;
++
++      ip_direct_send (nskb);
++
++      return;
++
++ free_nskb:
++      kfree_skb(nskb);
++}
++
++
++static unsigned int tarpit(struct sk_buff **pskb,
++                         unsigned int hooknum,
++                         const struct net_device *in,
++                         const struct net_device *out,
++                         const void *targinfo,
++                         void *userinfo)
++{
++      struct sk_buff *skb = *pskb;
++      struct rtable *rt = (struct rtable*)skb->dst;
++
++      /* Do we have an input route cache entry? */
++      if (!rt)
++              return NF_DROP;
++
++        /* No replies to physical multicast/broadcast */
++        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
++              return NF_DROP;
++
++        /* Now check at the protocol level */
++      if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
++                return NF_DROP;
++
++      /* Our naive response construction doesn't deal with IP
++           options, and probably shouldn't try. */
++      if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
++              return NF_DROP;
++
++        /* We aren't interested in fragments */
++      if (skb->nh.iph->frag_off & htons(IP_OFFSET))
++                return NF_DROP;
++
++      tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
++
++      return NF_DROP;
++}
++
++
++static int check(const char *tablename,
++               const struct ipt_entry *e,
++               void *targinfo,
++               unsigned int targinfosize,
++               unsigned int hook_mask)
++{
++      /* Only allow these for input/forward packet filtering. */
++      if (strcmp(tablename, "filter") != 0) {
++              DEBUGP("TARPIT: bad table %s'.\n", tablename);
++              return 0;
++      }
++      if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
++                           | (1 << NF_IP_FORWARD))) != 0) {
++              DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
++              return 0;
++      }
++
++      /* Must specify that it's a TCP packet */
++      if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
++              DEBUGP("TARPIT: not valid for non-tcp\n");
++              return 0;
++      }
++
++      return 1;
++}
++
++static struct ipt_target ipt_tarpit_reg
++= { { NULL, NULL }, "TARPIT", tarpit, check, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++      if (ipt_register_target(&ipt_tarpit_reg))
++              return -EINVAL;
++      return 0;
++}
++
++static void __exit fini(void)
++{
++      ipt_unregister_target(&ipt_tarpit_reg);
++}
++
++module_init(init);
++module_exit(fini);
++MODULE_LICENSE("GPL");
+diff -urN linux-2.4-brcm.orig/net/ipv4/netfilter/Makefile linux-2.4-brcm/net/ipv4/netfilter/Makefile
+--- linux-2.4-brcm.orig/net/ipv4/netfilter/Makefile    2006-12-08 20:39:48.000000000 +0000
++++ linux-2.4-brcm/net/ipv4/netfilter/Makefile 2006-12-08 21:01:59.000000000 +0000
+@@ -118,6 +118,7 @@
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
+ obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
+ obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o
++obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
+ obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
+ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+ obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
+Package: iptables-mod-tarpit
+Priority: optional
+Section: net
+Depends: kmod-ipt-tarpit
+Description: Iptables (IPv4) extension for tarpit
index 36820f561c8c6aa01be01727143ca81e38445999..632ea30cc49178a010155404ca9260e5457b3009 100644 (file)
@@ -17,6 +17,7 @@ IPT_EXTRA-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev
 IPT_EXTRA-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype
 IPT_EXTRA-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent
 IPT_EXTRA-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT
+IPT_EXTRA-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT
 
 IPT_FILTER-m :=
 IPT_FILTER-$(CONFIG_IP_NF_MATCH_IPP2P) += ipt_ipp2p