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