1 --- a/net/netfilter/Kconfig
2 +++ b/net/netfilter/Kconfig
5 To compile it as a module, choose M here. If unsure, say N.
7 +config NETFILTER_XT_TARGET_TARPIT
8 + tristate '"TARPIT" target support'
9 + depends on NETFILTER_XTABLES
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.
19 + This offers similar functionality to LaBrea
20 + <http://www.hackbusters.net/LaBrea/>, but does not require dedicated
21 + hardware or IPs. Any TCP port that you would normally DROP or REJECT
22 + can instead become a tarpit.
24 config NETFILTER_XT_TARGET_TCPMSS
25 tristate '"TCPMSS" target support'
26 depends on NETFILTER_XTABLES && (IPV6 || IPV6=n)
27 --- a/net/netfilter/Makefile
28 +++ b/net/netfilter/Makefile
30 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
31 obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
32 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
33 +obj-$(CONFIG_NETFILTER_XT_TARGET_TARPIT) += xt_TARPIT.o
34 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
35 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
36 obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
38 +++ b/net/netfilter/xt_TARPIT.c
41 + * Kernel module to capture and hold incoming TCP connections using
42 + * no local per-connection resources.
44 + * Based on ipt_REJECT.c and offering functionality similar to
45 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
47 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
49 + * This program is free software; you can redistribute it and/or modify
50 + * it under the terms of the GNU General Public License as published by
51 + * the Free Software Foundation; either version 2 of the License, or
52 + * (at your option) any later version.
54 + * This program is distributed in the hope that it will be useful,
55 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
56 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 + * GNU General Public License for more details.
59 + * You should have received a copy of the GNU General Public License
60 + * along with this program; if not, write to the Free Software
61 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
64 + * - Allow incoming TCP connections to be established.
65 + * - Passing data should result in the connection being switched to the
66 + * persist state (0 byte window), in which the remote side stops sending
67 + * data and asks to continue every 60 seconds.
68 + * - Attempts to shut down the connection should be ignored completely, so
69 + * the remote side ends up having to time it out.
72 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
73 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
74 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
77 +#include <linux/version.h>
78 +#include <linux/module.h>
79 +#include <linux/skbuff.h>
80 +#include <linux/ip.h>
83 +#include <net/icmp.h>
85 +#include <net/route.h>
86 +#include <linux/random.h>
87 +#include <linux/netfilter_ipv4/ip_tables.h>
90 +#define DEBUGP printk
92 +#define DEBUGP(format, args...)
95 +/* Stolen from ip_finish_output2 */
96 +static int ip_direct_send(struct sk_buff *skb)
98 + struct dst_entry *dst = skb->dst;
100 + if (dst->hh != NULL)
101 + return neigh_hh_output(dst->hh, skb);
102 + else if (dst->neighbour != NULL)
103 + return dst->neighbour->output(skb);
105 + if (net_ratelimit())
106 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
114 +static void tarpit_tcp(const struct sk_buff *oskb, struct rtable *ort,
115 + unsigned int local)
117 + struct sk_buff *nskb;
118 + struct rtable *nrt;
119 + struct tcphdr *otcph, *ntcph;
120 + struct flowi fl = {};
121 + unsigned int otcplen;
124 + const struct iphdr *oiph = ip_hdr(oskb);
125 + struct iphdr *niph;
127 + /* A truncated TCP header is not going to be useful */
128 + if (oskb->len < ip_hdrlen(oskb) + sizeof(struct tcphdr))
131 + otcph = (void *)oiph + ip_hdrlen(oskb);
132 + otcplen = oskb->len - ip_hdrlen(oskb);
134 + /* No replies for RST or FIN */
135 + if (otcph->rst || otcph->fin)
138 + /* No reply to !SYN,!ACK. Rate-limit replies to !SYN,ACKs */
139 + if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
142 + /* Check checksum. */
143 + if (tcp_v4_check(otcplen, oiph->saddr, oiph->daddr,
144 + csum_partial((char *)otcph, otcplen, 0)) != 0)
148 + * Copy skb (even if skb is about to be dropped, we cannot just
149 + * clone it because there may be other things, such as tcpdump,
150 + * interested in it)
152 + nskb = skb_copy(oskb, GFP_ATOMIC);
156 + niph = ip_hdr(nskb);
158 + /* This packet will not be the same as the other: clear nf fields */
159 + nf_conntrack_put(nskb->nfct);
161 +#ifdef CONFIG_NETFILTER_DEBUG
162 + nskb->nf_debug = 0;
165 + ntcph = (void *)niph + ip_hdrlen(nskb);
167 + /* Truncate to length (no data) */
168 + ntcph->doff = sizeof(struct tcphdr)/4;
169 + skb_trim(nskb, ip_hdrlen(nskb) + sizeof(struct tcphdr));
170 + niph->tot_len = htons(nskb->len);
172 + /* Swap source and dest */
173 + niph->daddr = xchg(&niph->saddr, niph->daddr);
174 + tmp = ntcph->source;
175 + ntcph->source = ntcph->dest;
178 + /* Use supplied sequence number or make a new one */
179 + ntcph->seq = otcph->ack ? otcph->ack_seq
180 + : htonl(secure_tcp_sequence_number(niph->saddr,
185 + /* Our SYN-ACKs must have a >0 window */
186 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
188 + ntcph->urg_ptr = 0;
191 + ((u_int8_t *)ntcph)[13] = 0;
193 + if (otcph->syn && otcph->ack) {
195 + ntcph->ack_seq = 0;
197 + ntcph->syn = otcph->syn;
199 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
202 + /* Adjust TCP checksum */
204 + ntcph->check = tcp_v4_check(sizeof(struct tcphdr),
207 + csum_partial((char *)ntcph,
208 + sizeof(struct tcphdr), 0));
210 + fl.nl_u.ip4_u.daddr = niph->daddr;
211 + fl.nl_u.ip4_u.saddr = local ? niph->saddr : 0;
212 + fl.nl_u.ip4_u.tos = RT_TOS(niph->tos) | RTO_CONN;
215 + if (ip_route_output_key(&init_net, &nrt, &fl))
218 + dst_release(nskb->dst);
219 + nskb->dst = &nrt->u.dst;
221 + /* Adjust IP TTL */
222 + niph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
224 + /* Set DF, id = 0 */
225 + niph->frag_off = htons(IP_DF);
228 + /* Adjust IP checksum */
230 + niph->check = ip_fast_csum((unsigned char *)niph, niph->ihl);
232 + /* "Never happens" */
233 + if (nskb->len > dst_mtu(nskb->dst))
236 + ip_direct_send(nskb);
243 +static unsigned int xt_tarpit_target(struct sk_buff *skb,
244 + const struct net_device *in,
245 + const struct net_device *out,
246 + unsigned int hooknum,
247 + const struct xt_target *target,
248 + const void *targinfo)
250 + const struct iphdr *iph = ip_hdr(skb);
251 + struct rtable *rt = (void *)skb->dst;
253 + /* Do we have an input route cache entry? */
257 + /* No replies to physical multicast/broadcast */
258 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
261 + /* Now check at the protocol level */
262 + if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
266 + * Our naive response construction does not deal with IP
267 + * options, and probably should not try.
269 + if (iph->ihl * 4 != sizeof(struct iphdr))
272 + /* We are not interested in fragments */
273 + if (iph->frag_off & htons(IP_OFFSET))
276 + tarpit_tcp(skb, rt, hooknum == NF_INET_LOCAL_IN);
280 +static bool xt_tarpit_check(const char *tablename, const void *entry,
281 + const struct xt_target *target, void *targinfo,
282 + unsigned int hook_mask)
286 + if (strcmp(tablename, "raw") == 0 && hook_mask == NF_INET_PRE_ROUTING)
288 + if (strcmp(tablename, "filter") != 0)
290 + invalid = hook_mask & ~((1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD));
294 +static struct xt_target xt_tarpit_reg = {
297 + .proto = IPPROTO_TCP,
298 + .target = xt_tarpit_target,
299 + .checkentry = xt_tarpit_check,
303 +static int __init xt_tarpit_init(void)
305 + return xt_register_target(&xt_tarpit_reg);
308 +static void __exit xt_tarpit_exit(void)
310 + xt_unregister_target(&xt_tarpit_reg);
313 +module_init(xt_tarpit_init);
314 +module_exit(xt_tarpit_exit);
315 +MODULE_DESCRIPTION("netfilter xt_TARPIT target module");
316 +MODULE_AUTHOR("Jan Engelhardt <jengelh@gmx.de>");
317 +MODULE_LICENSE("GPL");
318 +MODULE_ALIAS("ipt_TARPIT");