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