]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.4-rc1-04-TARPIT.patch
- moving config-* fixed.
[packages/kernel.git] / 2.6.4-rc1-04-TARPIT.patch
1 --- linux/net/ipv4/netfilter/Kconfig.orig       2004-03-03 13:28:08.000000000 +0100
2 +++ linux/net/ipv4/netfilter/Kconfig    2004-03-04 03:30:19.023129800 +0100
3 @@ -539,6 +539,38 @@
4  
5           To compile it as a module, choose M here.  If unsure, say N.
6  
7 +config IP_NF_TARGET_TARPIT
8 +       tristate "TARPIT target support"
9 +       depends on IP_NF_IPTABLES
10 +       ---help---
11 +         Adds a TARPIT target to iptables, which captures and holds
12 +         incoming TCP connections using no local per-connection resources.
13 +         Connections are accepted, but immediately switched to the persist
14 +         state (0 byte window), in which the remote side stops sending data
15 +         and asks to continue every 60-240 seconds.  Attempts to close the
16 +         connection are ignored, forcing the remote side to time out the
17 +         connection in 12-24 minutes.
18 +
19 +         This offers similar functionality to LaBrea
20 +         <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
21 +         hardware or IPs.  Any TCP port that you would normally DROP or REJECT
22 +         can instead become a tarpit.
23 +
24 +         To tarpit connections to TCP port 80 destined for the current machine:
25 +
26 +           iptables -A INPUT -p tcp -m tcp --dport 80 -j TARPIT
27 +
28 +         To significantly slow down Code Red/Nimda-style scans of unused
29 +         address space, forward unused ip addresses to a Linux box not acting
30 +         as a router (e.g. "ip route 10.0.0.0 255.0.0.0 ip.of.linux.box" on a Cisco),
31 +         enable IP forwarding on the Linux box, and add:
32 +
33 +           iptables -A FORWARD -p tcp -j TARPIT
34 +           iptables -A FORWARD -j DROP
35 +
36 +         You probably don't want the conntrack module loaded while you are using
37 +         TARPIT, or you will be using resources per connection.
38 +
39  config IP_NF_TARGET_TCPMSS
40         tristate "TCPMSS target support"
41         depends on IP_NF_IPTABLES
42 --- linux/net/ipv4/netfilter/Makefile.orig      2004-03-03 13:28:08.000000000 +0100
43 +++ linux/net/ipv4/netfilter/Makefile   2004-03-04 02:29:08.944066624 +0100
44 @@ -101,6 +101,7 @@
45  obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
46  obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
47  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
48 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
49  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
50  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
51  
52 diff -uNr linux/net/ipv4/netfilter.orig/ipt_TARPIT.c linux/net/ipv4/netfilter/ipt_TARPIT.c
53 --- linux/net/ipv4/netfilter.orig/ipt_TARPIT.c  1970-01-01 01:00:00.000000000 +0100
54 +++ linux/net/ipv4/netfilter/ipt_TARPIT.c       2004-03-04 03:25:12.925663688 +0100
55 @@ -0,0 +1,290 @@
56 +/* 
57 + * Kernel module to capture and hold incoming TCP connections using 
58 + * no local per-connection resources.
59 + * 
60 + * Based on ipt_REJECT.c and offering functionality similar to 
61 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
62 + * 
63 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
64 + * 
65 + * This program is free software; you can redistribute it and/or modify
66 + * it under the terms of the GNU General Public License as published by
67 + * the Free Software Foundation; either version 2 of the License, or
68 + * (at your option) any later version.
69 + *
70 + * This program is distributed in the hope that it will be useful,
71 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
72 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
73 + * GNU General Public License for more details.
74 + *
75 + * You should have received a copy of the GNU General Public License
76 + * along with this program; if not, write to the Free Software
77 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
78 + * 
79 + * Goal:
80 + * - Allow incoming TCP connections to be established.
81 + * - Passing data should result in the connection being switched to the 
82 + *   persist state (0 byte window), in which the remote side stops sending 
83 + *   data and asks to continue every 60 seconds.
84 + * - Attempts to shut down the connection should be ignored completely, so 
85 + *   the remote side ends up having to time it out.
86 + *
87 + * This means:
88 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
89 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
90 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
91 + */
92 +
93 +#include <linux/config.h>
94 +#include <linux/module.h>
95 +#include <linux/skbuff.h>
96 +#include <linux/ip.h>
97 +#include <net/ip.h>
98 +#include <net/tcp.h>
99 +#include <net/icmp.h>
100 +struct in_device;
101 +#include <net/route.h>
102 +#include <linux/random.h>
103 +#include <linux/netfilter_ipv4/ip_tables.h>
104 +
105 +#if 0
106 +#define DEBUGP printk
107 +#else
108 +#define DEBUGP(format, args...)
109 +#endif
110 +
111 +
112 +/* Stolen from ip_finish_output2 */
113 +static int ip_direct_send(struct sk_buff *skb)
114 +{
115 +       struct dst_entry *dst = skb->dst;
116 +       struct hh_cache *hh = dst->hh;
117 +
118 +       if (hh) {    
119 +               read_lock_bh(&hh->hh_lock);
120 +               memcpy(skb->data - 16, hh->hh_data, 16);
121 +                read_unlock_bh(&hh->hh_lock);
122 +                skb_push(skb, hh->hh_len);
123 +                return hh->hh_output(skb);
124 +        } else if (dst->neighbour)
125 +                return dst->neighbour->output(skb);
126 +
127 +       if (net_ratelimit())
128 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
129 +        kfree_skb(skb);
130 +        return -EINVAL;
131 +}
132 +
133 +
134 +/* Send reply */
135 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
136 +{
137 +       struct sk_buff *nskb;
138 +       struct rtable *nrt;
139 +       struct tcphdr *otcph, *ntcph;
140 +       unsigned int otcplen;
141 +       u_int16_t tmp;
142 +       struct flowi fl = {};
143 +
144 +       /* A truncated TCP header isn't going to be useful */
145 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
146 +               return;
147 +
148 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
149 +                                  + oskb->nh.iph->ihl);
150 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
151 +
152 +       /* No replies for RST or FIN */
153 +       if (otcph->rst || otcph->fin)
154 +               return;
155 +
156 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
157 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
158 +               return;
159 +
160 +       /* Check checksum. */
161 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
162 +                        oskb->nh.iph->daddr,
163 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
164 +               return;
165 +
166 +       /* Copy skb (even if skb is about to be dropped, we can't just
167 +           clone it because there may be other things, such as tcpdump,
168 +           interested in it) */
169 +       nskb = skb_copy(oskb, GFP_ATOMIC);
170 +       if (!nskb)
171 +               return;
172 +
173 +       /* This packet will not be the same as the other: clear nf fields */
174 +       nf_conntrack_put(nskb->nfct);
175 +       nskb->nfct = NULL;
176 +       nskb->nfcache = 0;
177 +#ifdef CONFIG_NETFILTER_DEBUG
178 +       nskb->nf_debug = 0;
179 +#endif
180 +
181 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
182 +
183 +       /* Truncate to length (no data) */
184 +       ntcph->doff = sizeof(struct tcphdr)/4;
185 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
186 +       nskb->nh.iph->tot_len = htons(nskb->len);
187 +
188 +       /* Swap source and dest */
189 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
190 +       tmp = ntcph->source;
191 +       ntcph->source = ntcph->dest;
192 +       ntcph->dest = tmp;
193 +
194 +       /* Use supplied sequence number or make a new one */
195 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
196 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
197 +                                                       nskb->nh.iph->daddr, 
198 +                                                       ntcph->source, 
199 +                                                       ntcph->dest));
200 +
201 +       /* Our SYN-ACKs must have a >0 window */
202 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
203 +
204 +       ntcph->urg_ptr = 0;
205 +
206 +       /* Reset flags */
207 +       ((u_int8_t *)ntcph)[13] = 0;
208 +
209 +       if (otcph->syn && otcph->ack) {
210 +               ntcph->rst = 1;
211 +               ntcph->ack_seq = 0;
212 +       } else {
213 +               ntcph->syn = otcph->syn;
214 +               ntcph->ack = 1;
215 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
216 +       }
217 +
218 +       /* Adjust TCP checksum */
219 +       ntcph->check = 0;
220 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
221 +                                  nskb->nh.iph->saddr,
222 +                                  nskb->nh.iph->daddr,
223 +                                  csum_partial((char *)ntcph,
224 +                                               sizeof(struct tcphdr), 0));
225 +
226 +       /* Adjust IP TTL */
227 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
228 +
229 +       /* Set DF, id = 0 */
230 +       nskb->nh.iph->frag_off = htons(IP_DF);
231 +       nskb->nh.iph->id = 0;
232 +
233 +       /* Adjust IP checksum */
234 +       nskb->nh.iph->check = 0;
235 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
236 +                                          nskb->nh.iph->ihl);
237 +
238 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
239 +       fl.nl_u.ip4_u.saddr = (local ? nskb->nh.iph->saddr : 0);
240 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
241 +       fl.oif = 0;
242 +       if (ip_route_output_key(&nrt, &fl) != 0)
243 +               goto free_nskb;
244 +
245 +       dst_release(nskb->dst);
246 +       nskb->dst = &nrt->u.dst;
247 +
248 +       /* "Never happens" */
249 +       if (nskb->len > dst_pmtu(nskb->dst))
250 +               goto free_nskb;
251 +
252 +       ip_direct_send (nskb);
253 +
254 +       return;
255 +
256 + free_nskb:
257 +       kfree_skb(nskb);
258 +}
259 +
260 +
261 +static unsigned int tarpit(struct sk_buff **pskb,
262 +                          unsigned int hooknum,
263 +                          const struct net_device *in,
264 +                          const struct net_device *out,
265 +                          const void *targinfo,
266 +                          void *userinfo)
267 +{
268 +       struct sk_buff *skb = *pskb;
269 +       struct rtable *rt = (struct rtable*)skb->dst;
270 +
271 +       /* Do we have an input route cache entry? */
272 +       if (!rt)
273 +               return NF_DROP;
274 +
275 +        /* No replies to physical multicast/broadcast */
276 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
277 +               return NF_DROP;
278 +
279 +        /* Now check at the protocol level */
280 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
281 +                return NF_DROP;
282 +
283 +       /* Our naive response construction doesn't deal with IP
284 +           options, and probably shouldn't try. */
285 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
286 +               return NF_DROP;
287 +
288 +        /* We aren't interested in fragments */
289 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
290 +                return NF_DROP;
291 +
292 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
293 +
294 +       return NF_DROP;
295 +}
296 +
297 +
298 +static int check(const char *tablename,
299 +                const struct ipt_entry *e,
300 +                void *targinfo,
301 +                unsigned int targinfosize,
302 +                unsigned int hook_mask)
303 +{
304 +       /* Only allow these for input/forward packet filtering. */
305 +       if (strcmp(tablename, "filter") != 0) {
306 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
307 +               return 0;
308 +       }
309 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
310 +                           | (1 << NF_IP_FORWARD))) != 0) {
311 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
312 +               return 0;
313 +       }
314 +
315 +       /* Must specify that it's a TCP packet */
316 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
317 +               DEBUGP("TARPIT: not valid for non-tcp\n");
318 +               return 0;
319 +       }
320 +
321 +       return 1;
322 +}
323 +
324 +static struct ipt_target ipt_tarpit_reg = {
325 +       .name           = "TARPIT",
326 +       .target         = tarpit,
327 +       .checkentry     = check,
328 +       .me             = THIS_MODULE
329 +};
330 +
331 +static int __init init(void)
332 +{
333 +       if (ipt_register_target(&ipt_tarpit_reg))
334 +               return -EINVAL;
335 +       return 0;
336 +}
337 +
338 +static void __exit fini(void)
339 +{
340 +       ipt_unregister_target(&ipt_tarpit_reg);
341 +}
342 +
343 +module_init(init);
344 +module_exit(fini);
345 +MODULE_LICENSE("GPL");
This page took 0.07016 seconds and 3 git commands to generate.